From 5511d2917c02c738065efbf3e2030334fba10ac2 Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Thu, 23 Aug 2018 12:45:29 -0700 Subject: [PATCH] Basic property editor framework --- src/Mod/Path/Gui/Resources/panels/SetupOp.ui | 12 ++- src/Mod/Path/PathScripts/PathSetupSheet.py | 4 + src/Mod/Path/PathScripts/PathSetupSheetGui.py | 81 +++++++++++++++++++ .../PathScripts/PathSetupSheetOpPrototype.py | 31 +++++-- 4 files changed, 122 insertions(+), 6 deletions(-) diff --git a/src/Mod/Path/Gui/Resources/panels/SetupOp.ui b/src/Mod/Path/Gui/Resources/panels/SetupOp.ui index eae56ff6e2..61c5b8e6f1 100644 --- a/src/Mod/Path/Gui/Resources/panels/SetupOp.ui +++ b/src/Mod/Path/Gui/Resources/panels/SetupOp.ui @@ -15,7 +15,17 @@ - + + + true + + + true + + + false + + diff --git a/src/Mod/Path/PathScripts/PathSetupSheet.py b/src/Mod/Path/PathScripts/PathSetupSheet.py index 7ec476313f..5937e3dddc 100644 --- a/src/Mod/Path/PathScripts/PathSetupSheet.py +++ b/src/Mod/Path/PathScripts/PathSetupSheet.py @@ -222,3 +222,7 @@ class _RegisteredOp(object): def RegisterOperation(name, objFactory, setupProperties): global _RegisteredOps _RegisteredOps[name] = _RegisteredOp(objFactory, setupProperties) + +def OpNamePrefix(name): + return name.replace('Path', '').replace(' ', '').replace('_', '') + diff --git a/src/Mod/Path/PathScripts/PathSetupSheetGui.py b/src/Mod/Path/PathScripts/PathSetupSheetGui.py index a3fefd68bf..a27e46e827 100644 --- a/src/Mod/Path/PathScripts/PathSetupSheetGui.py +++ b/src/Mod/Path/PathScripts/PathSetupSheetGui.py @@ -30,6 +30,7 @@ import PathScripts.PathGui as PathGui import PathScripts.PathIconViewProvider as PathIconViewProvider import PathScripts.PathLog as PathLog import PathScripts.PathSetupSheet as PathSetupSheet +import PathScripts.PathSetupSheetOpPrototype as PathSetupSheetOpPrototype import PathScripts.PathUtil as PathUtil from PySide import QtCore, QtGui @@ -93,17 +94,97 @@ class ViewProvider: def doubleClicked(self, vobj): self.setEdit(vobj) +class PropertyEditorDelegate(QtGui.QStyledItemDelegate): + + def paint(self, painter, option, index): + #PathLog.track(index.column(), type(option)) + if False and 2 == index.column(): + PathLog.track(index.row(), index.data().toString()) + painter.drawText(option.rect, index.data().toString()) + else: + QtGui.QStyledItemDelegate.paint(self, painter, option, index) + + def createEditor(self, parent, option, index): + PathLog.track(index.row(), index.column()) + if 0 == index.column(): + return QtGui.QStyledItemDelegate.createEditor(self, parent, option, index) + return None + + def setEditorData(self, widget, index): + PathLog.track(index.row(), index.column()) + if 0 == index.column(): + QtGui.QStyledItemDelegate.setEditorData(self, widget, index) + isset = widget.isChecked() + index.model().item(index.row(), 1).setEnabled(isset) + index.model().item(index.row(), 2).setEnabled(isset) + print("setEditorData(%s)" % widget) + + def setModelData(self, widget, model, index): + PathLog.track(index.row(), index.column()) + if 0 == index.column(): + return QtGui.QStyledItemDelegate.setModelData(self, widget, model, index) + print("setModelData(%s)" % widget) + + def updateEditorGeometry(self, widget, option, index): + #print("is this even called") + if widget: + widget.setGeometry(option.rect) + else: + print("so sad") + class OpTaskPanel: + def __init__(self, obj, name, op): self.name = name + self.prefix = PathSetupSheet.OpNamePrefix(name) self.obj = obj self.op = op self.form = FreeCADGui.PySideUic.loadUi(":/panels/SetupOp.ui") self.form.setWindowTitle(self.name) + self.props = sorted(op.properties()) + self.prototype = PathSetupSheetOpPrototype.OpPrototype() + op.factory("OpPrototype.%s" % name, self.prototype) + + def updateData(self, topLeft, bottomRight): + if 0 == topLeft.column(): + isset = self.model.item(topLeft.row(), 0).checkState() == QtCore.Qt.Checked + self.model.item(topLeft.row(), 1).setEnabled(isset) + self.model.item(topLeft.row(), 2).setEnabled(isset) + def setupUi(self): PathLog.track() + self.delegate = PropertyEditorDelegate(self.form) + self.model = QtGui.QStandardItemModel(len(self.props), 3, self.form) + self.model.setHorizontalHeaderLabels(['Set', 'Property', 'Value']) + + for i,name in enumerate(self.props): + prop = self.prototype.getProperty(name) + isset = hasattr(self.obj, self.propertyName(name)) + if isset: + prop.setValue(getattr(self.obj, self.propertyName(name))) + + self.model.setData(self.model.index(i, 0), isset, QtCore.Qt.EditRole) + self.model.setData(self.model.index(i, 1), name, QtCore.Qt.EditRole) + self.model.setData(self.model.index(i, 2), prop, QtCore.Qt.EditRole) + self.model.setData(self.model.index(i, 2), prop.toString(), QtCore.Qt.DisplayRole) + + self.model.item(i, 0).setCheckable(True) + self.model.item(i, 0).setText('') + self.model.item(i, 1).setEditable(False) + if not isset: + self.model.item(i, 1).setEnabled(False) + self.model.item(i, 2).setEnabled(False) + + self.form.table.setModel(self.model) + self.form.table.setItemDelegate(self.delegate) + self.form.table.resizeColumnsToContents() + + self.model.dataChanged.connect(self.updateData) + + def propertyName(self, prop): + return "%{}_%{}".format(self.prefix, prop) class TaskPanel: DataIds = QtCore.Qt.ItemDataRole.UserRole diff --git a/src/Mod/Path/PathScripts/PathSetupSheetOpPrototype.py b/src/Mod/Path/PathScripts/PathSetupSheetOpPrototype.py index b2e32f863d..8720129e8a 100644 --- a/src/Mod/Path/PathScripts/PathSetupSheetOpPrototype.py +++ b/src/Mod/Path/PathScripts/PathSetupSheetOpPrototype.py @@ -39,6 +39,7 @@ class Property(object): self.category = category self.info = info self.editorMode = 0 + self.value = '' def setValue(self, value): self.value = value @@ -48,7 +49,20 @@ class Property(object): def setEditorMode(self, mode): self.editorMode = mode + def toString(self): + if self.value: + return str(self.value) + t = self.typeString() + p = 'an' if t[0] in ['A', 'E', 'I', 'O', 'U'] else 'a' + return "%s %s" % (p, t) + + def typeString(self): + return "Property" + class PropertyEnumeration(Property): + def typeString(self): + return "Enumeration" + def setValue(self, value): if list == type(value): self.enums = value @@ -59,19 +73,24 @@ class PropertyEnumeration(Property): return self.enums class PropertyDistance(Property): - pass + def typeString(self): + return "Distance" class PropertyPercent(Property): - pass + def typeString(self): + return "Percent" class PropertyFloat(Property): - pass + def typeString(self): + return "Float" class PropertyBool(Property): - pass + def typeString(self): + return "Bool" class PropertyString(Property): - pass + def typeString(self): + return "String" class OpPrototype(object): @@ -99,6 +118,8 @@ class OpPrototype(object): def setEditorMode(self, name, mode): self.properties[name].setEditorMode(mode) + def getProperty(self, name): + return self.properties[name] def setupProperties(self, setup): return [p for p in self.properties if p.name in setup]