Template export/import of operation settings.

This commit is contained in:
Markus Lampert
2018-08-25 13:58:13 -07:00
parent 5f5543da31
commit a3cd80796b
5 changed files with 173 additions and 95 deletions

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>422</width>
<height>434</height>
<width>650</width>
<height>887</height>
</rect>
</property>
<property name="windowTitle">
@@ -42,6 +42,86 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="toolsGroup">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If enabled tool controller definitions are stored in the template.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="title">
<string>Tools</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QListWidget" name="toolsList">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Check all tool controllers which should be included in the template.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="settingsGroup">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable to include values of the SetupSheet in the template.&lt;/p&gt;&lt;p&gt;Any values of the SetupSheet that are changed from their default are preselected. If this field not selected the current SetupSheet was not modified.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="title">
<string>Setup Sheet</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1">
<widget class="QCheckBox" name="settingOperationDepths">
<property name="text">
<string>Operation Depths</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="settingOperationHeights">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable to include the default heights for operations in the template.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Operation Heights</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="settingToolRapid">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable to include the default rapid tool speeds in the template.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Tool Rapid Speeds</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QListWidget" name="settingsOpsList">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable all Operations for which the configuration values should be exported.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Note that only operations are listed which currently have configuration values setup.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="stockGroup">
<property name="toolTip">
@@ -109,79 +189,6 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="settingsGroup">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable to include values of the SetupSheet in the template.&lt;/p&gt;&lt;p&gt;Any values of the SetupSheet that are changed from their default are preselected. If this field not selected the current SetupSheet was not modified.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="title">
<string>Setup Sheet</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QCheckBox" name="settingOperationHeights">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable to include the default heights for operations in the template.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Operation Heights</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="settingOperationDepths">
<property name="text">
<string>Operation Depths</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="settingToolRapid">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable to include the default rapid tool speeds in the template.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Tool Rapid Speeds</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="toolsGroup">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If enabled tool controller definitions are stored in the template.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="title">
<string>Tools</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QListWidget" name="toolsList">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Check all tool controllers which should be included in the template.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
@@ -196,14 +203,12 @@
</widget>
<tabstops>
<tabstop>postProcessingGroup</tabstop>
<tabstop>stockGroup</tabstop>
<tabstop>stockExtent</tabstop>
<tabstop>stockPlacement</tabstop>
<tabstop>settingsGroup</tabstop>
<tabstop>settingOperationHeights</tabstop>
<tabstop>settingOperationDepths</tabstop>
<tabstop>settingToolRapid</tabstop>
<tabstop>toolsGroup</tabstop>
<tabstop>toolsList</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>

View File

@@ -162,11 +162,16 @@ class DlgJobTemplateExport:
rapidChanged = not job.SetupSheet.Proxy.hasDefaultToolRapids()
depthsChanged = not job.SetupSheet.Proxy.hasDefaultOperationDepths()
heightsChanged = not job.SetupSheet.Proxy.hasDefaultOperationHeights()
settingsChanged = rapidChanged or depthsChanged or heightsChanged
opsWithSettings = job.SetupSheet.Proxy.operationsWithSettings()
settingsChanged = rapidChanged or depthsChanged or heightsChanged or 0 != len(opsWithSettings)
self.dialog.settingsGroup.setChecked(settingsChanged)
self.dialog.settingToolRapid.setChecked(rapidChanged)
self.dialog.settingOperationDepths.setChecked(depthsChanged)
self.dialog.settingOperationHeights.setChecked(heightsChanged)
for op in opsWithSettings:
item = QtGui.QListWidgetItem(op)
item.setCheckState(QtCore.Qt.CheckState.Checked)
self.dialog.settingsOpsList.addItem(item)
for tc in sorted(job.ToolController, key=lambda o: o.Label):
item = QtGui.QListWidgetItem(tc.Label)
@@ -208,6 +213,14 @@ class DlgJobTemplateExport:
def includeSettingOperationDepths(self):
return self.dialog.settingOperationDepths.isChecked()
def includeSettingOpsSettings(self):
ops = []
for i in range(self.dialog.settingsOpsList.count()):
item = self.dialog.settingsOpsList.item(i)
if item.checkState() == QtCore.Qt.CheckState.Checked:
ops.append(item.text())
return ops
def exec_(self):
return self.dialog.exec_()
@@ -283,7 +296,7 @@ class CommandJobTemplateExport:
# setup sheet
setupSheetAttrs = None
if dialog:
setupSheetAttrs = job.Proxy.setupSheet.templateAttributes(dialog.includeSettingToolRapid(), dialog.includeSettingOperationHeights(), dialog.includeSettingOperationDepths())
setupSheetAttrs = job.Proxy.setupSheet.templateAttributes(dialog.includeSettingToolRapid(), dialog.includeSettingOperationHeights(), dialog.includeSettingOperationDepths(), dialog.includeSettingOpsSettings())
else:
setupSheetAttrs = job.Proxy.setupSheet.templateAttributes(True, True, True)
if setupSheetAttrs:

View File

