Basic property container with editor, no adding of properties yet

This commit is contained in:
Markus Lampert
2020-12-07 21:00:43 -08:00
parent 2f731b7da7
commit dd3a4be81d
8 changed files with 807 additions and 0 deletions

View File

@@ -96,6 +96,10 @@ SET(PathScripts_SRCS
PathScripts/PathProfileFaces.py
PathScripts/PathProfileFacesGui.py
PathScripts/PathProfileGui.py
PathScripts/PathProperty.py
PathScripts/PathPropertyContainer.py
PathScripts/PathPropertyContainerGui.py
PathScripts/PathPropertyEditor.py
PathScripts/PathSanity.py
PathScripts/PathSelection.py
PathScripts/PathSetupSheet.py

View File

@@ -121,6 +121,7 @@
<file>panels/PageOpVcarveEdit.ui</file>
<file>panels/PathEdit.ui</file>
<file>panels/PointEdit.ui</file>
<file>panels/PropertyContainer.ui</file>
<file>panels/SetupGlobal.ui</file>
<file>panels/SetupOp.ui</file>
<file>panels/ToolBitEditor.ui</file>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>552</width>
<height>651</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableView" name="table">
<property name="editTriggers">
<set>QAbstractItemView::AllEditTriggers</set>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="remove">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="add">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -66,6 +66,7 @@ def Startup():
# from PathScripts import PathProfileEdgesGui
# from PathScripts import PathProfileFacesGui
from PathScripts import PathProfileGui
from PathScripts import PathPropertyContainerGui
from PathScripts import PathSanity
from PathScripts import PathSetupSheetGui
from PathScripts import PathSimpleCopy

View File

@@ -0,0 +1,201 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2020 sliptonic <shopinthewoods@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import PathScripts.PathLog as PathLog
__title__ = "Property type abstraction for editing purposes"
__author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Prototype objects to allow extraction of setup sheet values and editing."
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
#PathLog.trackModule(PathLog.thisModule())
class Property(object):
'''Base class for all prototype properties'''
def __init__(self, name, propType, category, info):
self.name = name
self.propType = propType
self.category = category
self.info = info
self.editorMode = 0
self.value = None
def setValue(self, value):
self.value = value
def getValue(self):
return self.value
def setEditorMode(self, mode):
self.editorMode = mode
def displayString(self):
if self.value is None:
t = self.typeString()
p = 'an' if t[0] in ['A', 'E', 'I', 'O', 'U'] else 'a'
return "%s %s" % (p, t)
return self.value
def typeString(self):
return "Property"
def setupProperty(self, obj, name, category, value):
created = False
if not hasattr(obj, name):
obj.addProperty(self.propType, name, category, self.info)
self.initProperty(obj, name)
created = True
setattr(obj, name, value)
return created
def initProperty(self, obj, name):
pass
def setValueFromString(self, string):
self.setValue(self.valueFromString(string))
def valueFromString(self, string):
return string
class PropertyEnumeration(Property):
def typeString(self):
return "Enumeration"
def setValue(self, value):
if list == type(value):
self.enums = value # pylint: disable=attribute-defined-outside-init
else:
super(PropertyEnumeration, self).setValue(value)
def getEnumValues(self):
return self.enums
def initProperty(self, obj, name):
setattr(obj, name, self.enums)
class PropertyQuantity(Property):
def displayString(self):
if self.value is None:
return Property.displayString(self)
return self.value.getUserPreferred()[0]
class PropertyAngle(PropertyQuantity):
def typeString(self):
return "Angle"
class PropertyDistance(PropertyQuantity):
def typeString(self):
return "Distance"
class PropertyLength(PropertyQuantity):
def typeString(self):
return "Length"
class PropertyPercent(Property):
def typeString(self):
return "Percent"
class PropertyFloat(Property):
def typeString(self):
return "Float"
def valueFromString(self, string):
return float(string)
class PropertyInteger(Property):
def typeString(self):
return "Integer"
def valueFromString(self, string):
return int(string)
class PropertyBool(Property):
def typeString(self):
return "Bool"
def valueFromString(self, string):
return bool(string)
class PropertyString(Property):
def typeString(self):
return "String"
class PropertyMap(Property):
def typeString(self):
return "Map"
def displayString(self, value):
return str(value)
class OpPrototype(object):
PropertyType = {
'App::PropertyAngle': PropertyAngle,
'App::PropertyBool': PropertyBool,
'App::PropertyDistance': PropertyDistance,
'App::PropertyEnumeration': PropertyEnumeration,
'App::PropertyFile': PropertyString,
'App::PropertyFloat': PropertyFloat,
'App::PropertyFloatConstraint': Property,
'App::PropertyFloatList': Property,
'App::PropertyInteger': PropertyInteger,
'App::PropertyIntegerList': PropertyInteger,
'App::PropertyLength': PropertyLength,
'App::PropertyLink': Property,
'App::PropertyLinkList': Property,
'App::PropertyLinkSubListGlobal': Property,
'App::PropertyMap': PropertyMap,
'App::PropertyPercent': PropertyPercent,
'App::PropertyString': PropertyString,
'App::PropertyStringList': Property,
'App::PropertyVectorDistance': Property,
'App::PropertyVectorList': Property,
'Part::PropertyPartShape': Property,
}
def __init__(self, name):
self.Label = name
self.properties = {}
self.DoNotSetDefaultValues = True
self.Proxy = None
def __setattr__(self, name, val):
if name in ['Label', 'DoNotSetDefaultValues', 'properties', 'Proxy']:
if name == 'Proxy':
val = None # make sure the proxy is never set
return super(OpPrototype, self).__setattr__(name, val)
self.properties[name].setValue(val)
def addProperty(self, typeString, name, category, info = None):
prop = self.PropertyType[typeString](name, typeString, category, info)
self.properties[name] = prop
return self
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]

