diff --git a/src/Mod/Path/PathScripts/PathSurface.py b/src/Mod/Path/PathScripts/PathSurface.py index 3c7b1d8552..73040076d0 100644 --- a/src/Mod/Path/PathScripts/PathSurface.py +++ b/src/Mod/Path/PathScripts/PathSurface.py @@ -44,13 +44,14 @@ except ImportError: # import sys # sys.exit(msg) +from PySide.QtCore import QT_TRANSLATE_NOOP import Path import PathScripts.PathLog as PathLog -import PathScripts.PathUtils as PathUtils import PathScripts.PathOp as PathOp import PathScripts.PathSurfaceSupport as PathSurfaceSupport -import time +import PathScripts.PathUtils as PathUtils import math +import time # lazily loaded modules from lazy_loader.lazy_loader import LazyLoader @@ -60,13 +61,14 @@ Part = LazyLoader("Part", globals(), "Part") if FreeCAD.GuiUp: import FreeCADGui -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -# PathLog.trackModule(PathLog.thisModule()) +translate = FreeCAD.Qt.translate -# Qt translation handling -def translate(context, text, disambig=None): - return 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()) class ObjectSurface(PathOp.ObjectOp): @@ -107,17 +109,14 @@ class ObjectSurface(PathOp.ObjectOp): self.addNewProps.append(nm) # Set enumeration lists for enumeration properties - if len(self.addNewProps) > 0: - ENUMS = self.opPropertyEnumerations() - for n in ENUMS: - if n in self.addNewProps: - setattr(obj, n, ENUMS[n]) + for n in self.propertyEnumerations(): + setattr(obj, n[0], n[1]) - if warn: - newPropMsg = translate("PathSurface", "New property added to") - newPropMsg += ' "{}": {}'.format(obj.Label, self.addNewProps) + ". " - newPropMsg += translate("PathSurface", "Check default value(s).") - FreeCAD.Console.PrintWarning(newPropMsg + "\n") + # if warn: + # newPropMsg = translate("PathSurface", "New property added to") + # newPropMsg += ' "{}": {}'.format(obj.Label, self.addNewProps) + ". " + # newPropMsg += translate("PathSurface", "Check default value(s).") + # FreeCAD.Console.PrintWarning(newPropMsg + "\n") self.propertiesReady = True @@ -129,7 +128,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyBool", "ShowTempObjects", "Debug", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Show the temporary path construction objects when module is in DEBUG mode.", ), @@ -138,7 +137,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyDistance", "AngularDeflection", "Mesh Conversion", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Smaller values yield a finer, more accurate mesh. Smaller values increase processing time a lot.", ), @@ -147,7 +146,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyDistance", "LinearDeflection", "Mesh Conversion", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Smaller values yield a finer, more accurate mesh. Smaller values do not increase processing time much.", ), @@ -156,7 +155,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyFloat", "CutterTilt", "Rotation", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Stop index(angle) for rotational scan" ), ), @@ -164,7 +163,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyEnumeration", "DropCutterDir", "Rotation", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Dropcutter lines are created parallel to this axis.", ), @@ -173,7 +172,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyVectorDistance", "DropCutterExtraOffset", "Rotation", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Additional offset to the selected bounding box" ), ), @@ -181,7 +180,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyEnumeration", "RotationAxis", "Rotation", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "The model will be rotated around this axis." ), ), @@ -189,7 +188,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyFloat", "StartIndex", "Rotation", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Start index(angle) for rotational scan" ), ), @@ -197,7 +196,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyFloat", "StopIndex", "Rotation", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Stop index(angle) for rotational scan" ), ), @@ -205,7 +204,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyEnumeration", "ScanType", "Surface", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Planar: Flat, 3D surface scan. Rotational: 4th-axis rotational scan.", ), @@ -214,7 +213,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyInteger", "AvoidLastX_Faces", "Selected Geometry Settings", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Avoid cutting the last 'N' faces in the Base Geometry list of selected faces.", ), @@ -223,7 +222,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyBool", "AvoidLastX_InternalFeatures", "Selected Geometry Settings", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Do not cut internal features on avoided faces." ), ), @@ -231,7 +230,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyDistance", "BoundaryAdjustment", "Selected Geometry Settings", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Positive values push the cutter toward, or beyond, the boundary. Negative values retract the cutter away from the boundary.", ), @@ -240,7 +239,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyBool", "BoundaryEnforcement", "Selected Geometry Settings", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "If true, the cutter will remain inside the boundaries of the model or selected face(s).", ), @@ -249,7 +248,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyEnumeration", "HandleMultipleFeatures", "Selected Geometry Settings", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Choose how to process multiple Base Geometry features.", ), @@ -258,7 +257,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyDistance", "InternalFeaturesAdjustment", "Selected Geometry Settings", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Positive values push the cutter toward, or into, the feature. Negative values retract the cutter away from the feature.", ), @@ -267,7 +266,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyBool", "InternalFeaturesCut", "Selected Geometry Settings", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Cut internal feature areas within a larger selected face.", ), @@ -276,7 +275,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyEnumeration", "BoundBox", "Clearing Options", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Select the overall boundary for the operation." ), ), @@ -284,7 +283,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyEnumeration", "CutMode", "Clearing Options", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Set the direction for the cutting tool to engage the material: Climb (ClockWise) or Conventional (CounterClockWise)", ), @@ -293,7 +292,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyEnumeration", "CutPattern", "Clearing Options", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Set the geometric clearing pattern to use for the operation.", ), @@ -302,7 +301,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyFloat", "CutPatternAngle", "Clearing Options", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "The yaw angle used for certain clearing patterns" ), ), @@ -310,7 +309,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyBool", "CutPatternReversed", "Clearing Options", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Reverse the cut order of the stepover paths. For circular cut patterns, begin at the outside and work toward the center.", ), @@ -319,7 +318,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyDistance", "DepthOffset", "Clearing Options", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Set the Z-axis depth offset from the target surface.", ), @@ -328,7 +327,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyEnumeration", "LayerMode", "Clearing Options", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Complete the operation in a single pass at depth, or mulitiple passes to final depth.", ), @@ -337,7 +336,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyVectorDistance", "PatternCenterCustom", "Clearing Options", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Set the start point for the cut pattern." ), ), @@ -345,7 +344,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyEnumeration", "PatternCenterAt", "Clearing Options", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Choose location of the center point for starting the cut pattern.", ), @@ -354,7 +353,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyEnumeration", "ProfileEdges", "Clearing Options", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Profile the edges of the selection." ), ), @@ -362,7 +361,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyDistance", "SampleInterval", "Clearing Options", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Set the sampling resolution. Smaller values quickly increase processing time.", ), @@ -371,7 +370,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyFloat", "StepOver", "Clearing Options", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Set the stepover percentage, based on the tool's diameter.", ), @@ -380,7 +379,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyBool", "OptimizeLinearPaths", "Optimization", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Enable optimization of linear paths (co-linear points). Removes unnecessary co-linear points from G-Code output.", ), @@ -389,7 +388,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyBool", "OptimizeStepOverTransitions", "Optimization", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Enable separate optimization of transitions between, and breaks within, each step over path.", ), @@ -398,7 +397,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyBool", "CircularUseG2G3", "Optimization", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Convert co-planar arcs to G2/G3 gcode commands for `Circular` and `CircularZigZag` cut patterns.", ), @@ -407,7 +406,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyDistance", "GapThreshold", "Optimization", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Collinear and co-radial artifact gaps that are smaller than this threshold are closed in the path.", ), @@ -416,7 +415,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyString", "GapSizes", "Optimization", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Feedback: three smallest gaps identified in the path geometry.", ), @@ -425,7 +424,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyVectorDistance", "StartPoint", "Start Point", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "The custom start point for the path of this operation", ), @@ -434,39 +433,116 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyBool", "UseStartPoint", "Start Point", - QtCore.QT_TRANSLATE_NOOP( + QT_TRANSLATE_NOOP( "App::Property", "Make True, if specifying a Start Point" ), ), ] - def opPropertyEnumerations(self): + @classmethod + def propertyEnumerations(self, dataType="data"): + """propertyEnumerations(dataType="data")... return property enumeration lists of specified dataType. + Args: + dataType = 'data', 'raw', 'translated' + Notes: + 'data' is list of internal string literals used in code + 'raw' is list of (translated_text, data_string) tuples + 'translated' is list of translated string literals + """ + # Enumeration lists for App::PropertyEnumeration properties - return { - "BoundBox": ["BaseBoundBox", "Stock"], + enums = { + "BoundBox": [ + (translate("Path_Surface", "Outside"), "Outside"), + (translate("Path_Surface", "Inside"), "Inside"), + ], # this is the direction that the profile runs "PatternCenterAt": [ - "CenterOfMass", - "CenterOfBoundBox", - "XminYmin", - "Custom", - ], - "CutMode": ["Conventional", "Climb"], + (translate("Path_Surface", "CenterOfMass"), "CenterOfMass"), + (translate("Path_Surface", "CenterOfBoundBox"), "CenterOfBoundBox"), + (translate("Path_Surface", "XminYmin"), "XminYmin"), + (translate("Path_Surface", "Custom"), "Custom"), + ], # side of profile that cutter is on in relation to direction of profile + "CutMode": [ + (translate("Path_Surface", "Conventional"), "Conventional"), + (translate("Path_Surface", "Climb"), "Climb"), + ], # side of profile that cutter is on in relation to direction of profile "CutPattern": [ - "Circular", - "CircularZigZag", - "Line", - "Offset", - "Spiral", - "ZigZag", - ], # Additional goals ['Offset', 'ZigZagOffset', 'Grid', 'Triangle'] - "DropCutterDir": ["X", "Y"], - "HandleMultipleFeatures": ["Collectively", "Individually"], - "LayerMode": ["Single-pass", "Multi-pass"], - "ProfileEdges": ["None", "Only", "First", "Last"], - "RotationAxis": ["X", "Y"], - "ScanType": ["Planar", "Rotational"], + (translate("Path_Surface", "Circular"), "Circular"), + (translate("Path_Surface", "CircularZigZag"), "CircularZigZag"), + (translate("Path_Surface", "Line"), "Line"), + (translate("Path_Surface", "Offset"), "Offset"), + (translate("Path_Surface", "Spiral"), "Spiral"), + (translate("Path_Surface", "ZigZag"), "ZigZag"), + ], # side of profile that cutter is on in relation to direction of profile + "DropCutterDir": [ + (translate("Path_Surface", "X"), "X"), + (translate("Path_Surface", "Y"), "Y"), + ], # side of profile that cutter is on in relation to direction of profile + "HandleMultipleFeatures": [ + (translate("Path_Surface", "Collectively"), "Collectively"), + (translate("Path_Surface", "Individually"), "Individually"), + ], # side of profile that cutter is on in relation to direction of profile + "LayerMode": [ + (translate("Path_Surface", "Single-pass"), "Single-pass"), + (translate("Path_Surface", "Multi-pass"), "Multi-pass"), + ], # side of profile that cutter is on in relation to direction of profile + "ProfileEdges": [ + (translate("Path_Surface", "None"), "None"), + (translate("Path_Surface", "Only"), "Only"), + (translate("Path_Surface", "First"), "First"), + (translate("Path_Surface", "Last"), "Last"), + ], # side of profile that cutter is on in relation to direction of profile + "RotationAxis": [ + (translate("Path_Surface", "X"), "X"), + (translate("Path_Surface", "Y"), "Y"), + ], # side of profile that cutter is on in relation to direction of profile + "ScanType": [ + (translate("Path_Surface", "Planar"), "Planar"), + (translate("Path_Surface", "Rotational"), "Rotational"), + ], # side of profile that cutter is on in relation to direction of profile } + if dataType == "raw": + return enums + + data = list() + idx = 0 if dataType == "translated" else 1 + + PathLog.debug(enums) + + for k, v in enumerate(enums): + data.append((v, [tup[idx] for tup in enums[v]])) + PathLog.debug(data) + + return data + + # def opPropertyEnumerations(self): + # # Enumeration lists for App::PropertyEnumeration properties + # return { + # "BoundBox": ["BaseBoundBox", "Stock"], + # "PatternCenterAt": [ + # "CenterOfMass", + # "CenterOfBoundBox", + # "XminYmin", + # "Custom", + # ], + # "CutMode": ["Conventional", "Climb"], + # "CutPattern": [ + # "Circular", + # "CircularZigZag", + # "Line", + # "Offset", + # "Spiral", + # "ZigZag", + # ], # Additional goals ['Offset', 'ZigZagOffset', 'Grid', 'Triangle'] + # "DropCutterDir": ["X", "Y"], + # "HandleMultipleFeatures": ["Collectively", "Individually"], + # "LayerMode": ["Single-pass", "Multi-pass"], + # "ProfileEdges": ["None", "Only", "First", "Last"], + # "RotationAxis": ["X", "Y"], + # "ScanType": ["Planar", "Rotational"], + # } + def opPropertyDefaults(self, obj, job): """opPropertyDefaults(obj, job) ... returns a dictionary of default values for the operation's properties.""" @@ -646,32 +722,20 @@ class ObjectSurface(PathOp.ObjectOp): # Limit sample interval if obj.SampleInterval.Value < 0.0001: obj.SampleInterval.Value = 0.0001 - PathLog.error( - translate( - "PathSurface", - "Sample interval limits are 0.001 to 25.4 millimeters.", - ) - ) + PathLog.error("Sample interval limits are 0.001 to 25.4 millimeters.") + if obj.SampleInterval.Value > 25.4: obj.SampleInterval.Value = 25.4 - PathLog.error( - translate( - "PathSurface", - "Sample interval limits are 0.001 to 25.4 millimeters.", - ) - ) + PathLog.error("Sample interval limits are 0.001 to 25.4 millimeters.") # Limit cut pattern angle if obj.CutPatternAngle < -360.0: obj.CutPatternAngle = 0.0 - PathLog.error( - translate("PathSurface", "Cut pattern angle limits are +-360 degrees.") - ) + PathLog.error("Cut pattern angle limits are +-360 degrees.") + if obj.CutPatternAngle >= 360.0: obj.CutPatternAngle = 0.0 - PathLog.error( - translate("PathSurface", "Cut pattern angle limits are +- 360 degrees.") - ) + PathLog.error("Cut pattern angle limits are +- 360 degrees.") # Limit StepOver to natural number percentage if obj.StepOver > 100.0: @@ -682,20 +746,11 @@ class ObjectSurface(PathOp.ObjectOp): # Limit AvoidLastX_Faces to zero and positive values if obj.AvoidLastX_Faces < 0: obj.AvoidLastX_Faces = 0 - PathLog.error( - translate( - "PathSurface", - "AvoidLastX_Faces: Only zero or positive values permitted.", - ) - ) + PathLog.error("AvoidLastX_Faces: Only zero or positive values permitted.") + if obj.AvoidLastX_Faces > 100: obj.AvoidLastX_Faces = 100 - PathLog.error( - translate( - "PathSurface", - "AvoidLastX_Faces: Avoid last X faces count limited to 100.", - ) - ) + PathLog.error("AvoidLastX_Faces: Avoid last X faces count limited to 100.") def opUpdateDepths(self, obj): if hasattr(obj, "Base") and obj.Base: diff --git a/src/Mod/Path/PathScripts/PathSurfaceGui.py b/src/Mod/Path/PathScripts/PathSurfaceGui.py index e3bc454c63..81747fb26a 100644 --- a/src/Mod/Path/PathScripts/PathSurfaceGui.py +++ b/src/Mod/Path/PathScripts/PathSurfaceGui.py @@ -20,20 +20,29 @@ # * * # *************************************************************************** +from PySide import QtCore import FreeCAD import FreeCADGui +import PathScripts.PathLog as PathLog import PathGui as PGui # ensure Path/Gui/Resources are loaded -import PathScripts.PathSurface as PathSurface import PathScripts.PathGui as PathGui import PathScripts.PathOpGui as PathOpGui +import PathScripts.PathSurface as PathSurface -from PySide import QtCore __title__ = "Path Surface Operation UI" __author__ = "sliptonic (Brad Collette)" __url__ = "https://www.freecadweb.org" __doc__ = "Surface operation page controller and command implementation." +translate = FreeCAD.Qt.translate + +if False: + PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) + PathLog.trackModule(PathLog.thisModule()) +else: + PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + class TaskPanelOpPage(PathOpGui.TaskPanelPage): """Page controller class for the Surface operation.""" @@ -46,21 +55,46 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): def getForm(self): """getForm() ... returns UI""" - return FreeCADGui.PySideUic.loadUi(":/panels/PageOpSurfaceEdit.ui") + form = FreeCADGui.PySideUic.loadUi(":/panels/PageOpSurfaceEdit.ui") + comboToPropertyMap = [ + ("boundBoxSelect", "BoundBox"), + ("scanType", "ScanType"), + ("layerMode", "LayerMode"), + ("dropCutterDirSelect", "DropCutterDir"), + ] + enumTups = PathSurface.ObjectSurface.propertyEnumerations(dataType="raw") + self.populateCombobox(form, enumTups, comboToPropertyMap) + + return form + + def populateCombobox(self, form, enumTups, comboBoxesPropertyMap): + """fillComboboxes(form, comboBoxesPropertyMap) ... populate comboboxes with translated enumerations + ** comboBoxesPropertyMap will be unnecessary if UI files use strict combobox naming protocol. + Args: + form = UI form + enumTups = list of (translated_text, data_string) tuples + comboBoxesPropertyMap = list of (translated_text, data_string) tuples + """ + # Load appropriate enumerations in each combobox + for cb, prop in comboBoxesPropertyMap: + box = getattr(form, cb) # Get the combobox + box.clear() # clear the combobox + for text, data in enumTups[prop]: # load enumerations + box.addItem(text, data) def getFields(self, obj): """getFields(obj) ... transfers values from UI to obj's proprties""" self.updateToolController(obj, self.form.toolController) self.updateCoolant(obj, self.form.coolantController) - if obj.BoundBox != str(self.form.boundBoxSelect.currentText()): - obj.BoundBox = str(self.form.boundBoxSelect.currentText()) + if obj.BoundBox != str(self.form.boundBoxSelect.currentData()): + obj.BoundBox = str(self.form.boundBoxSelect.currentData()) - if obj.ScanType != str(self.form.scanType.currentText()): - obj.ScanType = str(self.form.scanType.currentText()) + if obj.ScanType != str(self.form.scanType.currentData()): + obj.ScanType = str(self.form.scanType.currentData()) - if obj.LayerMode != str(self.form.layerMode.currentText()): - obj.LayerMode = str(self.form.layerMode.currentText()) + if obj.LayerMode != str(self.form.layerMode.currentData()): + obj.LayerMode = str(self.form.layerMode.currentData()) """ The following method of getting values from the UI form @@ -92,8 +126,8 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): self.form.boundBoxExtraOffsetY.text() ).Value - if obj.DropCutterDir != str(self.form.dropCutterDirSelect.currentText()): - obj.DropCutterDir = str(self.form.dropCutterDirSelect.currentText()) + if obj.DropCutterDir != str(self.form.dropCutterDirSelect.currentData()): + obj.DropCutterDir = str(self.form.dropCutterDirSelect.currentData()) PathGui.updateInputField(obj, "DepthOffset", self.form.depthOffset) @@ -253,7 +287,7 @@ Command = PathOpGui.SetupOperation( "Surface", PathSurface.Create, TaskPanelOpPage, - "Path_3DSurface", + "Path_Surface", QtCore.QT_TRANSLATE_NOOP("Path_Surface", "3D Surface"), QtCore.QT_TRANSLATE_NOOP( "Path_Surface", "Create a 3D Surface Operation from a model" diff --git a/src/Mod/Path/PathScripts/PathSurfaceSupport.py b/src/Mod/Path/PathScripts/PathSurfaceSupport.py index 9369faa26d..e064a5022e 100644 --- a/src/Mod/Path/PathScripts/PathSurfaceSupport.py +++ b/src/Mod/Path/PathScripts/PathSurfaceSupport.py @@ -29,8 +29,6 @@ __doc__ = "Support functions and classes for 3D Surface and Waterline operations __contributors__ = "" import FreeCAD -from PySide import QtCore -import Path import PathScripts.PathLog as PathLog import PathScripts.PathUtils as PathUtils import PathScripts.PathOpTools as PathOpTools @@ -43,13 +41,14 @@ from lazy_loader.lazy_loader import LazyLoader Part = LazyLoader("Part", globals(), "Part") -PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -# PathLog.trackModule(PathLog.thisModule()) +if False: + PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) + PathLog.trackModule(PathLog.thisModule()) +else: + PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -# Qt translation handling -def translate(context, text, disambig=None): - return QtCore.QCoreApplication.translate(context, text, disambig) +translate = FreeCAD.Qt.translate class PathGeometryGenerator: @@ -217,7 +216,7 @@ class PathGeometryGenerator: # Cut pattern methods def _Circular(self): - GeoSet = list() + GeoSet = [] radialPasses = self._getRadialPasses() minRad = self.toolDiam * 0.45 siX3 = 3 * self.obj.SampleInterval.Value @@ -244,13 +243,13 @@ class PathGeometryGenerator: self._Circular() # Use _Circular generator def _Line(self): - GeoSet = list() + GeoSet = [] centRot = FreeCAD.Vector( 0.0, 0.0, 0.0 ) # Bottom left corner of face/selection/model # Create end points for set of lines to intersect with cross-section face - pntTuples = list() + pntTuples = [] for lc in range((-1 * (self.halfPasses - 1)), self.halfPasses + 1): x1 = centRot.x - self.halfDiag x2 = centRot.x + self.halfDiag @@ -271,8 +270,8 @@ class PathGeometryGenerator: self.rawGeoList = self._extractOffsetFaces() def _Spiral(self): - GeoSet = list() - SEGS = list() + GeoSet = [] + SEGS = [] draw = True loopRadians = 0.0 # Used to keep track of complete loops/cycles sumRadians = 0.0 @@ -420,7 +419,7 @@ class PathGeometryGenerator: def _extractOffsetFaces(self): PathLog.debug("_extractOffsetFaces()") - wires = list() + wires = [] shape = self.shape offset = 0.0 # Start right at the edge of cut area direction = 0 @@ -432,7 +431,7 @@ class PathGeometryGenerator: return -1 def _reverse_wire(w): - rev_list = list() + rev_list = [] for e in w.Edges: rev_list.append(PathUtils.reverseEdge(e)) rev_list.reverse() @@ -494,8 +493,8 @@ class ProcessSelectedFaces: two compound objects as a tuple: (FACES, VOIDS) or False.""" def __init__(self, JOB, obj): - self.modelSTLs = list() - self.profileShapes = list() + self.modelSTLs = [] + self.profileShapes = [] self.tempGroup = False self.showDebugObjects = False self.checkBase = False @@ -554,10 +553,10 @@ class ProcessSelectedFaces: if not self._isReady(module): return False - FACES = list() - VOIDS = list() - fShapes = list() - vShapes = list() + FACES = [] + VOIDS = [] + fShapes = [] + vShapes = [] GRP = self.JOB.Model.Group lenGRP = len(GRP) proceed = False @@ -669,7 +668,7 @@ class ProcessSelectedFaces: return True def _identifyFacesAndVoids(self, F, V): - TUPS = list() + TUPS = [] GRP = self.JOB.Model.Group lenGRP = len(GRP) hasFace = False @@ -697,13 +696,13 @@ class ProcessSelectedFaces: faceIdx = int(sub[4:]) - 1 if bst < add: if F[m] is False: - F[m] = list() + F[m] = [] F[m].append((shape, faceIdx)) PathLog.debug(".. Cutting {}".format(sub)) hasFace = True else: if V[m] is False: - V[m] = list() + V[m] = [] V[m].append((shape, faceIdx)) PathLog.debug(".. Avoiding {}".format(sub)) hasVoid = True @@ -713,7 +712,7 @@ class ProcessSelectedFaces: mFS = False mVS = False mPS = False - mIFS = list() + mIFS = [] if FCS: isHole = False @@ -722,15 +721,11 @@ class ProcessSelectedFaces: PathLog.debug("Attempting to get cross-section of collective faces.") outFCS, ifL = self.findUnifiedRegions(FCS) if self.obj.InternalFeaturesCut and ifL: - ifL = list() # clear avoid shape list + ifL = [] # clear avoid shape list if len(outFCS) == 0: - msg = translate( - "PathSurfaceSupport", - "Cannot process selected faces. Check horizontal " - "surface exposure.", - ) - FreeCAD.Console.PrintError(msg + "\n") + msg = "PathSurfaceSupport \n Cannot process selected faces. Check horizontal \n surface exposure.\n" + FreeCAD.Console.PrintError(msg) cont = False else: cfsL = Part.makeCompound(outFCS) @@ -760,12 +755,7 @@ class ProcessSelectedFaces: ofstVal = self._calculateOffsetValue(isHole) faceOfstShp = PathUtils.getOffsetArea(cfsL, ofstVal, plane=self.wpc) if not faceOfstShp: - msg = ( - translate( - "PathSurfaceSupport", "Failed to create offset face." - ) - + "\n" - ) + msg = "Failed to create offset face." FreeCAD.Console.PrintError(msg) cont = False @@ -805,7 +795,7 @@ class ProcessSelectedFaces: if len(gUR) > 0: outerFace = gUR[0] if self.obj.InternalFeaturesCut: - ifL = list() # avoid shape list + ifL = [] # avoid shape list if outerFace: PathLog.debug( @@ -819,11 +809,11 @@ class ProcessSelectedFaces: ) if psOfst: if mPS is False: - mPS = list() + mPS = [] mPS.append(psOfst) if self.profileEdges == "Only": if mFS is False: - mFS = list() + mFS = [] mFS.append(True) cont = False else: @@ -850,7 +840,7 @@ class ProcessSelectedFaces: # faceOfstShp = faceOfstShp.cut(intOfstShp) if mFS is False: - mFS = list() + mFS = [] mFS.append(faceOfstShp) # Eif # Efor @@ -859,7 +849,7 @@ class ProcessSelectedFaces: if len(mIFS) > 0: if mVS is False: - mVS = list() + mVS = [] for ifs in mIFS: mVS.append(ifs) @@ -870,7 +860,7 @@ class ProcessSelectedFaces: outFCS, intFEAT = self.findUnifiedRegions(VDS) if self.obj.InternalFeaturesCut: - intFEAT = list() + intFEAT = [] lenOtFcs = len(outFCS) if lenOtFcs == 0: @@ -900,11 +890,8 @@ class ProcessSelectedFaces: ofstVal = self._calculateOffsetValue(isHole, isVoid=True) avdOfstShp = PathUtils.getOffsetArea(avoid, ofstVal, plane=self.wpc) if avdOfstShp is False: - msg = translate( - "PathSurfaceSupport", - "Failed to create collective offset avoid face.", - ) - FreeCAD.Console.PrintError(msg + "\n") + msg = "Failed to create collective offset avoid face.\n" + FreeCAD.Console.PrintError(msg) cont = False if cont: @@ -918,19 +905,13 @@ class ProcessSelectedFaces: ofstVal = self._calculateOffsetValue(isHole=True) ifOfstShp = PathUtils.getOffsetArea(ifc, ofstVal, plane=self.wpc) if ifOfstShp is False: - msg = ( - translate( - "PathSurfaceSupport", - "Failed to create collective offset avoid internal features.", - ) - + "\n" - ) + msg = "Failed to create collective offset avoid internal features.\n" FreeCAD.Console.PrintError(msg) else: avdShp = avdOfstShp.cut(ifOfstShp) if mVS is False: - mVS = list() + mVS = [] mVS.append(avdShp) return (mFS, mVS, mPS) @@ -1123,7 +1104,7 @@ def getShapeSlice(shape): slc.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - slc.BoundBox.ZMin)) return slc else: - fL = list() + fL = [] for W in slcShp.Wires: slc = Part.Face(W) slc.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - slc.BoundBox.ZMin)) @@ -1161,7 +1142,7 @@ def getProjectedFace(tempGroup, wire): def getCrossSection(shape): PathLog.debug("getCrossSection()") - wires = list() + wires = [] bb = shape.BoundBox mid = (bb.ZMin + bb.ZMax) / 2.0 @@ -1212,7 +1193,7 @@ def getSliceFromEnvelope(env): maxz = eBB.ZMin + extFwd emax = math.floor(maxz - 1.0) - E = list() + E = [] for e in range(0, len(env.Edges)): emin = env.Edges[e].BoundBox.ZMin if emin > emax: @@ -1240,7 +1221,7 @@ def _makeSafeSTL(self, JOB, obj, mdlIdx, faceShapes, voidShapes, ocl): STL object to determine minimum travel height to clear stock and model.""" PathLog.debug("_makeSafeSTL()") - fuseShapes = list() + fuseShapes = [] Mdl = JOB.Model.Group[mdlIdx] mBB = Mdl.Shape.BoundBox sBB = JOB.Stock.Shape.BoundBox @@ -1287,11 +1268,8 @@ def _makeSafeSTL(self, JOB, obj, mdlIdx, faceShapes, voidShapes, ocl): adjStckWst = stckWst fuseShapes.append(adjStckWst) else: - msg = translate( - "PathSurfaceSupport", - "Path transitions might not avoid the model. Verify paths.", - ) - FreeCAD.Console.PrintWarning(msg + "\n") + msg = "Path transitions might not avoid the model. Verify paths.\n" + FreeCAD.Console.PrintWarning(msg) else: # If boundbox is Job.Stock, add hidden pad under stock as base plate toolDiam = self.cutter.getDiameter() @@ -1355,9 +1333,9 @@ def pathGeomToLinesPointSet(self, obj, compGeoShp): """pathGeomToLinesPointSet(self, obj, compGeoShp)... Convert a compound set of sequential line segments to directionally-oriented collinear groupings.""" PathLog.debug("pathGeomToLinesPointSet()") - # Extract intersection line segments for return value as list() - LINES = list() - inLine = list() + # Extract intersection line segments for return value as [] + LINES = [] + inLine = [] chkGap = False lnCnt = 0 ec = len(compGeoShp.Edges) @@ -1393,7 +1371,7 @@ def pathGeomToLinesPointSet(self, obj, compGeoShp): inLine.reverse() LINES.append(inLine) # Save inLine segments lnCnt += 1 - inLine = list() # reset collinear container + inLine = [] # reset collinear container if self.CutClimb is True: sp = cp # FreeCAD.Vector(v1[0], v1[1], 0.0) else: @@ -1438,7 +1416,7 @@ def pathGeomToLinesPointSet(self, obj, compGeoShp): if obj.CutPatternReversed is True: if cpa != 0.0 and cpa % 90.0 == 0.0: F = LINES.pop(0) - rev = list() + rev = [] for iL in F: if iL == "BRK": rev.append(iL) @@ -1462,9 +1440,9 @@ def pathGeomToZigzagPointSet(self, obj, compGeoShp): Convert a compound set of sequential line segments to directionally-oriented collinear groupings with a ZigZag directional indicator included for each collinear group.""" PathLog.debug("_pathGeomToZigzagPointSet()") - # Extract intersection line segments for return value as list() - LINES = list() - inLine = list() + # Extract intersection line segments for return value as [] + LINES = [] + inLine = [] lnCnt = 0 chkGap = False ec = len(compGeoShp.Edges) @@ -1505,7 +1483,7 @@ def pathGeomToZigzagPointSet(self, obj, compGeoShp): LINES.append(inLine) lnCnt += 1 dirFlg = -1 * dirFlg # Change zig to zag - inLine = list() # reset collinear container + inLine = [] # reset collinear container sp = cp # FreeCAD.Vector(v1[0], v1[1], 0.0) lst = ep @@ -1553,7 +1531,7 @@ def pathGeomToZigzagPointSet(self, obj, compGeoShp): # Handle last inLine list if dirFlg == 1: - rev = list() + rev = [] for iL in inLine: if iL == "BRK": rev.append(iL) @@ -1564,7 +1542,7 @@ def pathGeomToZigzagPointSet(self, obj, compGeoShp): if not obj.CutPatternReversed: rev.reverse() else: - rev2 = list() + rev2 = [] for iL in rev: if iL == "BRK": rev2.append(iL) @@ -1584,11 +1562,11 @@ def pathGeomToCircularPointSet(self, obj, compGeoShp): """pathGeomToCircularPointSet(self, obj, compGeoShp)... Convert a compound set of arcs/circles to a set of directionally-oriented arc end points and the corresponding center point.""" - # Extract intersection line segments for return value as list() + # Extract intersection line segments for return value as [] PathLog.debug("pathGeomToCircularPointSet()") - ARCS = list() - stpOvrEI = list() - segEI = list() + ARCS = [] + stpOvrEI = [] + segEI = [] isSame = False sameRad = None ec = len(compGeoShp.Edges) @@ -1649,8 +1627,8 @@ def pathGeomToCircularPointSet(self, obj, compGeoShp): for so in range(0, len(stpOvrEI)): SO = stpOvrEI[so] if SO[0] == "A": - startOnAxis = list() - endOnAxis = list() + startOnAxis = [] + endOnAxis = [] EI = SO[1] # list of corresponding compGeoShp.Edges indexes # Identify startOnAxis and endOnAxis arcs @@ -1728,7 +1706,7 @@ def pathGeomToCircularPointSet(self, obj, compGeoShp): ARCS.append(("L", dirFlg, [arc])) elif SO[0] == "A": # A = Arc # PathLog.debug("SO[0] == 'Arc'") - PRTS = list() + PRTS = [] EI = SO[1] # list of corresponding Edges indexes CONN = SO[2] # list of corresponding connected edges tuples (iE, iS) chkGap = False @@ -1828,9 +1806,9 @@ def pathGeomToSpiralPointSet(obj, compGeoShp): """_pathGeomToSpiralPointSet(obj, compGeoShp)... Convert a compound set of sequential line segments to directional, connected groupings.""" PathLog.debug("_pathGeomToSpiralPointSet()") - # Extract intersection line segments for return value as list() - LINES = list() - inLine = list() + # Extract intersection line segments for return value as [] + LINES = [] + inLine = [] lnCnt = 0 ec = len(compGeoShp.Edges) start = 2 @@ -1865,7 +1843,7 @@ def pathGeomToSpiralPointSet(obj, compGeoShp): else: LINES.append(inLine) # Save inLine segments lnCnt += 1 - inLine = list() # reset container + inLine = [] # reset container inLine.append(tup) # p1 = sp p2 = ep @@ -1882,7 +1860,7 @@ def pathGeomToOffsetPointSet(obj, compGeoShp): Convert a compound set of 3D profile segmented wires to 2D segments, applying linear optimization.""" PathLog.debug("pathGeomToOffsetPointSet()") - LINES = list() + LINES = [] optimize = obj.OptimizeLinearPaths ofstCnt = len(compGeoShp) @@ -1934,15 +1912,15 @@ class FindUnifiedRegions: self.FACES = facesList # format is tuple (faceShape, faceIndex_on_base) self.geomToler = geomToler self.tempGroup = None - self.topFaces = list() - self.edgeData = list() - self.circleData = list() + self.topFaces = [] + self.edgeData = [] + self.circleData = [] self.noSharedEdges = True - self.topWires = list() - self.REGIONS = list() - self.INTERNALS = list() - self.idGroups = list() - self.sharedEdgeIdxs = list() + self.topWires = [] + self.REGIONS = [] + self.INTERNALS = [] + self.idGroups = [] + self.sharedEdgeIdxs = [] self.fusedFaces = None self.internalsReady = False @@ -2011,11 +1989,10 @@ class FindUnifiedRegions: tfBB_Area = tfBB.XLength * tfBB.YLength # self._showShape(topFace, 'topFaceAlt_2_{}'.format(fNum)) if tfBB_Area < (fBB_Area * 0.9): - msg = translate( - "PathSurfaceSupport", - "Faild to extract processing region for Face", + msg = "Faild to extract processing region for Face {}\n".format( + fNum ) - FreeCAD.Console.PrintError(msg + "{}.\n".format(fNum)) + FreeCAD.Console.PrintError(msg) cont = False # Eif @@ -2053,7 +2030,7 @@ class FindUnifiedRegions: def _groupEdgesByLength(self): PathLog.debug("_groupEdgesByLength()") threshold = self.geomToler - grp = list() + grp = [] processLast = False def keyFirst(tup): @@ -2089,7 +2066,7 @@ class FindUnifiedRegions: if len(grp) > 1: # grp.sort() self.idGroups.append(grp) - grp = list() + grp = [] break # Ewhile # Ewhile @@ -2100,7 +2077,7 @@ class FindUnifiedRegions: def _identifySharedEdgesByLength(self, grp): PathLog.debug("_identifySharedEdgesByLength()") - holds = list() + holds = [] specialIndexes = [] threshold = self.geomToler @@ -2148,7 +2125,7 @@ class FindUnifiedRegions: holds.extend(grp) grp = holds lenGrp = len(grp) - holds = list() + holds = [] if len(specialIndexes) > 0: # Remove shared edges from EDGES data @@ -2159,13 +2136,13 @@ class FindUnifiedRegions: def _extractWiresFromEdges(self): PathLog.debug("_extractWiresFromEdges()") DATA = self.edgeData - holds = list() + holds = [] firstEdge = None cont = True connectedEdges = [] connectedIndexes = [] connectedCnt = 0 - LOOPS = list() + LOOPS = [] def faceIndex(tup): return tup[3] @@ -2246,7 +2223,7 @@ class FindUnifiedRegions: holds.extend(indexes) indexes = holds idxCnt = len(indexes) - holds = list() + holds = [] if idxCnt == 0: cont = False if safety == 0: @@ -2284,7 +2261,7 @@ class FindUnifiedRegions: def _identifyInternalFeatures(self): PathLog.debug("_identifyInternalFeatures()") - remList = list() + remList = [] for (top, fcIdx) in self.topFaces: big = Part.Face(top.OuterWire) @@ -2307,9 +2284,9 @@ class FindUnifiedRegions: def _processNestedRegions(self): PathLog.debug("_processNestedRegions()") cont = True - hold = list() - Ids = list() - remList = list() + hold = [] + Ids = [] + remList = [] for i in range(0, len(self.REGIONS)): Ids.append(i) idsCnt = len(Ids) @@ -2338,7 +2315,7 @@ class FindUnifiedRegions: # Ewhile hold.extend(Ids) Ids = hold - hold = list() + hold = [] idsCnt = len(Ids) if len(Ids) == 0: cont = False @@ -2351,7 +2328,7 @@ class FindUnifiedRegions: # Accessory methods def _getCompleteCrossSection(self, shape): PathLog.debug("_getCompleteCrossSection()") - wires = list() + wires = [] bb = shape.BoundBox mid = (bb.ZMin + bb.ZMax) / 2.0 @@ -2409,11 +2386,8 @@ class FindUnifiedRegions: of tuples (faceShape, faceIndex) received at instantiation of the class object.""" PathLog.debug("getUnifiedRegions()") if len(self.FACES) == 0: - msg = translate( - "PathSurfaceSupport", - "No FACE data tuples received at instantiation of class.", - ) - FreeCAD.Console.PrintError(msg + "\n") + msg = "No FACE data tuples received at instantiation of class.\n" + FreeCAD.Console.PrintError(msg) return [] self._extractTopFaces() @@ -2460,7 +2434,7 @@ class FindUnifiedRegions: if self.noSharedEdges: PathLog.debug("No shared edges by length detected.") - allTopFaces = list() + allTopFaces = [] for (topFace, fcIdx) in self.topFaces: allTopFaces.append(topFace) # Identify internal features @@ -2495,17 +2469,11 @@ class FindUnifiedRegions: else: return False - msg = translate( - "PathSurfaceSupport", - "getUnifiedRegions() must be called before getInternalFeatures().", - ) - FreeCAD.Console.PrintError(msg + "\n") + msg = "getUnifiedRegions() must be called before getInternalFeatures().\n" + FreeCAD.Console.PrintError(msg) return False -# Eclass - - class OCL_Tool: """The OCL_Tool class is designed to translate a FreeCAD standard ToolBit shape, or Legacy tool type, in the active Tool Controller, into an OCL tool type."""