@@ -26,6 +26,7 @@ import FreeCAD
import Path
import PathScripts.PathGeom as PathGeom
import PathScripts.PathLog as PathLog
import PathScripts.PathSetupSheetOpPrototype as PathSetupSheetOpPrototype
import PathScripts.PathUtil as PathUtil
import PySide
@@ -154,21 +155,48 @@ class SetupSheet:
if attrs.get(name) is not None:
setattr(self.obj, name, attrs[name])
def templateAttributes(self, includeRapids=True, includeHeights=True, includeDepths=True):
for opName,op in PathUtil.keyValueIter(_RegisteredOps):
opSetting = attrs.get(opName)
if opSetting is not None:
prototype = op.prototype(opName)
for propName in op.properties():
value = opSetting.get(propName)
if not value is None:
prop = prototype.getProperty(propName)
propertyName = OpPropertyName(opName, propName)
propertyGroup = OpPropertyGroup(opName)
prop.setupProperty(self.obj, propertyName, propertyGroup, prop.valueFromString(value))
def templateAttributes(self, includeRapids=True, includeHeights=True, includeDepths=True, includeOps=None):
'''templateAttributes(includeRapids, includeHeights, includeDepths) ... answers a dictionary with the default values.'''
attrs = {}
if includeRapids:
attrs[Template.VertRapid] = self.obj.VertRapid.UserString
attrs[Template.HorizRapid] = self.obj.HorizRapid.UserString
if includeHeights:
attrs[Template.SafeHeightOffset] = self.obj.SafeHeightOffset.UserString
attrs[Template.SafeHeightExpression] = self.obj.SafeHeightExpression
attrs[Template.ClearanceHeightOffset] = self.obj.ClearanceHeightOffset.UserString
attrs[Template.ClearanceHeightExpression] = self.obj.ClearanceHeightExpression
if includeDepths:
attrs[Template.StartDepthExpression] = self.obj.StartDepthExpression
attrs[Template.FinalDepthExpression] = self.obj.FinalDepthExpression
attrs[Template.StepDownExpression] = self.obj.StepDownExpression
if includeOps:
for opName in includeOps:
settings = {}
op = _RegisteredOps[opName]
for propName in op.properties():
prop = OpPropertyName(opName, propName)
if hasattr(self.obj, prop):
settings[propName] = getattr(self.obj, prop)
attrs[opName] = settings
return attrs
def expressionReference(self):
@@ -208,6 +236,16 @@ class SetupSheet:
'''decodeTemplateAttributes(attrs) ... expand template attributes to reference the receiver where applicable.'''
return _traverseTemplateAttributes(attrs, self.decodeAttributeString)
def operationsWithSettings(self):
'''operationsWithSettings() ... returns a list of operations which currently have some settings defined.'''
ops = []
for name,value in PathUtil.keyValueIter(_RegisteredOps):
for prop in value.registeredPropertyNames(name):
if hasattr(self.obj, prop):
ops.append(name)
break
return ops
def Create(name = 'SetupSheet'):
obj = FreeCAD.ActiveDocument.addObject('App::FeaturePython', name)
@@ -215,10 +253,19 @@ def Create(name = 'SetupSheet'):
return obj
class _RegisteredOp(object):
def __init__(self, factory, properties):
self.factory = factory
self.properties = properties
def registeredPropertyNames(self, name):
return [OpPropertyName(name, prop) for prop in self.properties()]
def prototype(self, name):
ptt = PathSetupSheetOpPrototype.OpPrototype(name)
self.factory("OpPrototype.%s" % name, ptt)
return ptt
def RegisterOperation(name, objFactory, setupProperties):
global _RegisteredOps
_RegisteredOps[name] = _RegisteredOp(objFactory, setupProperties)
@@ -226,3 +273,7 @@ def RegisterOperation(name, objFactory, setupProperties):
def OpNamePrefix(name):
return name.replace('Path', '').replace(' ', '').replace('_', '')
def OpPropertyName(opName, propName):
return "{}{}".format(OpNamePrefix(opName), propName)
def OpPropertyGroup(opName):
return "Op {}".format(opName)

View File

@@ -128,14 +128,12 @@ 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(name)
op.factory("OpPrototype.%s" % name, self.prototype)
self.prototype = op.prototype(name)
def updateData(self, topLeft, bottomRight):
if 0 == topLeft.column():
@@ -179,23 +177,25 @@ class OpTaskPanel:
self.model.dataChanged.connect(self.updateData)
def propertyName(self, prop):
return "{}{}".format(self.prefix, prop)
return PathSetupSheet.OpPropertyName(self.name, prop)
def categoryName(self):
return "Op {}".format(self.name)
def propertyGroup(self):
return PathSetupSheet.OpPropertyGroup(self.name)
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:
prop.setupProperty(self.obj, propName, self.categoryName())
setattr(self.obj, propName, prop.getValue())
if prop.setupProperty(self.obj, propName, self.propertyGroup(), prop.getValue()):
propertiesCreatedRemoved = True
else:
if hasattr(self.obj, propName):
self.obj.removeProperty(propName)
return True
propertiesCreatedRemoved = True
return propertiesCreatedRemoved
class TaskPanel:
@@ -219,16 +219,18 @@ class TaskPanel:
def accept(self):
self.getFields()
[op.accept() for op in self.ops]
#if any([op.accept() for op in self.ops]):
# PathLog.track()
# self.obj.touch()
if any([op.accept() for op in self.ops]):
PathLog.track()
#sel = FreeCADGui.Selection.getSelection()
#FreeCADGui.Selection.clearSelection()
#for o in sel:
# FreeCADGui.Selection.addSelection(o)
FreeCAD.ActiveDocument.commitTransaction()
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
#FreeCADGui.Selection.removeObserver(self.s)
FreeCAD.ActiveDocument.recompute()
#self.vobj.update()
#FreeCAD.ActiveDocument.recompute()
def getFields(self):
def updateExpression(name, widget):

View File

@@ -66,14 +66,21 @@ class Property(object):
def typeString(self):
return "Property"
def setupProperty(self, obj, name, category):
def setupProperty(self, obj, name, category, value):
if not hasattr(obj, name):
obj.addProperty(self.propType, name, category, self.info)
self.initProperty(obj, name)
setattr(obj, name, value)
return True
return False
def initProperty(self, obj, name):
pass
def valueFromString(self, string):
return string
class PropertyEnumeration(Property):
def typeString(self):
return "Enumeration"