View File

@@ -0,0 +1,89 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2020 sliptonic <shopinthewoods@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD
import PySide
__title__ = 'Generic property container to store some values.'
__author__ = 'sliptonic (Brad Collette)'
__url__ = 'https://www.freecadweb.org'
__doc__ = 'A generic container for typed properties in arbitrary categories.'
def translate(context, text, disambig=None):
return PySide.QtCore.QCoreApplication.translate(context, text, disambig)
class PropertyContainer(object):
'''Property container object.'''
CustomPropertyGroups = 'CustomPropertyGroups'
CustomPropertyGroupDefault = 'User'
def __init__(self, obj):
self.obj = obj
obj.addProperty('App::PropertyStringList', self.CustomPropertyGroups, 'Base', PySide.QtCore.QT_TRANSLATE_NOOP('PathPropertyContainer', 'List of custom property groups'))
obj.setEditorMode(self.CustomPropertyGroups, 2) # hide
def __getstate__(self):
return None
def __setstate__(self, state):
for obj in FreeCAD.ActiveDocument.Objects:
if hasattr(obj, 'Proxy') and obj.Proxy == self:
self.obj = obj
obj.setEditorMode(self.CustomPropertyGroups, 2) # hide
break
return None
def onDocumentRestored(self, obj):
obj.setEditorMode(self.CustomPropertyGroups, 2) # hide
def getCustomProperties(self):
'''Return a list of all custom properties created in this container.'''
return [p for p in self.obj.PropertiesList if self.obj.getGroupOfProperty(p) in self.obj.CustomPropertyGroups]
def addCustomProperty(self, propertyType, name, group=None, desc=None):
'''addCustomProperty(propertyType, name, group=None, desc=None) ... adds a custom property and tracks its group.'''
if desc is None:
desc = ''
if group is None:
group = self.CustomPropertyGroupDefault
groups = self.obj.CustomPropertyGroups
if not group in groups:
groups.append(group)
self.obj.CustomPropertyGroups = groups
self.obj.addProperty(propertyType, name, group, desc)
def Create(name = 'PropertyContainer'):
obj = FreeCAD.ActiveDocument.addObject('App::FeaturePython', name)
obj.Proxy = PropertyContainer(obj)
return obj
def IsPropertyContainer(obj):
'''Returns True if the supplied object is a property container (or its Proxy).'''
if type(obj) == PropertyContainer:
return True
if hasattr(obj, 'Proxy'):
return IsPropertyContainer(obj.Proxy)
return False

