diff --git a/src/Mod/Path/PathScripts/PathDeburr.py b/src/Mod/Path/PathScripts/PathDeburr.py index fbfdf7cf02..45c92b9676 100644 --- a/src/Mod/Path/PathScripts/PathDeburr.py +++ b/src/Mod/Path/PathScripts/PathDeburr.py @@ -29,54 +29,68 @@ import PathScripts.PathOp as PathOp import PathScripts.PathOpTools as PathOpTools import math -from PySide import QtCore +from PySide.QtCore import QT_TRANSLATE_NOOP # lazily loaded modules from lazy_loader.lazy_loader import LazyLoader -Part = LazyLoader('Part', globals(), 'Part') + +Part = LazyLoader("Part", globals(), "Part") __title__ = "Path Deburr Operation" __author__ = "sliptonic (Brad Collette), Schildkroet" __url__ = "http://www.freecadweb.org" __doc__ = "Deburr operation." -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 def toolDepthAndOffset(width, extraDepth, tool, printInfo): - '''toolDepthAndOffset(width, extraDepth, tool) ... return tuple for given\n - parameters.''' + """toolDepthAndOffset(width, extraDepth, tool) ... return tuple for given\n + parameters.""" - if not hasattr(tool, 'Diameter'): - raise ValueError('Deburr requires tool with diameter\n') + if not hasattr(tool, "Diameter"): + raise ValueError("Deburr requires tool with diameter\n") suppressInfo = False - if hasattr(tool, 'CuttingEdgeAngle'): + if hasattr(tool, "CuttingEdgeAngle"): angle = float(tool.CuttingEdgeAngle) if PathGeom.isRoughly(angle, 180) or PathGeom.isRoughly(angle, 0): angle = 180 toolOffset = float(tool.Diameter) / 2 else: - if hasattr(tool, 'TipDiameter'): + if hasattr(tool, "TipDiameter"): toolOffset = float(tool.TipDiameter) / 2 - elif hasattr(tool, 'FlatRadius'): + elif hasattr(tool, "FlatRadius"): toolOffset = float(tool.FlatRadius) else: toolOffset = 0.0 if printInfo and not suppressInfo: - FreeCAD.Console.PrintMessage(translate('PathDeburr', "The selected tool has no FlatRadius and no TipDiameter property. Assuming {}\n".format("Endmill" if angle == 180 else "V-Bit"))) + FreeCAD.Console.PrintMessage( + translate( + "PathDeburr", + "The selected tool has no FlatRadius and no TipDiameter property. Assuming {}\n".format( + "Endmill" if angle == 180 else "V-Bit" + ), + ) + ) suppressInfo = True else: angle = 180 toolOffset = float(tool.Diameter) / 2 if printInfo: - FreeCAD.Console.PrintMessage(translate('PathDeburr', 'The selected tool has no CuttingEdgeAngle property. Assuming Endmill\n')) + FreeCAD.Console.PrintMessage( + translate( + "PathDeburr", + "The selected tool has no CuttingEdgeAngle property. Assuming Endmill\n", + ) + ) suppressInfo = True tan = math.tan(math.radians(angle / 2)) @@ -90,40 +104,119 @@ def toolDepthAndOffset(width, extraDepth, tool, printInfo): class ObjectDeburr(PathEngraveBase.ObjectOp): - '''Proxy class for Deburr operation.''' + """Proxy class for Deburr operation.""" def opFeatures(self, obj): - return PathOp.FeatureTool | PathOp.FeatureHeights | PathOp.FeatureStepDown | PathOp.FeatureBaseEdges | PathOp.FeatureBaseFaces | PathOp.FeatureCoolant | PathOp.FeatureBaseGeometry + return ( + PathOp.FeatureTool + | PathOp.FeatureHeights + | PathOp.FeatureStepDown + | PathOp.FeatureBaseEdges + | PathOp.FeatureBaseFaces + | PathOp.FeatureCoolant + | PathOp.FeatureBaseGeometry + ) def initOperation(self, obj): PathLog.track(obj.Label) - obj.addProperty('App::PropertyDistance', 'Width', 'Deburr', - QtCore.QT_TRANSLATE_NOOP('PathDeburr', 'The desired width of the chamfer')) - obj.addProperty('App::PropertyDistance', 'ExtraDepth', 'Deburr', - QtCore.QT_TRANSLATE_NOOP('PathDeburr', 'The additional depth of the tool path')) - obj.addProperty('App::PropertyEnumeration', 'Join', 'Deburr', - QtCore.QT_TRANSLATE_NOOP('PathDeburr', 'How to join chamfer segments')) - obj.Join = ['Round', 'Miter'] - obj.setEditorMode('Join', 2) # hide for now - obj.addProperty('App::PropertyEnumeration', 'Direction', 'Deburr', - QtCore.QT_TRANSLATE_NOOP('PathDeburr', 'Direction of Operation')) - obj.Direction = ['CW', 'CCW'] - obj.addProperty('App::PropertyEnumeration', 'Side', 'Deburr', - QtCore.QT_TRANSLATE_NOOP('PathDeburr', 'Side of Operation')) - obj.Side = ['Outside', 'Inside'] - obj.setEditorMode('Side', 2) # Hide property, it's calculated by op - obj.addProperty('App::PropertyInteger', 'EntryPoint', 'Deburr', - QtCore.QT_TRANSLATE_NOOP('PathDeburr', 'Select the segment, there the operations starts')) + obj.addProperty( + "App::PropertyDistance", + "Width", + "Deburr", + QT_TRANSLATE_NOOP("App::Property", "The desired width of the chamfer"), + ) + obj.addProperty( + "App::PropertyDistance", + "ExtraDepth", + "Deburr", + QT_TRANSLATE_NOOP("App::Property", "The additional depth of the tool path"), + ) + obj.addProperty( + "App::PropertyEnumeration", + "Join", + "Deburr", + QT_TRANSLATE_NOOP("App::Property", "How to join chamfer segments"), + ) + # obj.Join = ["Round", "Miter"] + obj.setEditorMode("Join", 2) # hide for now + obj.addProperty( + "App::PropertyEnumeration", + "Direction", + "Deburr", + QT_TRANSLATE_NOOP("App::Property", "Direction of Operation"), + ) + # obj.Direction = ["CW", "CCW"] + obj.addProperty( + "App::PropertyEnumeration", + "Side", + "Deburr", + QT_TRANSLATE_NOOP("App::Property", "Side of Operation"), + ) + obj.Side = ["Outside", "Inside"] + obj.setEditorMode("Side", 2) # Hide property, it's calculated by op + obj.addProperty( + "App::PropertyInteger", + "EntryPoint", + "Deburr", + QT_TRANSLATE_NOOP( + "App::Property", "Select the segment, there the operations starts" + ), + ) + + ENUMS = self.propertyEnumerations() + for n in ENUMS: + setattr(obj, n[0], n[1]) + + @classmethod + def propertyEnumerations(self, dataType="data"): + + """opPropertyEnumerations(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 + enums = { + "Direction": [ + (translate("Path", "CW"), "CW"), + (translate("Path", "CCW"), "CCW"), + ], # this is the direction that the profile runs + "Join": [ + (translate("PathDeburr", "Round"), "Round"), + (translate("PathDeburr", "Miter"), "Miter"), + ], # this is the direction that the profile runs + } + + if dataType == "raw": + return enums + + data = list() + idx = 0 if dataType == "translated" else 1 + + PathLog.debug(enums) + + for k, v in enumerate(enums): + # data[k] = [tup[idx] for tup in v] + data.append((v, [tup[idx] for tup in enums[v]])) + PathLog.debug(data) + + return data def opOnDocumentRestored(self, obj): - obj.setEditorMode('Join', 2) # hide for now + obj.setEditorMode("Join", 2) # hide for now def opExecute(self, obj): PathLog.track(obj.Label) - if not hasattr(self, 'printInfo'): + if not hasattr(self, "printInfo"): self.printInfo = True try: - (depth, offset, extraOffset, suppressInfo) = toolDepthAndOffset(obj.Width.Value, obj.ExtraDepth.Value, self.tool, self.printInfo) + (depth, offset, extraOffset, suppressInfo) = toolDepthAndOffset( + obj.Width.Value, obj.ExtraDepth.Value, self.tool, self.printInfo + ) self.printInfo = not suppressInfo except ValueError as e: msg = "{} \n No path will be generated".format(e) @@ -147,13 +240,15 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): for f in subs: sub = base.Shape.getElement(f) - if type(sub) == Part.Edge: # Edge + if type(sub) == Part.Edge: # Edge edges.append(sub) - - elif type(sub) == Part.Face and sub.normalAt(0, 0) != FreeCAD.Vector(0, 0, 1): # Angled face + + elif type(sub) == Part.Face and sub.normalAt(0, 0) != FreeCAD.Vector( + 0, 0, 1 + ): # Angled face # If an angled face is selected, the lower edge is projected to the height of the upper edge, # to simulate an edge - + # Find z value of upper edge for edge in sub.Edges: for p0 in edge.Vertexes: @@ -161,7 +256,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): max_h = p0.Point.z # Find biggest radius for top/bottom - for edge in sub.Edges: + for edge in sub.Edges: if Part.Circle == type(edge.Curve): if edge.Vertexes[0].Point.z == max_h: if edge.Curve.Radius > radius_top: @@ -169,63 +264,139 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): else: if edge.Curve.Radius > radius_bottom: radius_bottom = edge.Curve.Radius - + # Search for lower edge and raise it to height of upper edge for edge in sub.Edges: - if Part.Circle == type(edge.Curve): # Edge is a circle + if Part.Circle == type(edge.Curve): # Edge is a circle if edge.Vertexes[0].Point.z < max_h: - - if edge.Closed: # Circle + + if edge.Closed: # Circle # New center - center = FreeCAD.Vector(edge.Curve.Center.x, edge.Curve.Center.y, max_h) - new_edge = Part.makeCircle(edge.Curve.Radius, center, FreeCAD.Vector(0, 0, 1)) + center = FreeCAD.Vector( + edge.Curve.Center.x, edge.Curve.Center.y, max_h + ) + new_edge = Part.makeCircle( + edge.Curve.Radius, + center, + FreeCAD.Vector(0, 0, 1), + ) edges.append(new_edge) - + # Modify offset for inner angled faces if radius_bottom < radius_top: offset -= 2 * extraOffset - + break - else: # Arc - if edge.Vertexes[0].Point.z == edge.Vertexes[1].Point.z: + else: # Arc + if ( + edge.Vertexes[0].Point.z + == edge.Vertexes[1].Point.z + ): # Arc vertexes are on same layer - l1 = math.sqrt((edge.Vertexes[0].Point.x - edge.Curve.Center.x)**2 + (edge.Vertexes[0].Point.y - edge.Curve.Center.y)**2) - l2 = math.sqrt((edge.Vertexes[1].Point.x - edge.Curve.Center.x)**2 + (edge.Vertexes[1].Point.y - edge.Curve.Center.y)**2) - + l1 = math.sqrt( + ( + edge.Vertexes[0].Point.x + - edge.Curve.Center.x + ) + ** 2 + + ( + edge.Vertexes[0].Point.y + - edge.Curve.Center.y + ) + ** 2 + ) + l2 = math.sqrt( + ( + edge.Vertexes[1].Point.x + - edge.Curve.Center.x + ) + ** 2 + + ( + edge.Vertexes[1].Point.y + - edge.Curve.Center.y + ) + ** 2 + ) + # New center - center = FreeCAD.Vector(edge.Curve.Center.x, edge.Curve.Center.y, max_h) + center = FreeCAD.Vector( + edge.Curve.Center.x, + edge.Curve.Center.y, + max_h, + ) # Calculate angles based on x-axis (0 - PI/2) - start_angle = math.acos((edge.Vertexes[0].Point.x - edge.Curve.Center.x) / l1) - end_angle = math.acos((edge.Vertexes[1].Point.x - edge.Curve.Center.x) / l2) + start_angle = math.acos( + ( + edge.Vertexes[0].Point.x + - edge.Curve.Center.x + ) + / l1 + ) + end_angle = math.acos( + ( + edge.Vertexes[1].Point.x + - edge.Curve.Center.x + ) + / l2 + ) # Angles are based on x-axis (Mirrored on x-axis) -> negative y value means negative angle - if edge.Vertexes[0].Point.y < edge.Curve.Center.y: + if ( + edge.Vertexes[0].Point.y + < edge.Curve.Center.y + ): start_angle *= -1 - if edge.Vertexes[1].Point.y < edge.Curve.Center.y: + if ( + edge.Vertexes[1].Point.y + < edge.Curve.Center.y + ): end_angle *= -1 # Create new arc - new_edge = Part.ArcOfCircle(Part.Circle(center, FreeCAD.Vector(0,0,1), edge.Curve.Radius), start_angle, end_angle).toShape() + new_edge = Part.ArcOfCircle( + Part.Circle( + center, + FreeCAD.Vector(0, 0, 1), + edge.Curve.Radius, + ), + start_angle, + end_angle, + ).toShape() edges.append(new_edge) - + # Modify offset for inner angled faces if radius_bottom < radius_top: offset -= 2 * extraOffset break - else: # Line - if edge.Vertexes[0].Point.z == edge.Vertexes[1].Point.z and edge.Vertexes[0].Point.z < max_h: - new_edge = Part.Edge(Part.LineSegment(FreeCAD.Vector(edge.Vertexes[0].Point.x, edge.Vertexes[0].Point.y, max_h), FreeCAD.Vector(edge.Vertexes[1].Point.x, edge.Vertexes[1].Point.y, max_h))) + else: # Line + if ( + edge.Vertexes[0].Point.z == edge.Vertexes[1].Point.z + and edge.Vertexes[0].Point.z < max_h + ): + new_edge = Part.Edge( + Part.LineSegment( + FreeCAD.Vector( + edge.Vertexes[0].Point.x, + edge.Vertexes[0].Point.y, + max_h, + ), + FreeCAD.Vector( + edge.Vertexes[1].Point.x, + edge.Vertexes[1].Point.y, + max_h, + ), + ) + ) edges.append(new_edge) - elif sub.Wires: basewires.extend(sub.Wires) - - else: # Flat face + + else: # Flat face basewires.append(Part.Wire(sub.Edges)) self.edges = edges # pylint: disable=attribute-defined-outside-init @@ -244,7 +415,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): wires.append(wire) # Set direction of op - forward = (obj.Direction == 'CW') + forward = obj.Direction == "CW" # Set value of side obj.Side = side[0] @@ -258,7 +429,7 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): while z + obj.StepDown.Value < depth: z = z + obj.StepDown.Value zValues.append(z) - + zValues.append(depth) PathLog.track(obj.Label, depth, zValues) @@ -269,30 +440,30 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): self.buildpathocc(obj, wires, zValues, True, forward, obj.EntryPoint) def opRejectAddBase(self, obj, base, sub): - '''The chamfer op can only deal with features of the base model, all others are rejected.''' + """The chamfer op can only deal with features of the base model, all others are rejected.""" return base not in self.model def opSetDefaultValues(self, obj, job): PathLog.track(obj.Label, job.Label) - obj.Width = '1 mm' - obj.ExtraDepth = '0.5 mm' - obj.Join = 'Round' - obj.setExpression('StepDown', '0 mm') - obj.StepDown = '0 mm' - obj.Direction = 'CW' + obj.Width = "1 mm" + obj.ExtraDepth = "0.5 mm" + obj.Join = "Round" + obj.setExpression("StepDown", "0 mm") + obj.StepDown = "0 mm" + obj.Direction = "CW" obj.Side = "Outside" obj.EntryPoint = 0 def SetupProperties(): setup = [] - setup.append('Width') - setup.append('ExtraDepth') + setup.append("Width") + setup.append("ExtraDepth") return setup def Create(name, obj=None, parentJob=None): - '''Create(name) ... Creates and returns a Deburr operation.''' + """Create(name) ... Creates and returns a Deburr operation.""" if obj is None: obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) obj.Proxy = ObjectDeburr(obj, name, parentJob) diff --git a/src/Mod/Path/PathScripts/PathDeburrGui.py b/src/Mod/Path/PathScripts/PathDeburrGui.py index 537d12dca5..ddcce623ee 100644 --- a/src/Mod/Path/PathScripts/PathDeburrGui.py +++ b/src/Mod/Path/PathScripts/PathDeburrGui.py @@ -27,6 +27,7 @@ import PathScripts.PathGui as PathGui import PathScripts.PathLog as PathLog import PathScripts.PathOpGui as PathOpGui from PySide import QtCore, QtGui +from PySide.QtCore import QT_TRANSLATE_NOOP __title__ = "Path Deburr Operation UI" __author__ = "sliptonic (Brad Collette), Schildkroet" @@ -34,16 +35,18 @@ __url__ = "https://www.freecadweb.org" __doc__ = "Deburr operation page controller and command implementation." -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()) -def translate(context, text, disambig=None): - return QtCore.QCoreApplication.translate(context, text, disambig) +translate = FreeCAD.Qt.translate class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): - '''Enhanced base geometry page to also allow special base objects.''' + """Enhanced base geometry page to also allow special base objects.""" def super(self): return super(TaskPanelBaseGeometryPage, self) @@ -53,51 +56,69 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): class TaskPanelOpPage(PathOpGui.TaskPanelPage): - '''Page controller class for the Deburr operation.''' + """Page controller class for the Deburr operation.""" + + _ui_form = ":/panels/PageOpDeburrEdit.ui" def getForm(self): - return FreeCADGui.PySideUic.loadUi(":/panels/PageOpDeburrEdit.ui") + form = FreeCADGui.PySideUic.loadUi(self._ui_form) + comboToPropertyMap = [("direction", "Direction")] + enumTups = PathDeburr.ObjectDeburr.propertyEnumerations(dataType="raw") + + self.populateCombobox(form, enumTups, comboToPropertyMap) + + return form def initPage(self, obj): - self.opImagePath = "{}Mod/Path/Images/Ops/{}".format(FreeCAD.getHomePath(), 'chamfer.svg') # pylint: disable=attribute-defined-outside-init - self.opImage = QtGui.QPixmap(self.opImagePath) # pylint: disable=attribute-defined-outside-init + self.opImagePath = "{}Mod/Path/Images/Ops/{}".format( + FreeCAD.getHomePath(), "chamfer.svg" + ) # pylint: disable=attribute-defined-outside-init + self.opImage = QtGui.QPixmap( + self.opImagePath + ) # pylint: disable=attribute-defined-outside-init self.form.opImage.setPixmap(self.opImage) - iconMiter = QtGui.QIcon(':/icons/edge-join-miter-not.svg') - iconMiter.addFile(':/icons/edge-join-miter.svg', state=QtGui.QIcon.On) - iconRound = QtGui.QIcon(':/icons/edge-join-round-not.svg') - iconRound.addFile(':/icons/edge-join-round.svg', state=QtGui.QIcon.On) + iconMiter = QtGui.QIcon(":/icons/edge-join-miter-not.svg") + iconMiter.addFile(":/icons/edge-join-miter.svg", state=QtGui.QIcon.On) + iconRound = QtGui.QIcon(":/icons/edge-join-round-not.svg") + iconRound.addFile(":/icons/edge-join-round.svg", state=QtGui.QIcon.On) self.form.joinMiter.setIcon(iconMiter) self.form.joinRound.setIcon(iconRound) def getFields(self, obj): - PathGui.updateInputField(obj, 'Width', self.form.value_W) - PathGui.updateInputField(obj, 'ExtraDepth', self.form.value_h) + PathGui.updateInputField(obj, "Width", self.form.value_W) + PathGui.updateInputField(obj, "ExtraDepth", self.form.value_h) if self.form.joinRound.isChecked(): - obj.Join = 'Round' + obj.Join = "Round" elif self.form.joinMiter.isChecked(): - obj.Join = 'Miter' + obj.Join = "Miter" - if obj.Direction != str(self.form.direction.currentText()): - obj.Direction = str(self.form.direction.currentText()) + if obj.Direction != str(self.form.direction.currentData()): + obj.Direction = str(self.form.direction.currentData()) self.updateToolController(obj, self.form.toolController) self.updateCoolant(obj, self.form.coolantController) def setFields(self, obj): - self.form.value_W.setText(FreeCAD.Units.Quantity(obj.Width.Value, FreeCAD.Units.Length).UserString) - self.form.value_h.setText(FreeCAD.Units.Quantity(obj.ExtraDepth.Value, FreeCAD.Units.Length).UserString) + self.form.value_W.setText( + FreeCAD.Units.Quantity(obj.Width.Value, FreeCAD.Units.Length).UserString + ) + self.form.value_h.setText( + FreeCAD.Units.Quantity( + obj.ExtraDepth.Value, FreeCAD.Units.Length + ).UserString + ) self.setupToolController(obj, self.form.toolController) self.setupCoolant(obj, self.form.coolantController) - self.form.joinRound.setChecked('Round' == obj.Join) - self.form.joinMiter.setChecked('Miter' == obj.Join) + self.form.joinRound.setChecked("Round" == obj.Join) + self.form.joinMiter.setChecked("Miter" == obj.Join) self.form.joinFrame.hide() self.selectInComboBox(obj.Direction, self.form.direction) def updateWidth(self): - PathGui.updateInputField(self.obj, 'Width', self.form.value_W) + PathGui.updateInputField(self.obj, "Width", self.form.value_W) def updateExtraDepth(self): - PathGui.updateInputField(self.obj, 'ExtraDepth', self.form.value_h) + PathGui.updateInputField(self.obj, "ExtraDepth", self.form.value_h) def getSignalsForUpdate(self, obj): signals = [] @@ -114,16 +135,20 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): self.form.value_h.editingFinished.connect(self.updateExtraDepth) def taskPanelBaseGeometryPage(self, obj, features): - '''taskPanelBaseGeometryPage(obj, features) ... return page for adding base geometries.''' + """taskPanelBaseGeometryPage(obj, features) ... return page for adding base geometries.""" return TaskPanelBaseGeometryPage(obj, features) -Command = PathOpGui.SetupOperation('Deburr', - PathDeburr.Create, - TaskPanelOpPage, - 'Path_Deburr', - QtCore.QT_TRANSLATE_NOOP("PathDeburr", "Deburr"), - QtCore.QT_TRANSLATE_NOOP("PathDeburr", "Creates a Deburr Path along Edges or around Faces"), - PathDeburr.SetupProperties) +Command = PathOpGui.SetupOperation( + "Deburr", + PathDeburr.Create, + TaskPanelOpPage, + "Path_Deburr", + QT_TRANSLATE_NOOP("Path_Deburr", "Deburr"), + QT_TRANSLATE_NOOP( + "Path_Deburr", "Creates a Deburr Path along Edges or around Faces" + ), + PathDeburr.SetupProperties, +) FreeCAD.Console.PrintLog("Loading PathDeburrGui... done\n") diff --git a/src/Mod/Path/PathScripts/PathFixture.py b/src/Mod/Path/PathScripts/PathFixture.py index 0571e13467..9c871bbdd6 100644 --- a/src/Mod/Path/PathScripts/PathFixture.py +++ b/src/Mod/Path/PathScripts/PathFixture.py @@ -189,7 +189,7 @@ PathUtils.addToJob(obj) if FreeCAD.GuiUp: # register the FreeCAD command - FreeCADGui.addCommand("PathFixture", CommandPathFixture()) + FreeCADGui.addCommand("Path_Fixture", CommandPathFixture()) FreeCAD.Console.PrintLog("Loading PathFixture... done\n") diff --git a/src/Mod/Path/PathScripts/PathInspect.py b/src/Mod/Path/PathScripts/PathInspect.py index f22fbe8f0d..786bcd2c4c 100644 --- a/src/Mod/Path/PathScripts/PathInspect.py +++ b/src/Mod/Path/PathScripts/PathInspect.py @@ -27,19 +27,17 @@ from PySide import QtCore, QtGui import FreeCAD import FreeCADGui import Path +from PySide.QtCore import QT_TRANSLATE_NOOP - -# Qt translation handling -def translate(context, text, disambig=None): - return QtCore.QCoreApplication.translate(context, text, disambig) +translate = FreeCAD.Qt.translate class GCodeHighlighter(QtGui.QSyntaxHighlighter): - def __init__(self, parent=None): - def convertcolor(c): - return QtGui.QColor(int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF)) + return QtGui.QColor( + int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF) + ) super(GCodeHighlighter, self).__init__(parent) p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Editor") @@ -63,19 +61,18 @@ class GCodeHighlighter(QtGui.QSyntaxHighlighter): self.highlightingRules = [] numberFormat = QtGui.QTextCharFormat() numberFormat.setForeground(colors[0]) - self.highlightingRules.append( - (QtCore.QRegExp("[\\-0-9\\.]"), numberFormat)) + self.highlightingRules.append((QtCore.QRegExp("[\\-0-9\\.]"), numberFormat)) keywordFormat = QtGui.QTextCharFormat() keywordFormat.setForeground(colors[1]) keywordFormat.setFontWeight(QtGui.QFont.Bold) keywordPatterns = ["\\bG[0-9]+\\b", "\\bM[0-9]+\\b"] self.highlightingRules.extend( - [(QtCore.QRegExp(pattern), keywordFormat) for pattern in keywordPatterns]) + [(QtCore.QRegExp(pattern), keywordFormat) for pattern in keywordPatterns] + ) speedFormat = QtGui.QTextCharFormat() speedFormat.setFontWeight(QtGui.QFont.Bold) speedFormat.setForeground(colors[2]) - self.highlightingRules.append( - (QtCore.QRegExp("\\bF[0-9\\.]+\\b"), speedFormat)) + self.highlightingRules.append((QtCore.QRegExp("\\bF[0-9\\.]+\\b"), speedFormat)) def highlightBlock(self, text): @@ -93,7 +90,7 @@ class GCodeEditorDialog(QtGui.QDialog): def __init__(self, PathObj, parent=FreeCADGui.getMainWindow()): self.PathObj = PathObj.Path - if hasattr(PathObj, 'ToolController'): + if hasattr(PathObj, "ToolController"): self.tool = PathObj.ToolController.Tool else: self.tool = None @@ -103,10 +100,19 @@ class GCodeEditorDialog(QtGui.QDialog): p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path") c = p.GetUnsigned("DefaultHighlightPathColor", 4286382335) - Q = QtGui.QColor(int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF)) - highlightcolor = (Q.red() / 255., Q.green() / 255., Q.blue() / 255., Q.alpha() / 255.) + Q = QtGui.QColor( + int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF) + ) + highlightcolor = ( + Q.red() / 255.0, + Q.green() / 255.0, + Q.blue() / 255.0, + Q.alpha() / 255.0, + ) - self.selectionobj = FreeCAD.ActiveDocument.addObject("Path::Feature", "selection") + self.selectionobj = FreeCAD.ActiveDocument.addObject( + "Path::Feature", "selection" + ) self.selectionobj.ViewObject.LineWidth = 4 self.selectionobj.ViewObject.NormalColor = highlightcolor @@ -123,14 +129,21 @@ class GCodeEditorDialog(QtGui.QDialog): # Note lab = QtGui.QLabel() - lab.setText(translate("Path_Inspect", "Note: Pressing OK will commit any change you make above to the object, but if the object is parametric, these changes will be overridden on recompute.")) + lab.setText( + translate( + "Path_Inspect", + "Note: Pressing OK will commit any change you make above to the object, but if the object is parametric, these changes will be overridden on recompute.", + ) + ) lab.setWordWrap(True) layout.addWidget(lab) # OK and Cancel buttons self.buttons = QtGui.QDialogButtonBox( QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel, - QtCore.Qt.Horizontal, self) + QtCore.Qt.Horizontal, + self, + ) layout.addWidget(self.buttons) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) @@ -138,19 +151,19 @@ class GCodeEditorDialog(QtGui.QDialog): self.finished.connect(self.cleanup) prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path") - Xpos = int(prefs.GetString('inspecteditorX', "0")) - Ypos = int(prefs.GetString('inspecteditorY', "0")) - height = int(prefs.GetString('inspecteditorH', "500")) - width = int(prefs.GetString('inspecteditorW', "600")) + Xpos = int(prefs.GetString("inspecteditorX", "0")) + Ypos = int(prefs.GetString("inspecteditorY", "0")) + height = int(prefs.GetString("inspecteditorH", "500")) + width = int(prefs.GetString("inspecteditorW", "600")) self.move(Xpos, Ypos) self.resize(width, height) def cleanup(self): prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path") - prefs.SetString('inspecteditorX', str(self.x())) - prefs.SetString('inspecteditorY', str(self.y())) - prefs.SetString('inspecteditorW', str(self.width())) - prefs.SetString('inspecteditorH', str(self.height())) + prefs.SetString("inspecteditorX", str(self.x())) + prefs.SetString("inspecteditorY", str(self.y())) + prefs.SetString("inspecteditorW", str(self.width())) + prefs.SetString("inspecteditorH", str(self.height())) FreeCAD.ActiveDocument.removeObject(self.selectionobj.Name) def highlightpath(self): @@ -191,7 +204,7 @@ class GCodeEditorDialog(QtGui.QDialog): p = Path.Path() firstrapid = Path.Command("G0", {"X": prevX, "Y": prevY, "Z": prevZ}) - selectionpath = [firstrapid] + commands[startrow:endrow + 1] + selectionpath = [firstrapid] + commands[startrow : endrow + 1] p.Commands = selectionpath self.selectionobj.Path = p @@ -207,21 +220,28 @@ def show(obj): prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path") # default Max Highlighter Size = 512 Ko defaultMHS = 512 * 1024 - mhs = prefs.GetUnsigned('inspecteditorMaxHighlighterSize', defaultMHS) + mhs = prefs.GetUnsigned("inspecteditorMaxHighlighterSize", defaultMHS) if hasattr(obj, "Path"): if obj.Path: dia = GCodeEditorDialog(obj) dia.editor.setText(obj.Path.toGCode()) gcodeSize = len(dia.editor.toPlainText()) - if (gcodeSize <= mhs): + if gcodeSize <= mhs: # because of poor performance, syntax highlighting is # limited to mhs octets (default 512 KB). # It seems than the response time curve has an inflexion near 500 KB # beyond 500 KB, the response time increases exponentially. dia.highlighter = GCodeHighlighter(dia.editor.document()) else: - FreeCAD.Console.PrintMessage(translate("Path", "GCode size too big ({} o), disabling syntax highlighter.".format(gcodeSize))) + FreeCAD.Console.PrintMessage( + translate( + "Path", + "GCode size too big ({} o), disabling syntax highlighter.".format( + gcodeSize + ), + ) + ) result = dia.exec_() # exec_() returns 0 or 1 depending on the button pressed (Ok or # Cancel) @@ -234,12 +254,15 @@ def show(obj): class CommandPathInspect: - def GetResources(self): - return {'Pixmap': 'Path_Inspect', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Inspect", "Inspect G-code"), - 'Accel': "P, I", - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Inspect", "Inspects the G-code contents of a path")} + return { + "Pixmap": "Path_Inspect", + "MenuText": QT_TRANSLATE_NOOP("Path_Inspect", "Inspect G-code"), + "Accel": "P, I", + "ToolTip": QT_TRANSLATE_NOOP( + "Path_Inspect", "Inspects the G-code contents of a path" + ), + } def IsActive(self): if FreeCAD.ActiveDocument is not None: @@ -253,19 +276,26 @@ class CommandPathInspect: selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: FreeCAD.Console.PrintError( - translate("Path_Inspect", "Please select exactly one path object") + "\n") + translate("Path_Inspect", "Please select exactly one path object") + + "\n" + ) return - if not(selection[0].isDerivedFrom("Path::Feature")): + if not (selection[0].isDerivedFrom("Path::Feature")): FreeCAD.Console.PrintError( - translate("Path_Inspect", "Please select exactly one path object") + "\n") + translate("Path_Inspect", "Please select exactly one path object") + + "\n" + ) return # if everything is ok, execute FreeCADGui.addModule("PathScripts.PathInspect") FreeCADGui.doCommand( - 'PathScripts.PathInspect.show(FreeCAD.ActiveDocument.' + selection[0].Name + ')') + "PathScripts.PathInspect.show(FreeCAD.ActiveDocument." + + selection[0].Name + + ")" + ) if FreeCAD.GuiUp: # register the FreeCAD command - FreeCADGui.addCommand('Path_Inspect', CommandPathInspect()) + FreeCADGui.addCommand("Path_Inspect", CommandPathInspect()) diff --git a/src/Mod/Path/PathScripts/PathProbe.py b/src/Mod/Path/PathScripts/PathProbe.py index e2fc33e8f0..dbb2b2c0e9 100644 --- a/src/Mod/Path/PathScripts/PathProbe.py +++ b/src/Mod/Path/PathScripts/PathProbe.py @@ -27,8 +27,8 @@ import Path import PathScripts.PathLog as PathLog import PathScripts.PathOp as PathOp import PathScripts.PathUtils as PathUtils +from PySide.QtCore import QT_TRANSLATE_NOOP -from PySide import QtCore __title__ = "Path Probing Operation" __author__ = "sliptonic (Brad Collette)" @@ -42,63 +42,106 @@ else: PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -# Qt translation handling -def translate(context, text, disambig=None): - return QtCore.QCoreApplication.translate(context, text, disambig) - - class ObjectProbing(PathOp.ObjectOp): - '''Proxy object for Probing operation.''' + """Proxy object for Probing operation.""" def opFeatures(self, obj): - '''opFeatures(obj) ... Probing works on the stock object.''' + """opFeatures(obj) ... Probing works on the stock object.""" return PathOp.FeatureDepths | PathOp.FeatureHeights | PathOp.FeatureTool def initOperation(self, obj): - obj.addProperty("App::PropertyLength", "Xoffset", "Probe", QtCore.QT_TRANSLATE_NOOP("App::Property", "X offset between tool and probe")) - obj.addProperty("App::PropertyLength", "Yoffset", "Probe", QtCore.QT_TRANSLATE_NOOP("App::Property", "Y offset between tool and probe")) - obj.addProperty("App::PropertyInteger", "PointCountX", "Probe", QtCore.QT_TRANSLATE_NOOP("App::Property", "Number of points to probe in X direction")) - obj.addProperty("App::PropertyInteger", "PointCountY", "Probe", QtCore.QT_TRANSLATE_NOOP("App::Property", "Number of points to probe in Y direction")) - obj.addProperty("App::PropertyFile", "OutputFileName", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The output location for the probe data to be written")) + obj.addProperty( + "App::PropertyLength", + "Xoffset", + "Probe", + QT_TRANSLATE_NOOP("App::Property", "X offset between tool and probe"), + ) + obj.addProperty( + "App::PropertyLength", + "Yoffset", + "Probe", + QT_TRANSLATE_NOOP("App::Property", "Y offset between tool and probe"), + ) + obj.addProperty( + "App::PropertyInteger", + "PointCountX", + "Probe", + QT_TRANSLATE_NOOP( + "App::Property", "Number of points to probe in X direction" + ), + ) + obj.addProperty( + "App::PropertyInteger", + "PointCountY", + "Probe", + QT_TRANSLATE_NOOP( + "App::Property", "Number of points to probe in Y direction" + ), + ) + obj.addProperty( + "App::PropertyFile", + "OutputFileName", + "Path", + QT_TRANSLATE_NOOP( + "App::Property", "The output location for the probe data to be written" + ), + ) def nextpoint(self, startpoint=0.0, endpoint=0.0, count=3): curstep = 0 dist = (endpoint - startpoint) / (count - 1) - while curstep <= count-1: + while curstep <= count - 1: yield startpoint + (curstep * dist) curstep += 1 def opExecute(self, obj): - '''opExecute(obj) ... generate probe locations.''' + """opExecute(obj) ... generate probe locations.""" PathLog.track() self.commandlist.append(Path.Command("(Begin Probing)")) stock = PathUtils.findParentJob(obj).Stock bb = stock.Shape.BoundBox - openstring = '(PROBEOPEN {})'.format(obj.OutputFileName) + openstring = "(PROBEOPEN {})".format(obj.OutputFileName) self.commandlist.append(Path.Command(openstring)) self.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value})) for y in self.nextpoint(bb.YMin, bb.YMax, obj.PointCountY): for x in self.nextpoint(bb.XMin, bb.XMax, obj.PointCountX): - self.commandlist.append(Path.Command("G0", {"X": x + obj.Xoffset.Value, "Y": y + obj.Yoffset.Value, "Z": obj.SafeHeight.Value})) - self.commandlist.append(Path.Command("G38.2", {"Z": obj.FinalDepth.Value, "F": obj.ToolController.VertFeed.Value})) + self.commandlist.append( + Path.Command( + "G0", + { + "X": x + obj.Xoffset.Value, + "Y": y + obj.Yoffset.Value, + "Z": obj.SafeHeight.Value, + }, + ) + ) + self.commandlist.append( + Path.Command( + "G38.2", + { + "Z": obj.FinalDepth.Value, + "F": obj.ToolController.VertFeed.Value, + }, + ) + ) self.commandlist.append(Path.Command("G0", {"Z": obj.SafeHeight.Value})) self.commandlist.append(Path.Command("(PROBECLOSE)")) def opSetDefaultValues(self, obj, job): - '''opSetDefaultValues(obj, job) ... set default value for RetractHeight''' + """opSetDefaultValues(obj, job) ... set default value for RetractHeight""" def SetupProperties(): - setup = ['Xoffset', 'Yoffset', 'PointCountX', 'PointCountY', 'OutputFileName'] + setup = ["Xoffset", "Yoffset", "PointCountX", "PointCountY", "OutputFileName"] return setup def Create(name, obj=None, parentJob=None): - '''Create(name) ... Creates and returns a Probing operation.''' + """Create(name) ... Creates and returns a Probing operation.""" if obj is None: obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) proxy = ObjectProbing(obj, name, parentJob) diff --git a/src/Mod/Path/PathScripts/PathProbeGui.py b/src/Mod/Path/PathScripts/PathProbeGui.py index 29c97d7adc..96c80b50ae 100644 --- a/src/Mod/Path/PathScripts/PathProbeGui.py +++ b/src/Mod/Path/PathScripts/PathProbeGui.py @@ -22,11 +22,13 @@ import FreeCAD import FreeCADGui -import PathGui as PGui # ensure Path/Gui/Resources are loaded +import PathGui as PGui # ensure Path/Gui/Resources are loaded import PathScripts.PathProbe as PathProbe import PathScripts.PathOpGui as PathOpGui import PathScripts.PathGui as PathGui +import PathScripts.PathLog as PathLog +from PySide.QtCore import QT_TRANSLATE_NOOP from PySide import QtCore, QtGui __title__ = "Path Probing Operation UI" @@ -35,38 +37,46 @@ __url__ = "http://www.freecadweb.org" __doc__ = "Probing operation page controller and command implementation." -# 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()) + +translate = FreeCAD.Qt.translate class TaskPanelOpPage(PathOpGui.TaskPanelPage): - '''Page controller class for the Probing operation.''' + """Page controller class for the Probing operation.""" def getForm(self): - '''getForm() ... returns UI''' + """getForm() ... returns UI""" return FreeCADGui.PySideUic.loadUi(":/panels/PageOpProbeEdit.ui") def getFields(self, obj): - '''getFields(obj) ... transfers values from UI to obj's proprties''' + """getFields(obj) ... transfers values from UI to obj's proprties""" self.updateToolController(obj, self.form.toolController) - PathGui.updateInputField(obj, 'Xoffset', self.form.Xoffset) - PathGui.updateInputField(obj, 'Yoffset', self.form.Yoffset) + PathGui.updateInputField(obj, "Xoffset", self.form.Xoffset) + PathGui.updateInputField(obj, "Yoffset", self.form.Yoffset) obj.PointCountX = self.form.PointCountX.value() obj.PointCountY = self.form.PointCountY.value() obj.OutputFileName = str(self.form.OutputFileName.text()) def setFields(self, obj): - '''setFields(obj) ... transfers obj's property values to UI''' + """setFields(obj) ... transfers obj's property values to UI""" self.setupToolController(obj, self.form.toolController) - self.form.Xoffset.setText(FreeCAD.Units.Quantity(obj.Xoffset.Value, FreeCAD.Units.Length).UserString) - self.form.Yoffset.setText(FreeCAD.Units.Quantity(obj.Yoffset.Value, FreeCAD.Units.Length).UserString) + self.form.Xoffset.setText( + FreeCAD.Units.Quantity(obj.Xoffset.Value, FreeCAD.Units.Length).UserString + ) + self.form.Yoffset.setText( + FreeCAD.Units.Quantity(obj.Yoffset.Value, FreeCAD.Units.Length).UserString + ) self.form.OutputFileName.setText(obj.OutputFileName) self.form.PointCountX.setValue(obj.PointCountX) self.form.PointCountY.setValue(obj.PointCountY) def getSignalsForUpdate(self, obj): - '''getSignalsForUpdate(obj) ... return list of signals for updating obj''' + """getSignalsForUpdate(obj) ... return list of signals for updating obj""" signals = [] signals.append(self.form.toolController.currentIndexChanged) signals.append(self.form.PointCountX.valueChanged) @@ -78,16 +88,25 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): return signals def SetOutputFileName(self): - filename = QtGui.QFileDialog.getSaveFileName(self.form, translate("Path_Probe", "Select Output File"), None, translate("Path_Probe", "All Files (*.*)")) + filename = QtGui.QFileDialog.getSaveFileName( + self.form, + translate("Path_Probe", "Select Output File"), + None, + translate("Path_Probe", "All Files (*.*)"), + ) if filename and filename[0]: self.obj.OutputFileName = str(filename[0]) self.setFields(self.obj) -Command = PathOpGui.SetupOperation('Probe', PathProbe.Create, TaskPanelOpPage, - 'Path_Probe', - QtCore.QT_TRANSLATE_NOOP("Probe", "Probe"), - QtCore.QT_TRANSLATE_NOOP("Probe", "Create a Probing Grid from a job stock"), - PathProbe.SetupProperties) +Command = PathOpGui.SetupOperation( + "Probe", + PathProbe.Create, + TaskPanelOpPage, + "Path_Probe", + QtCore.QT_TRANSLATE_NOOP("Path_Probe", "Probe"), + QtCore.QT_TRANSLATE_NOOP("Path_Probe", "Create a Probing Grid from a job stock"), + PathProbe.SetupProperties, +) FreeCAD.Console.PrintLog("Loading PathProbeGui... done\n")