diff --git a/multiplexers/workbench/.gitignore b/multiplexers/workbench/.gitignore new file mode 100644 index 00000000..63378e5d --- /dev/null +++ b/multiplexers/workbench/.gitignore @@ -0,0 +1 @@ +dontsavethisfile.txt \ No newline at end of file diff --git a/tests/timeit/24.socket.01.client.py b/tests/timeit/24.socket.01.client.py index 517d6906..3c82adc6 100755 --- a/tests/timeit/24.socket.01.client.py +++ b/tests/timeit/24.socket.01.client.py @@ -37,7 +37,6 @@ def test1(): sock.sendall(bytes(data + "\n", "utf-8")) received = str(sock.recv(1024), "utf-8") return len(received) -https://github.com/ceccopierangiolieugenio/pyTermTk/issues/210 a = {} diff --git a/ttkDesigner/app/designer.py b/ttkDesigner/app/designer.py index f9b9fc36..192545da 100644 --- a/ttkDesigner/app/designer.py +++ b/ttkDesigner/app/designer.py @@ -23,25 +23,22 @@ import os import json -from TermTk import TTk, TTkK, TTkLog, TTkCfg, TTkColor, TTkTheme, TTkTerm, TTkHelper +from TermTk import TTkK, TTkLog, TTkColor, TTkHelper, TTkShortcut from TermTk import TTkString -from TermTk import TTkColorGradient from TermTk import pyTTkSlot, pyTTkSignal from TermTk import TTkWidget, TTkFrame, TTkButton, TTkLabel, TTkMenuButton from TermTk import TTkTabWidget -from TermTk import TTkAbstractScrollArea, TTkAbstractScrollView, TTkScrollArea from TermTk import TTkFileDialogPicker, TTkMessageBox -from TermTk import TTkFileTree, TTkTextEdit -from TermTk import TTkLayout, TTkGridLayout, TTkVBoxLayout, TTkHBoxLayout +from TermTk import TTkGridLayout, TTkVBoxLayout, TTkHBoxLayout from TermTk import TTkSplitter from TermTk import TTkLogViewer from TermTk import TTkUiLoader, TTkUtil from .cfg import * from .about import * -from .widgetbox import DragDesignItem, WidgetBox, WidgetBoxScrollArea +from .widgetbox import WidgetBoxScrollArea from .windoweditor import WindowEditor from .treeinspector import TreeInspector from .propertyeditor import PropertyEditor @@ -51,6 +48,8 @@ from .superobj import SuperWidget, SuperWidgetFrame +import pickle + # # Mimic the QT Designer layout # @@ -78,11 +77,16 @@ # class TTkDesigner(TTkGridLayout): - __slots__ = ('_pippo', '_main', '_windowEditor', '_toolBar', '_fileNameLabel', '_sigslotEditor', '_treeInspector', '_fileName', '_currentPath', '_notepad', + __slots__ = ('_main', '_toolBar', '_fileNameLabel', + '_sigslotEditor', '_treeInspector', '_windowEditor', '_notepad', + '_fileName', '_currentPath', + '_snapshot', '_snapId', # Signals 'weModified', 'thingSelected', 'widgetNameChanged' ) def __init__(self, fileName=None, *args, **kwargs): + self._snapshot = [] + self._snapId = -1 self._fileName = "untitled.tui.json" self._currentPath = self._currentPath = os.path.abspath('.') @@ -131,22 +135,26 @@ def __init__(self, fileName=None, *args, **kwargs): self.thingSelected.connect(propertyEditor.setDetail) self.weModified.connect(self._treeInspector.refresh) + self.weModified.connect(self._takeSnapshot) fileMenu = topMenuFrame.newMenubarTop().addMenu("&File") - fileMenu.addMenu("New").menuButtonClicked.connect(self.new) - fileMenu.addMenu("Open").menuButtonClicked.connect(self.open) - fileMenu.addMenu("Save").menuButtonClicked.connect(self.save) - fileMenu.addMenu("Save As...").menuButtonClicked.connect(self.saveAs) + fileMenu.addMenu("&New").menuButtonClicked.connect(self.new) + fileMenu.addMenu("&Open").menuButtonClicked.connect(self.open) + fileMenu.addMenu("&Save").menuButtonClicked.connect(self.save) + fileMenu.addMenu("Save &As...").menuButtonClicked.connect(self.saveAs) fileMenu.addSpacer() - fileMenu.addMenu("Import 🎁").menuButtonClicked.connect(self.importDictWin) - fileMenu.addMenu("Export 📦").menuButtonClicked.connect(self.quickExport) + fileMenu.addMenu("&Import 🎁").menuButtonClicked.connect(self.importDictWin) + fileMenu.addMenu("&Export 📦").menuButtonClicked.connect(self.quickExport) fileMenu.addSpacer() - fileMenu.addMenu("Exit").menuButtonClicked.connect(TTkHelper.quit) + fileMenu.addMenu("E&xit").menuButtonClicked.connect(TTkHelper.quit) - extraMenu = topMenuFrame.newMenubarTop().addMenu("E&xtra") - extraMenu.addMenu("Scratchpad").menuButtonClicked.connect(self.scratchpad) + extraMenu = topMenuFrame.newMenubarTop().addMenu("E&dit") + extraMenu.addMenu("&Undo (CTRL+Z)").menuButtonClicked.connect(self.undo) + extraMenu.addMenu("&Redo (CTRL+Y)").menuButtonClicked.connect(self.redo) + extraMenu.addSpacer() + extraMenu.addMenu("&Scratchpad 📝").menuButtonClicked.connect(self.scratchpad) extraMenu.addSpacer() - extraMenu.addMenu("Preview...").menuButtonClicked.connect(self.preview) + extraMenu.addMenu("&Preview...").menuButtonClicked.connect(self.preview) def _showAbout(btn): TTkHelper.overlay(None, About(), 30,10) @@ -176,9 +184,72 @@ def _showAboutTTk(btn): self._toolBar.addWidget(self._fileNameLabel) + TTkShortcut(TTkK.CTRL | TTkK.Key_Z).activated.connect(self.undo) + TTkShortcut(TTkK.CTRL | TTkK.Key_Y).activated.connect(self.redo) + self._takeSnapshot() + if fileName: self._openFile(fileName) + # Snapshot Logic: + # _snapshots = [ s0 , s1 , s2 , s3 , s4 , s5 , s6 ] + # _snapId = 3 ^ + # + # Undo: + # _snapId-- = 2 ^ = s2 + # load s2 + # + # Redo: + # _snapId++ = 4 ^ = s4 + # load s4 + # + # Take Snapshot: + # Remove the forward Snapshots: + # _snapshots = [ s0 , s1 , s2 , s3 ] + # Append The new one and update snapId + # _snapshots = [ s0 , s1 , s2 , s3 , s4+ ] + # _snapId++ = 4 + + @pyTTkSlot() + def _takeSnapshot(self): + tui = self._windowEditor.dumpDict() + connections = self._sigslotEditor.dumpDict() + data = { + 'version':'2.0.0', + 'tui':tui, + 'connections':connections} + TTkLog.debug(f"{len(pickle.dumps(data))=} {len(self._snapshot)=}") + if ( self._snapshot and + 0 <= self._snapId < len(self._snapshot) and + data == self._snapshot[self._snapId]): return + self._snapshot = self._snapshot[:self._snapId+1]+[data] + self._snapId = len(self._snapshot)-1 + + def _loadSnapshot(self): + self.weModified.disconnect(self._takeSnapshot) + data = self._snapshot[self._snapId] + sw = SuperWidget.loadDict(self, self._windowEditor.viewport(), data['tui']) + self._windowEditor.importSuperWidget(sw) + self._sigslotEditor.importConnections(data['connections']) + self._treeInspector.refresh() + self.weModified.connect(self._takeSnapshot) + + @pyTTkSlot() + def undo(self): + TTkLog.debug(f"Undo: {len(self._snapshot)=}") + if not self._snapshot: return + if self._snapId <= 0: return + self._snapId -= 1 + self._loadSnapshot() + + @pyTTkSlot() + def redo(self): + TTkLog.debug(f"Undo: {len(self._snapshot)=}") + if not self._snapshot: return + if self._snapId >= len(self._snapshot)-1: return + self._snapId += 1 + self._loadSnapshot() + def getWidgets(self): widgets = set() def _getMenu(menu): @@ -237,7 +308,7 @@ def quickExport(self): @pyTTkSlot() def scratchpad(self): win = TTkWindow( - title="Mr Scratchpad", + title="Mr Scratchpad 📝", size=(80,30), layout=self._notepad, flags=TTkK.WindowFlag.WindowMaximizeButtonHint|TTkK.WindowFlag.WindowCloseButtonHint) diff --git a/ttkDesigner/app/superobj/supercontrol.py b/ttkDesigner/app/superobj/supercontrol.py index 4c696c31..b25c31e7 100644 --- a/ttkDesigner/app/superobj/supercontrol.py +++ b/ttkDesigner/app/superobj/supercontrol.py @@ -88,14 +88,16 @@ def keyEvent(self, evt): return True bkPos = self.pos() x,y = 0,0 - if evt.key == ttk.TTkK.Key_Up: y=-1 - elif evt.key == ttk.TTkK.Key_Down: y=1 + if evt.key == ttk.TTkK.Key_Up: y=-1 + elif evt.key == ttk.TTkK.Key_Down: y= 1 elif evt.key == ttk.TTkK.Key_Left: x=-1 - elif evt.key == ttk.TTkK.Key_Right: x=1 + elif evt.key == ttk.TTkK.Key_Right: x= 1 + else: return super().keyEvent(evt) if any((x,y)): self.move(bkPos[0]+x, bkPos[1]+y) self._alignWidToPos(bkPos) - return True + return True + return super().keyEvent(evt) def paintEvent(self, canvas): w,h = self.size()