View File

@@ -0,0 +1,235 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2020 sliptonic <shopinthewoods@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD
import FreeCADGui
import PathScripts.PathGui as PathGui
import PathScripts.PathIconViewProvider as PathIconViewProvider
import PathScripts.PathLog as PathLog
import PathScripts.PathPropertyContainer as PathPropertyContainer
import PathScripts.PathPropertyEditor as PathPropertyEditor
import PathScripts.PathUtil as PathUtil
from PySide import QtCore, QtGui
__title__ = "Property Container Editor"
__author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Task panel editor for a PropertyContainer"
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
class ViewProvider:
'''ViewProvider for a PropertyContainer.
It's sole job is to provide an icon and invoke the TaskPanel on edit.'''
def __init__(self, vobj, name):
PathLog.track(name)
vobj.Proxy = self
self.icon = name
# mode = 2
self.obj = None
self.vobj = None
def attach(self, vobj):
PathLog.track()
self.vobj = vobj
self.obj = vobj.Object
def getIcon(self):
return ":/icons/Path-SetupSheet.svg"
def __getstate__(self):
return None
def __setstate__(self, state):
# pylint: disable=unused-argument
return None
def getDisplayMode(self, mode):
# pylint: disable=unused-argument
return 'Default'
def setEdit(self, vobj, mode=0):
# pylint: disable=unused-argument
PathLog.track()
taskPanel = TaskPanel(vobj)
FreeCADGui.Control.closeDialog()
FreeCADGui.Control.showDialog(taskPanel)
taskPanel.setupUi()
return True
def unsetEdit(self, vobj, mode):
# pylint: disable=unused-argument
FreeCADGui.Control.closeDialog()
return
def claimChildren(self):
return []
def doubleClicked(self, vobj):
self.setEdit(vobj)
class Delegate(QtGui.QStyledItemDelegate):
RoleObject = QtCore.Qt.UserRole + 1
RoleProperty = QtCore.Qt.UserRole + 2
RoleEditor = QtCore.Qt.UserRole + 3
#def paint(self, painter, option, index):
# #PathLog.track(index.column(), type(option))
def createEditor(self, parent, option, index):
# pylint: disable=unused-argument
editor = PathPropertyEditor.Editor(index.data(self.RoleObject), index.data(self.RoleProperty))
index.model().setData(index, editor, self.RoleEditor)
return editor.widget(parent)
def setEditorData(self, widget, index):
PathLog.track(index.row(), index.column())
index.data(self.RoleEditor).setEditorData(widget)
def setModelData(self, widget, model, index):
# pylint: disable=unused-argument
PathLog.track(index.row(), index.column())
editor = index.data(self.RoleEditor)
editor.setModelData(widget)
index.model().setData(index, editor.displayString(), QtCore.Qt.DisplayRole)
def updateEditorGeometry(self, widget, option, index):
# pylint: disable=unused-argument
widget.setGeometry(option.rect)
class TaskPanel:
ColumnName = 0
ColumnVal = 1
ColumnDesc = 2
def __init__(self, vobj):
self.obj = vobj.Object
self.props = sorted(self.obj.Proxy.getCustomProperties())
self.form = FreeCADGui.PySideUic.loadUi(":panels/PropertyContainer.ui")
# initialized later
self.delegate = None
self.model = None
FreeCAD.ActiveDocument.openTransaction(translate("PathPropertyContainer", "Edit PropertyContainer"))
def updateData(self, topLeft, bottomRight):
# pylint: disable=unused-argument
#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)
print("index = ({}, {}) - ({}, {})".format(topLeft.row(), topLeft.column(), bottomRight.row(), bottomRight.column()))
if topLeft.column() == self.ColumnDesc:
obj = topLeft.data(Delegate.RoleObject)
prop = topLeft.data(Delegate.RoleProperty)
def setupUi(self):
PathLog.track()
self.delegate = Delegate(self.form)
self.model = QtGui.QStandardItemModel(len(self.props), 3, self.form)
self.model.setHorizontalHeaderLabels(['Property', 'Value', 'Description'])
for i,name in enumerate(self.props):
info = self.obj.getDocumentationOfProperty(name)
value = self.obj.getPropertyByName(name)
self.model.setData(self.model.index(i, self.ColumnName), name, QtCore.Qt.EditRole)
self.model.setData(self.model.index(i, self.ColumnVal), self.obj, Delegate.RoleObject)
self.model.setData(self.model.index(i, self.ColumnVal), name, Delegate.RoleProperty)
self.model.setData(self.model.index(i, self.ColumnVal), str(value), QtCore.Qt.DisplayRole)
self.model.setData(self.model.index(i, self.ColumnDesc), info, QtCore.Qt.EditRole)
self.model.item(i, self.ColumnName).setEditable(False)
self.form.table.setModel(self.model)
self.form.table.setItemDelegateForColumn(self.ColumnVal, self.delegate)
self.form.table.resizeColumnsToContents()
self.model.dataChanged.connect(self.updateData)
self.form.table.selectionModel().selectionChanged.connect(self.propertySelected)
self.form.add.clicked.connect(self.propertyAdd)
self.form.remove.clicked.connect(self.propertyRemove)
self.propertySelected([])
def accept(self):
#propertiesCreatedRemoved = False
#for i,name in enumerate(self.props):
# prop = self.prototype.getProperty(name)
# propName = self.propertyName(name)
# enabled = self.model.item(i, 0).checkState() == QtCore.Qt.Checked
# if enabled and not prop.getValue() is None:
# if prop.setupProperty(self.obj, propName, self.propertyGroup(), prop.getValue()):
# propertiesCreatedRemoved = True
# else:
# if hasattr(self.obj, propName):
# self.obj.removeProperty(propName)
# propertiesCreatedRemoved = True
FreeCAD.ActiveDocument.commitTransaction()
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
def reject(self):
FreeCAD.ActiveDocument.abortTransaction()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
def propertySelected(self, selection):
PathLog.track()
if selection:
self.form.remove.setEnabled(True)
else:
self.form.remove.setEnabled(False)
def propertyAdd(self):
PathLog.track()
def propertyRemove(self):
PathLog.track()
rows = []
for index in self.form.table.selectionModel().selectedIndexes():
if not index.row() in rows:
rows.append(index.row())
for row in reversed(sorted(rows)):
self.obj.removeProperty(self.model.item(row).data(QtCore.Qt.EditRole))
self.model.removeRow(row)
def Create(name = 'PropertyContainer'):
'''Create(name = 'PropertyContainer') ... creates a new setup sheet'''
FreeCAD.ActiveDocument.openTransaction(translate("PathPropertyContainer", "Create PropertyContainer"))
pcont = PathPropertyContainer.Create(name)
PathIconViewProvider.Attach(pcont.ViewObject, name)
return pcont
PathIconViewProvider.RegisterViewProvider('PropertyContainer', ViewProvider)

