From 9d98ac390e317483ff6c9c643da82c9437eb0794 Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Sun, 8 Oct 2017 14:16:15 -0700 Subject: [PATCH] Changed tool parameters to use a QuantitySpinBox. --- .../Resources/panels/DlgToolControllerEdit.ui | 157 ++++++++++++------ src/Mod/Path/PathScripts/PathGui.py | 84 ++++++++-- .../Path/PathScripts/PathToolController.py | 32 ++-- 3 files changed, 198 insertions(+), 75 deletions(-) diff --git a/src/Mod/Path/Gui/Resources/panels/DlgToolControllerEdit.ui b/src/Mod/Path/Gui/Resources/panels/DlgToolControllerEdit.ui index 9e5c1ed9e2..845e2e923b 100644 --- a/src/Mod/Path/Gui/Resources/panels/DlgToolControllerEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/DlgToolControllerEdit.ui @@ -16,7 +16,15 @@ - + + + + 0 + 0 + 474 + 535 + + Controller @@ -79,10 +87,13 @@ - + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + 0.000000000000000 - + 9999999.000000000000000 @@ -92,10 +103,13 @@ - + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + 0.000000000000000 - + 9999999.000000000000000 @@ -105,10 +119,13 @@ - + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + 0.000000000000000 - + 9999999.000000000000000 @@ -118,10 +135,13 @@ - + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + 0.000000000000000 - + 9999999.000000000000000 @@ -183,7 +203,15 @@ - + + + + 0 + 0 + 474 + 535 + + Tool @@ -377,18 +405,21 @@ - - - 0 mm + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - 0.125000000000000 + + 0.00 - + + 0.000000000000000 + + 100.000000000000000 - - 0.000000000000000 + + 0.125000000000000 mm @@ -396,71 +427,86 @@ - - - 0 mm + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - 100.000000000000000 + + 0.00 - + 0.000000000000000 + + 100.000000000000000 + mm - - - 0 mm + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - 100.000000000000000 + + 0.00 - + 0.000000000000000 + + 100.000000000000000 + mm - - - 0 mm + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - 100.000000000000000 + + 0.00 - + 0.000000000000000 + + 100.000000000000000 + mm - - - 0 mm + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - 100.000000000000000 + + 0.00 - + 0.000000000000000 + + 100.000000000000000 + mm - + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + ° @@ -502,17 +548,32 @@ - - Gui::InputField - QLineEdit -
Gui/InputField.h
-
Gui::QuantitySpinBox QDoubleSpinBox
Gui/QuantitySpinBox.h
+ + tcName + tcNumber + horizFeed + vertFeed + horizRapid + vertRapid + spindleSpeed + spindleDirection + buttonBox + toolName + toolType + toolMaterial + toolDiameter + toolLengthOffset + toolFlatRadius + toolCornerRadius + toolCuttingEdgeAngle + toolCuttingEdgeHeight + diff --git a/src/Mod/Path/PathScripts/PathGui.py b/src/Mod/Path/PathScripts/PathGui.py index e53f4cc831..47fcc69069 100644 --- a/src/Mod/Path/PathScripts/PathGui.py +++ b/src/Mod/Path/PathScripts/PathGui.py @@ -25,60 +25,114 @@ import FreeCAD import FreeCADGui import PathScripts.PathLog as PathLog -import importlib +import PySide from PathScripts.PathGeom import PathGeom -from PySide import QtCore, QtGui __title__ = "Path UI helper and utility functions" __author__ = "sliptonic (Brad Collette)" __url__ = "http://www.freecadweb.org" __doc__ = "A collection of helper and utility functions for the Path GUI." +def translate(context, text, disambig=None): + return PySide.QtCore.QCoreApplication.translate(context, text, disambig) + if False: PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) PathLog.trackModule(PathLog.thisModule()) else: PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -def updateInputField(obj, prop, widget, onBeforeChange = None): - '''updateInputField(obj, prop, widget) ... helper function to update obj's property named prop with the value from widget, if it has changed.''' +def _getProperty(obj, prop): + o = obj + attr = obj + for name in prop.split('.'): + o = attr + if not hasattr(o, name): + break + attr = getattr(o, name) + + if o == attr: + PathLog.warning(translate('PathGui', "%s has no property %s (%s))") % (obj.Label, prop)) + return (None, None, None) + + #PathLog.debug("found property %s of %s (%s: %s)" % (prop, obj.Label, name, attr)) + return(o, attr, name) + +def getProperty(obj, prop): + '''getProperty(obj, prop) ... answer obj's property defined by its canonical name.''' + o, attr, name = _getProperty(obj, prop) + return attr + +def setProperty(obj, prop, value): + '''setProperty(obj, prop, value) ... set the property value of obj's property defined by its canonical name.''' + o, attr, name = _getProperty(obj, prop) + if o and name: + setattr(o, name, value) + +def updateInputField(obj, prop, widget, onBeforeChange=None): + '''updateInputField(obj, prop, widget) ... update obj's property prop with the value of widget. +The property's value is only assigned if the new value differs from the current value. +This prevents onChanged notifications where the value didn't acutally change. +Gui::InputField and Gui::QuantitySpinBox widgets are supported - and the property can +be of type Quantity or Float. +If onBeforeChange is specified it is called before a new value is assigned to the property. +Returns True if a new value was assigned, False otherwise (new value is the same as the current). +''' value = FreeCAD.Units.Quantity(widget.text()).Value - attr = getattr(obj, prop) + attr = getProperty(obj, prop) attrValue = attr.Value if hasattr(attr, 'Value') else attr if not PathGeom.isRoughly(attrValue, value): - PathLog.debug("updateInputField(%s, %s): %.2f -> %.2f" % (obj.Label, prop, getattr(obj, prop), value)) + PathLog.debug("updateInputField(%s, %s): %.2f -> %.2f" % (obj.Label, prop, attr, value)) if onBeforeChange: onBeforeChange(obj) - setattr(obj, prop, value) + setProperty(obj, prop, value) return True return False class QuantitySpinBox: - def __init__(self, widget, obj, propName, onBeforeChange=None): + '''Controller class to interface a Gui::QuantitySpinBox. +The spin box gets bound to a given property and supports update in both directions. + QuatitySpinBox(widget, obj, prop, onBeforeChange=None) + widget ... expected to be reference to a Gui::QuantitySpinBox + obj ... document object + prop ... canonical name of the (sub-) property + onBeforeChange ... an optional callback being executed before the value of the property is changed +''' + + def __init__(self, widget, obj, prop, onBeforeChange=None): self.obj = obj self.widget = widget - self.prop = propName + self.prop = prop self.onBeforeChange = onBeforeChange - if hasattr(obj, propName): - widget.setProperty('unit', getattr(self.obj, self.prop).getUserPreferred()[2]) - widget.setProperty('binding', "%s.%s" % (obj.Name, propName)) + attr = getProperty(self.obj, self.prop) + if attr is not None: + if hasattr(attr, 'Value'): + widget.setProperty('unit', attr.getUserPreferred()[2]) + widget.setProperty('binding', "%s.%s" % (obj.Name, prop)) self.valid = True else: + PathLog.warning(translate('PathGui', "Cannot find property %s of %s") % (prop, obj.Label)) self.valid = False def expression(self): + '''expression() ... returns the expression if one is bound to the property''' if self.valid: return self.widget.property('expression') - return False + return '' def updateSpinBox(self, quantity=None): + '''updateSpinBox(quantity=None) ... update the display value of the spin box. +If no value is provided the value of the bound property is used. +quantity can be of type Quantity or Float.''' if self.valid: if quantity is None: - quantity = getattr(self.obj, self.prop) - self.widget.setProperty('rawValue', quantity.Value) + quantity = getProperty(self.obj, self.prop) + value = quantity.Value if hasattr(quantity, 'Value') else quantity + self.widget.setProperty('rawValue', value) def updateProperty(self): + '''updateProperty() ... update the bound property with the value from the spin box''' if self.valid: return updateInputField(self.obj, self.prop, self.widget, self.onBeforeChange) return None diff --git a/src/Mod/Path/PathScripts/PathToolController.py b/src/Mod/Path/PathScripts/PathToolController.py index f1a25f12cd..79d587b40a 100644 --- a/src/Mod/Path/PathScripts/PathToolController.py +++ b/src/Mod/Path/PathScripts/PathToolController.py @@ -269,11 +269,19 @@ class ToolControllerEditor: if not asDialog: self.form.buttonBox.hide() self.obj = obj + self.vertFeed = PathGui.QuantitySpinBox(self.form.vertFeed, obj, 'VertFeed') self.horizFeed = PathGui.QuantitySpinBox(self.form.horizFeed, obj, 'HorizFeed') self.vertRapid = PathGui.QuantitySpinBox(self.form.vertRapid, obj, 'VertRapid') self.horizRapid = PathGui.QuantitySpinBox(self.form.horizRapid, obj, 'HorizRapid') + self.toolDiameter = PathGui.QuantitySpinBox(self.form.toolDiameter, obj, 'Tool.Diameter') + self.toolLengthOffset = PathGui.QuantitySpinBox(self.form.toolLengthOffset, obj, 'Tool.LengthOffset') + self.toolFlatRadius = PathGui.QuantitySpinBox(self.form.toolFlatRadius, obj, 'Tool.FlatRadius') + self.toolCornerRadius = PathGui.QuantitySpinBox(self.form.toolCornerRadius, obj, 'Tool.CornerRadius') + self.toolCuttingEdgeAngle = PathGui.QuantitySpinBox(self.form.toolCuttingEdgeAngle, obj, 'Tool.CuttingEdgeAngle') + self.toolCuttingEdgeHeight = PathGui.QuantitySpinBox(self.form.toolCuttingEdgeHeight, obj, 'Tool.CuttingEdgeHeight') + def getType(self, tooltype): "gets a combobox index number for a given type or viceversa" toolslist = ["Drill", "CenterDrill", "CounterSink", "CounterBore", @@ -315,12 +323,12 @@ class ToolControllerEditor: self.form.toolName.setText(tc.Tool.Name) self.form.toolType.setCurrentIndex(self.getType(tc.Tool.ToolType)) self.form.toolMaterial.setCurrentIndex(self.getMaterial(tc.Tool.Material)) - self.form.toolDiameter.setText(FreeCAD.Units.Quantity(tc.Tool.Diameter, FreeCAD.Units.Length).UserString) - self.form.toolLengthOffset.setText(FreeCAD.Units.Quantity(tc.Tool.LengthOffset, FreeCAD.Units.Length).UserString) - self.form.toolFlatRadius.setText(FreeCAD.Units.Quantity(tc.Tool.FlatRadius, FreeCAD.Units.Length).UserString) - self.form.toolCornerRadius.setText(FreeCAD.Units.Quantity(tc.Tool.CornerRadius, FreeCAD.Units.Length).UserString) - self.form.toolCuttingEdgeAngle.setText(FreeCAD.Units.Quantity(tc.Tool.CuttingEdgeAngle, FreeCAD.Units.Angle).UserString) - self.form.toolCuttingEdgeHeight.setText(FreeCAD.Units.Quantity(tc.Tool.CuttingEdgeHeight, FreeCAD.Units.Length).UserString) + self.toolDiameter.updateSpinBox() + self.toolLengthOffset.updateSpinBox() + self.toolFlatRadius.updateSpinBox() + self.toolCornerRadius.updateSpinBox() + self.toolCuttingEdgeAngle.updateSpinBox() + self.toolCuttingEdgeHeight.updateSpinBox() def updateToolController(self): tc = self.obj @@ -337,12 +345,12 @@ class ToolControllerEditor: tc.Tool.Name = str(self.form.toolName.text()) tc.Tool.ToolType = self.getType(self.form.toolType.currentIndex()) tc.Tool.Material = self.getMaterial(self.form.toolMaterial.currentIndex()) - tc.Tool.Diameter = FreeCAD.Units.parseQuantity(self.form.toolDiameter.text()) - tc.Tool.LengthOffset = FreeCAD.Units.parseQuantity(self.form.toolLengthOffset.text()) - tc.Tool.FlatRadius = FreeCAD.Units.parseQuantity(self.form.toolFlatRadius.text()) - tc.Tool.CornerRadius = FreeCAD.Units.parseQuantity(self.form.toolCornerRadius.text()) - tc.Tool.CuttingEdgeAngle = FreeCAD.Units.Quantity(self.form.toolCuttingEdgeAngle.text()) - tc.Tool.CuttingEdgeHeight = FreeCAD.Units.parseQuantity(self.form.toolCuttingEdgeHeight.text()) + self.toolDiameter.updateProperty() + self.toolLengthOffset.updateProperty() + self.toolFlatRadius.updateProperty() + self.toolCornerRadius.updateProperty() + self.toolCuttingEdgeAngle.updateProperty() + self.toolCuttingEdgeHeight.updateProperty() except Exception as e: PathLog.error(translate("PathToolController", "Error updating TC: %s") % e)