From 13dc30868216507dbdd808d586bfc8a87e19ff83 Mon Sep 17 00:00:00 2001 From: Eugenio Parodi Date: Sun, 2 Apr 2023 23:55:22 +0100 Subject: [PATCH] Little progress in the ttkDesigner open file --- TermTk/TTkUiTools/uiloader.py | 5 +- ttkDesigner/app/designer.py | 21 ++++++- ttkDesigner/app/superobj/superlayout.py | 31 ++++++---- ttkDesigner/app/superobj/superwidget.py | 82 +++++++++++++++++++++++++ ttkDesigner/app/treeinspector.py | 2 +- ttkDesigner/app/windoweditor.py | 23 ++++++- 6 files changed, 145 insertions(+), 19 deletions(-) diff --git a/TermTk/TTkUiTools/uiloader.py b/TermTk/TTkUiTools/uiloader.py index d4f3aa91..9b045216 100644 --- a/TermTk/TTkUiTools/uiloader.py +++ b/TermTk/TTkUiTools/uiloader.py @@ -144,7 +144,10 @@ class TTkUiLoader(): TTkLog.debug(ui) - widget = _getWidget(ui['tui']) + if issubclass(globals()[ui['tui']['class']],TTkLayout): + widget = _getLayout(ui['tui']) + else: + widget = _getWidget(ui['tui']) def _getSignal(sender, name): for cc in reversed(type(sender).__mro__): diff --git a/ttkDesigner/app/designer.py b/ttkDesigner/app/designer.py index e029d581..84719adc 100644 --- a/ttkDesigner/app/designer.py +++ b/ttkDesigner/app/designer.py @@ -182,13 +182,28 @@ class TTkDesigner(TTkGridLayout): win.layout().addWidget(widget) TTkHelper.overlay(None, win, 2, 2, modal=True) + def _openFile(self, fileName): + TTkLog.info(f"Open: {fileName}") + with open(fileName) as fp: + # jj = fp.read() + # # ttk = SuperWidget.loadDict(self._windowEditor.viewport(), jj['tui']) + # wid = TTkUiLoader.loadJson(jj) + # self._windowEditor.importWidget(wid) + dd = json.load(fp) + sw = SuperWidget.loadDict(self._windowEditor.viewport(), dd['tui']) + self._windowEditor.importSuperWidget(sw) + @pyTTkSlot() def open(self): - pass + # self._openFile('tmp/pippo.003.json') + # return + filePicker = TTkFileDialogPicker(pos = (3,3), size=(75,24), caption="Open", path=".", fileMode=TTkK.FileMode.AnyFile ,filter="Json Files (*.json);;All Files (*)") + filePicker.pathPicked.connect(self._openFile) + TTkHelper.overlay(None, filePicker, 5, 5, True) @pyTTkSlot() def save(self): - pass + return self.saveAs() def _saveToFile(self, fileName): TTkLog.info(f"Saving to: {fileName}") @@ -219,6 +234,6 @@ class TTkDesigner(TTkGridLayout): TTkHelper.overlay(None, messageBox, 5, 5, True) else: self._saveToFile(fileName) - filePicker = TTkFileDialogPicker(pos = (3,3), size=(75,24), caption="Pick Something", path=".", fileMode=TTkK.FileMode.AnyFile ,filter="All Files (*);;Python Files (*.py);;Bash scripts (*.sh);;Markdown Files (*.md)") + filePicker = TTkFileDialogPicker(pos = (3,3), size=(75,24), caption="Save As...", path=".", fileMode=TTkK.FileMode.AnyFile ,filter="All Files (*);;Python Files (*.json)") filePicker.pathPicked.connect(_approveFile) TTkHelper.overlay(None, filePicker, 5, 5, True) diff --git a/ttkDesigner/app/superobj/superlayout.py b/ttkDesigner/app/superobj/superlayout.py index 72c6d62d..d0bbb821 100644 --- a/ttkDesigner/app/superobj/superlayout.py +++ b/ttkDesigner/app/superobj/superlayout.py @@ -72,7 +72,7 @@ class SuperLayout(ttk.TTkWidget): children.append(w.widget().dumpDict()|layoutItemParams) ret = {'class': self.layout().__class__.__name__, # 'params' : SuperObject.dumpParams(self._lay), - 'params' : SuperObject.dumpParams(self.layout()), + 'params' : SuperObject.dumpParams(self.layout())|{'Geometry':self.geometry()}, 'children':children} return ret @@ -96,7 +96,7 @@ class SuperLayout(ttk.TTkWidget): def mouseReleaseEvent(self, evt) -> bool: if self._superRootWidget or not self._selectable: return False self.pushSuperControlWidget() - # self.thingSelected.emit(self._lay,self) + self.thingSelected.emit(self._lay,self) return True def mouseDragEvent(self, evt) -> bool: @@ -117,6 +117,20 @@ class SuperLayout(ttk.TTkWidget): def superChild(self): return self._lay + @staticmethod + def slFromLayout(layout: ttk.TTkLayout, *args, **kwargs): + if 'lay' not in kwargs: + kwargs |= {'lay':layout} + if issubclass(type(layout),ttk.TTkVBoxLayout): + sl = so.SuperLayoutVBox(*args, **kwargs) + elif issubclass(type(layout),ttk.TTkHBoxLayout): + sl = so.SuperLayoutHBox(*args, **kwargs) + elif issubclass(type(layout),ttk.TTkGridLayout): + sl = so.SuperLayoutGrid(*args, **kwargs) + else: + sl = so.SuperLayout( *args, **kwargs) + return sl + def addSuperWidget(self, sw): self.layout().addWidget(sw) @@ -147,17 +161,10 @@ class SuperLayout(ttk.TTkWidget): if issubclass(type(data),ttk.TTkLayout): _,__,w,h = data.geometry() x,y = evt.x-hsx, evt.y-hsy - lay = ttk.TTkLayout() - if issubclass(type(data),ttk.TTkVBoxLayout): - sl = so.SuperLayoutVBox(pos=(x,y), size=(w,h), lay=lay, weModified=self.weModified, thingSelected=self.thingSelected, selectable=True) - elif issubclass(type(data),ttk.TTkHBoxLayout): - sl = so.SuperLayoutHBox(pos=(x,y), size=(w,h), lay=lay, weModified=self.weModified, thingSelected=self.thingSelected, selectable=True) - elif issubclass(type(data),ttk.TTkGridLayout): - sl = so.SuperLayoutGrid(pos=(x,y), size=(w,h), lay=lay, weModified=self.weModified, thingSelected=self.thingSelected, selectable=True) - else: - sl = so.SuperLayout( pos=(x,y), size=(w,h), lay=lay, weModified=self.weModified, thingSelected=self.thingSelected, selectable=True) + lay = ttk.TTkLayout(pos=(x,y), size=(w,h)) + sl = SuperLayout.slFromLayout(layout=data, lay=lay, pos=(x,y), size=(w,h), weModified=self.weModified, thingSelected=self.thingSelected, selectable=True) self.addSuperWidget(sl) - self._lay.addItem(data) + self._lay.addItem(lay) elif issubclass(type(data), so.SuperLayout): sl = data self.addSuperWidget(sl) diff --git a/ttkDesigner/app/superobj/superwidget.py b/ttkDesigner/app/superobj/superwidget.py index 54c38fb5..bd8829e0 100644 --- a/ttkDesigner/app/superobj/superwidget.py +++ b/ttkDesigner/app/superobj/superwidget.py @@ -73,6 +73,85 @@ class SuperWidget(ttk.TTkWidget): } return ret + @staticmethod + def swFromWidget(wid, *args, **kwargs): + # layout = wid.layout() + #newLayout = ttk.TTkLayout() + ## copy layout compatible properties + #for att in newLayout.__slots__: + # if hasattr(layout,att): + # setattr(newLayout,att,getattr(layout,att)) + #wid.setLayout(newLayout) + + #if issubclass(type(data),ttk.TTkVBoxLayout): + # sl = so.SuperLayoutVBox(pos=(x,y), size=(w,h), lay=lay, weModified=self.weModified, thingSelected=self.thingSelected, selectable=True) + #elif issubclass(type(data),ttk.TTkHBoxLayout): + # sl = so.SuperLayoutHBox(pos=(x,y), size=(w,h), lay=lay, weModified=self.weModified, thingSelected=self.thingSelected, selectable=True) + #elif issubclass(type(data),ttk.TTkGridLayout): + # sl = so.SuperLayoutGrid(pos=(x,y), size=(w,h), lay=lay, weModified=self.weModified, thingSelected=self.thingSelected, selectable=True) + #else: + # sl = so.SuperLayout( pos=(x,y), size=(w,h), lay=lay, weModified=self.weModified, thingSelected=self.thingSelected, selectable=True) + + layout = wid.layout() + sw = so.SuperWidget(wid=wid, *args, **kwargs) + sw.changeSuperLayout(type(layout)) + for ch in layout.children(): + x,y,w,h = ch.geometry() + if ch.layoutItemType == ttk.TTkK.WidgetItem: + sch = so.SuperWidget.swFromWidget(ch.widget(), *args, **(kwargs|{'pos':(x,y),'size':(w,h)})) + else: + sch = so.SuperLayout.slFromLayout(ch, *args, **(kwargs|{'pos':(x,y),'size':(w,h),'selectable':True})) + if issubclass(type(layout),ttk.TTkGridLayout): + sw._superLayout.layout().addWidget(sch,ch._row,ch._col,ch._rowspan,ch._colspan) + else: + sw._superLayout.layout().addWidget(sch) + return sw + + @staticmethod + def loadDict(parent, widProp): + ttkClass = getattr(ttk,widProp['class']) + if issubclass(ttkClass,ttk.TTkLayout): + demiProp = { + 'version':'1.0.0', + 'tui':{ + 'class' : widProp['class'], + 'params' : widProp['params'], + 'children' : [] + }, + 'connections':[] + } + layout = ttk.TTkUiLoader.loadDict(demiProp) + x,y,w,h = layout.geometry() + sl = sup = so.SuperLayout.slFromLayout(layout=layout, lay=ttk.TTkLayout(), pos=(x,y), size=(w,h), weModified=parent.weModified, thingSelected=parent.thingSelected, selectable=True) + children = widProp['children'] + else: + demiProp = { + 'version':'1.0.0', + 'tui':{ + 'class' : widProp['class'], + 'params' : widProp['params']|{'Layout':'TTkLayout'}, + 'layout': { + 'class' : 'TTkLayout', + 'params' : widProp['layout']['params'], + 'children' : [] + } + }, + 'connections':[] + } + wid = ttk.TTkUiLoader.loadDict(demiProp) + sup = so.SuperWidget(wid=wid, pos=wid.pos(), weModified=parent.weModified, thingSelected=parent.thingSelected) + sup.changeSuperLayout(getattr(ttk,widProp['layout']['class'])) + sl = sup._superLayout + children = widProp['layout']['children'] + + for ch in children: + sch = SuperWidget.loadDict(parent, ch) + if issubclass(type(sl),so.SuperLayoutGrid): + sl.layout().addWidget(sch,ch['row'],ch['col'],ch['rowspan'],ch['colspan']) + else: + sl.layout().addWidget(sch) + return sup + def changeSuperLayout(self, layout): sl = self._superLayout self.layout().removeWidget(sl) @@ -99,6 +178,9 @@ class SuperWidget(ttk.TTkWidget): def mousePressEvent(self, evt) -> bool: return True + def makeRootWidget(self): + self._superRootWidget = True + def pushSuperControlWidget(self): if self._superRootWidget: return False scw = so.SuperControlWidget(self) diff --git a/ttkDesigner/app/treeinspector.py b/ttkDesigner/app/treeinspector.py index 6c724e37..8b59e507 100644 --- a/ttkDesigner/app/treeinspector.py +++ b/ttkDesigner/app/treeinspector.py @@ -97,7 +97,7 @@ class TreeInspector(ttk.TTkGridLayout): if issubclass(type(superThing), SuperWidget): thing = thing._wid elif issubclass(type(superThing), SuperLayout): - thing = thing.layout() + thing = thing._lay expanded = True # ttk.TTkHelper.isParent(widSelected,thing) if widSelected else False if issubclass(type(superThing), SuperWidget): top = _TTkTomTreeWidgetItem([ diff --git a/ttkDesigner/app/windoweditor.py b/ttkDesigner/app/windoweditor.py index 7cbff6e7..fce4f607 100644 --- a/ttkDesigner/app/windoweditor.py +++ b/ttkDesigner/app/windoweditor.py @@ -34,6 +34,20 @@ class WindowEditorView(ttk.TTkAbstractScrollView): self._ttk = SuperWidget(wid=ttk.TTkWidget(name = 'TTk'), weModified=self.weModified, thingSelected=self.thingSelected, pos=(4,2), size=(self.width()-8,self.height()-4), superRootWidget=True) self.layout().addWidget(self._ttk) + def importWidget(self, wid): + if self._ttk: + self.layout().removeWidget(self._ttk) + self._ttk = SuperWidget.swFromWidget(wid=wid, weModified=self.weModified, thingSelected=self.thingSelected, pos=(4,2), size=(self.width()-8,self.height()-4)) + self._ttk.makeRootWidget() + self.layout().addWidget(self._ttk) + + def importSuperWidget(self, sw): + if self._ttk: + self.layout().removeWidget(self._ttk) + self._ttk = sw + self._ttk.makeRootWidget() + self.layout().addWidget(self._ttk) + def getTTk(self): return self._ttk @@ -61,8 +75,13 @@ class WindowEditorView(ttk.TTkAbstractScrollView): self._canvas.fill(pos=(0,0),size=(w,h), char="╳", color=ttk.TTkColor.fg("#444400")+ttk.TTkColor.bg("#000044")) class WindowEditor(ttk.TTkAbstractScrollArea): + __slots__ = ('getTTk', 'dumpDict', 'importWidget', 'importSuperWidget') def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setViewport(wev := WindowEditorView()) - self.getTTk = wev.getTTk - self.dumpDict = wev.dumpDict + wev.importWidget(ttk.TTkWidget(name = 'TTk')) + # Forward Methods + self.getTTk = wev.getTTk + self.dumpDict = wev.dumpDict + self.importWidget = wev.importWidget + self.importSuperWidget = wev.importSuperWidget \ No newline at end of file