View File

@@ -0,0 +1,219 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2020 sliptonic <shopinthewoods@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD
import PathScripts.PathLog as PathLog
import PathScripts.PathSetupSheetOpPrototype as PathSetupSheetOpPrototype
from PySide import QtCore, QtGui
__title__ = "Path Property Editor"
__author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Task panel editor for Properties"
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
LOGLEVEL = False
if LOGLEVEL:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
class _PropertyEditor(object):
'''Base class of all property editors - just outlines the TableView delegate interface.'''
def __init__(self, obj, prop):
self.obj = obj
self.prop = prop
def widget(self, parent):
'''widget(parent) ... called by the delegate to get a new editor widget.
Must be implemented by subclasses and return the widget.'''
pass # pylint: disable=unnecessary-pass
def setEditorData(self, widget):
'''setEditorData(widget) ... called by the delegate to initialize the editor.
The widget is the object returned by widget().
Must be implemented by subclasses.'''
pass # pylint: disable=unnecessary-pass
def setModelData(self, widget):
'''setModelData(widget) ... called by the delegate to store new values.
Must be implemented by subclasses.'''
pass # pylint: disable=unnecessary-pass
def propertyValue(self):
return self.obj.getPropertyByName(self.prop)
def setProperty(self, value):
setattr(self.obj, self.prop, value)
def displayString(self):
return self.propertyValue()
class _PropertyEditorBool(_PropertyEditor):
'''Editor for boolean values - uses a combo box.'''
def widget(self, parent):
return QtGui.QComboBox(parent)
def setEditorData(self, widget):
widget.clear()
widget.addItems(['false', 'true'])
index = 1 if self.propertyValue() else 0
widget.setCurrentIndex(index)
def setModelData(self, widget):
self.setProperty(widget.currentText() == 'true')
class _PropertyEditorString(_PropertyEditor):
'''Editor for string values - uses a line edit.'''
def widget(self, parent):
return QtGui.QLineEdit(parent)
def setEditorData(self, widget):
text = '' if self.propertyValue() is None else self.propertyValue()
widget.setText(text)
def setModelData(self, widget):
self.setProperty(widget.text())
class _PropertyEditorQuantity(_PropertyEditor):
def widget(self, parent):
return QtGui.QLineEdit(parent)
def setEditorData(self, widget):
quantity = self.propertyValue()
if quantity is None:
quantity = self.defaultQuantity()
widget.setText(quantity.getUserPreferred()[0])
def defaultQuantity(self):
pass
def setModelData(self, widget):
self.setProperty(FreeCAD.Units.Quantity(widget.text()))
def displayString(self):
if self.propertyValue() is None:
return ''
return self.propertyValue().getUserPreferred()[0]
class _PropertyEditorAngle(_PropertyEditorQuantity):
'''Editor for angle values - uses a line edit'''
def defaultQuantity(self):
return FreeCAD.Units.Quantity(0, FreeCAD.Units.Angle)
class _PropertyEditorLength(_PropertyEditorQuantity):
'''Editor for length values - uses a line edit.'''
def defaultQuantity(self):
return FreeCAD.Units.Quantity(0, FreeCAD.Units.Length)
class _PropertyEditorPercent(_PropertyEditor):
'''Editor for percent values - uses a spin box.'''
def widget(self, parent):
return QtGui.QSpinBox(parent)
def setEditorData(self, widget):
widget.setRange(0, 100)
value = self.propertyValue()
if value is None:
value = 0
widget.setValue(value)
def setModelData(self, widget):
self.setProperty(widget.value())
class _PropertyEditorInteger(_PropertyEditor):
'''Editor for integer values - uses a spin box.'''
def widget(self, parent):
return QtGui.QSpinBox(parent)
def setEditorData(self, widget):
value = self.propertyValue()
if value is None:
value = 0
widget.setValue(value)
def setModelData(self, widget):
self.setProperty(widget.value())
class _PropertyEditorFloat(_PropertyEditor):
'''Editor for float values - uses a double spin box.'''
def widget(self, parent):
return QtGui.QDoubleSpinBox(parent)
def setEditorData(self, widget):
value = self.propertyValue()
if value is None:
value = 0.0
widget.setValue(value)
def setModelData(self, widget):
self.setProperty(widget.value())
class _PropertyEditorFile(_PropertyEditor):
def widget(self, parent):
return QtGui.QLineEdit(parent)
def setEditorData(self, widget):
text = '' if self.propertyValue() is None else self.propertyValue()
widget.setText(text)
def setModelData(self, widget):
self.setProperty(widget.text())
_EditorFactory = {
'App::PropertyAngle' : _PropertyEditorAngle,
'App::PropertyBool' : _PropertyEditorBool,
'App::PropertyDistance' : _PropertyEditorLength,
#'App::PropertyEnumeration' : _PropertyEditorEnum,
#'App::PropertyFile' : _PropertyEditorFile,
'App::PropertyFloat' : _PropertyEditorFloat,
'App::PropertyInteger' : _PropertyEditorInteger,
'App::PropertyLength' : _PropertyEditorLength,
'App::PropertyPercent' : _PropertyEditorPercent,
'App::PropertyString' : _PropertyEditorString,
}
def Types():
'''Return the types of properties supported.'''
return [t for t in _EditorFactory]
def Editor(obj, prop):
'''Returns an editor class to be used for the given property.'''
factory = _EditorFactory[obj.getTypeIdOfProperty(prop)]
if factory:
return factory(obj, prop)
return None