From fbd30db6d8212a02f11465ec4bffba70de0d572a Mon Sep 17 00:00:00 2001 From: azagoruyko Date: Sun, 22 Sep 2024 12:13:20 +0200 Subject: [PATCH] feat(widgets): add compound widget fix(ui): skip connections menu for empty named attributes --- __init__.py | 20 ++++---- widgets.py | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 11 deletions(-) diff --git a/__init__.py b/__init__.py index ff831a1..35c5756 100644 --- a/__init__.py +++ b/__init__.py @@ -83,8 +83,9 @@ def executor(cmd, env=None): print("Error: "+str(e)) self.mainWindow.showLog() else: - self.updateWidgets() - self.updateWidgetStyles() + if cmd: # in case command is specified, no command can be used for obtaining completions + self.updateWidgets() + self.updateWidgetStyles() return localEnv for idx, a in enumerate(attributes): @@ -114,7 +115,7 @@ def connectionMenu(self, menu, module, attrWidgetIndex, path="/"): subMenu = QMenu(module.name()) for a in module.attributes(): - if a.template() == attr.template(): + if a.template() == attr.template() and a.name(): # skip empty names as well subMenu.addAction(a.name(), Callback(self.connectAttr, path+module.name()+"/"+a.name(), attrWidgetIndex)) for ch in module.children(): @@ -129,18 +130,15 @@ def nameContextMenuEvent(self, event, attrWidgetIndex): menu = QMenu(self) if self.moduleItem and self.moduleItem.parent(): - makeConnectionMenu = QMenu("Make connection") + makeConnectionMenu = menu.addMenu("Make connection") + for a in self.moduleItem.module.parent().attributes(): - if a.template() == attr.template(): + if a.template() == attr.template() and a.name(): # skip empty names as well makeConnectionMenu.addAction(a.name(), Callback(self.connectAttr, "/"+a.name(), attrWidgetIndex)) for ch in self.moduleItem.module.parent().children(): - if ch is self.moduleItem.module: - continue - - self.connectionMenu(makeConnectionMenu, ch, attrWidgetIndex) - - menu.addMenu(makeConnectionMenu) + if ch is not self.moduleItem.module: + self.connectionMenu(makeConnectionMenu, ch, attrWidgetIndex) if attr.connect(): menu.addAction("Break connection", Callback(self.disconnectAttr, attrWidgetIndex)) diff --git a/widgets.py b/widgets.py index 7668bea..a0ad2b4 100644 --- a/widgets.py +++ b/widgets.py @@ -1562,11 +1562,152 @@ def setJsonData(self, value): w.loadFromJsonList(value["data"]) w.setReadOnly(value["readonly"]) +class EditCompountWidgetsDialog(QDialog): + saved = Signal(list) # [(template, data), ...] + + def __init__(self, compoundWidget, **kwargs): + super().__init__(**kwargs) + + self.compoundWidget = compoundWidget + + self.setWindowTitle("Edit widgets") + self.setGeometry(100, 100, 300, 400) + + layout = QVBoxLayout() + self.setLayout(layout) + + self.listWidget = QListWidget() + self.listWidget.setDragEnabled(True) + self.listWidget.setDragDropMode(QAbstractItemView.InternalMove) + self.listWidget.contextMenuEvent = self.listContextMenuEvent + self.listWidget.setDropIndicatorShown(True) + self.listWidget.setIconSize(QSize(64, 64)) + + for w in compoundWidget.getWidgets(): + self.listWidget.addItem(self.itemFromWidget(w)) + + saveBtn = QPushButton("Save") + saveBtn.clicked.connect(self.save) + + layout.addWidget(self.listWidget) + layout.addWidget(saveBtn) + + centerWindow(self) + + def listContextMenuEvent(self, event): + menu = QMenu(self) + + addMenu = menu.addMenu("Add") + for template in TemplateWidgets: + w = TemplateWidgets[template]() + w.setJsonData(w.getDefaultData()) + w.template = template + addMenu.addAction(template, Callback(self.listWidget.addItem, self.itemFromWidget(w))) + + menu.addAction("Remove", lambda: self.listWidget.takeItem(self.listWidget.currentRow())) + menu.addAction("Clear", self.listWidget.clear) + menu.popup(event.globalPos()) + + def itemFromWidget(self, w): + item = QListWidgetItem() + item.setIcon(QIcon(QPixmap.grabWidget(w))) + item.setText(w.template) + item.setData(Qt.UserRole, w.getJsonData()) + return item + + def save(self): + widgetsData = [] + for i in range(self.listWidget.count()): + item = self.listWidget.item(i) + data = item.data(Qt.UserRole) + template = item.text() + widgetsData.append((template, data)) + + self.saved.emit(widgetsData) + self.accept() + +class CompoundTemplateWidget(TemplateWidget): + def __init__(self, **kwargs): + super().__init__(**kwargs) + + layout = QHBoxLayout() + self.setLayout(layout) + layout.setContentsMargins(QMargins()) + + def contextMenuEvent(self, event): + menu = QMenu(self) + menu.addAction("Edit widgets", self.editWidgets) + menu.popup(event.globalPos()) + + def editWidgets(self): + def saveWidgets(widgetsData): + clearLayout(self.layout()) + + templates, widgets, values = [], [], [] + for template, d in widgetsData: + templates.append(template) + widgets.append(d) + values.append(d[d["default"]]) + + self.setJsonData({"templates": templates, "widgets": widgets, "values": values, "default": "values"}) + self.somethingChanged.emit() + + dlg = EditCompountWidgetsDialog(self) + dlg.saved.connect(saveWidgets) + dlg.exec_() + + def getWidgets(self): + layout = self.layout() + widgets = [] + for i in range(layout.count()): + w = layout.itemAt(i).widget() + if w: + widgets.append(w) + return widgets + + def getDefaultData(self): + d1 = ListBoxTemplateWidget().getDefaultData() + d2 = ButtonTemplateWidget().getDefaultData() + return {"widgets": [d1, d2], "values": [d1[d1["default"]], d2[d2["default"]]], "templates":["listBox", "button"], "default": "values"} + + def getJsonData(self): + values, widgets, templates = [], [], [] + for w in self.getWidgets(): + d = w.getJsonData() + templates.append(w.template) + values.append(d[d["default"]]) + widgets.append(d) + return {"templates": templates, "widgets": widgets, "values": values, "default": "values"} + + def setJsonData(self, value): + layout = self.layout() + + widgets = value["widgets"] + templates = value["templates"] + values = value["values"] + + clearLayout(layout) + for i in range(len(widgets)): + w = TemplateWidgets[templates[i]](executor=self.executor) + w.template = templates[i] + + d = dict(widgets[i]) + d[d["default"]] = values[i] + w.setJsonData(d) + + w.somethingChanged.connect(self.somethingChanged.emit) + + layout.addWidget(w, alignment=Qt.AlignTop) + layout.addSpacing(5) + + layout.addStretch() + TemplateWidgets = { "button": ButtonTemplateWidget, "checkBox": CheckBoxTemplateWidget, "comboBox": ComboBoxTemplateWidget, "curve": CurveTemplateWidget, + "compound": CompoundTemplateWidget, "json": JsonTemplateWidget, "label": LabelTemplateWidget, "lineEdit": LineEditTemplateWidget,