From 4230af991e6d2a8368302ffd69940febbec9cb89 Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Tue, 29 Oct 2019 22:11:10 -0700 Subject: [PATCH] Added JobTemplate support for ToolBit --- src/Mod/Path/PathScripts/PathToolBit.py | 54 +++++++----- src/Mod/Path/PathScripts/PathToolBitCmd.py | 2 +- src/Mod/Path/PathScripts/PathToolBitGui.py | 33 ++++---- .../Path/PathScripts/PathToolBitLibraryGui.py | 2 +- .../Path/PathScripts/PathToolController.py | 82 ++++++++++++------- .../Path/PathScripts/PathToolControllerGui.py | 2 +- 6 files changed, 102 insertions(+), 73 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathToolBit.py b/src/Mod/Path/PathScripts/PathToolBit.py index 1813b4c2b8..703859aaee 100644 --- a/src/Mod/Path/PathScripts/PathToolBit.py +++ b/src/Mod/Path/PathScripts/PathToolBit.py @@ -262,16 +262,8 @@ class ToolBit(object): def saveToFile(self, obj, path, setFile=True): try: - data = {} - data['version'] = 1 - data['name'] = obj.Label - data['template'] = obj.BitTemplate - params = {} - for prop in self.bitPropertyNames(obj): - params[prop] = PathUtil.getProperty(obj, prop).UserString - data['parameter'] = params with open(path, 'w') as fp: - json.dump(data, fp, indent=' ') + json.dump(self.templateAttrs(obj), fp, indent=' ') if setFile: obj.File = path return True @@ -279,26 +271,44 @@ class ToolBit(object): PathLog.error("Could not save tool %s to %s (%s)" % (obj.Label, path, e)) raise + def templateAttrs(self, obj): + attrs = {} + attrs['version'] = 2 # Path.Tool is version 1 + attrs['name'] = obj.Label + attrs['template'] = obj.BitTemplate + params = {} + for prop in self.bitPropertyNames(obj): + params[prop] = PathUtil.getProperty(obj, prop).UserString + attrs['parameter'] = params + return attrs + def Declaration(path): with open(path, 'r') as fp: return json.load(fp) -def CreateFrom(path, name = 'ToolBit'): - try: - data = Declaration(path) - obj = Create(name, data['template']) - obj.Label = data['name'] - params = data['parameter'] +class ToolBitFactory(object): + + def CreateFromAttrs(self, attrs, name='ToolBit'): + obj = Factory.Create(name, attrs['template']) + obj.Label = attrs['name'] + params = attrs['parameter'] for prop in params: PathUtil.setProperty(obj, prop, params[prop]) obj.Proxy._updateBitShape(obj) obj.Proxy.unloadBitBody(obj) return obj - except (OSError, IOError) as e: - PathLog.error("%s not a valid tool file (%s)" % (path, e)) - raise -def Create(name = 'ToolBit', templateFile=None): - obj = FreeCAD.ActiveDocument.addObject('Part::FeaturePython', name) - obj.Proxy = ToolBit(obj, templateFile) - return obj + def CreateFrom(self, path, name='ToolBit'): + try: + data = Declaration(path) + return Factory.CreateFromAttrs(data, name) + except (OSError, IOError) as e: + PathLog.error("%s not a valid tool file (%s)" % (path, e)) + raise + + def Create(self, name='ToolBit', templateFile=None): + obj = FreeCAD.ActiveDocument.addObject('Part::FeaturePython', name) + obj.Proxy = ToolBit(obj, templateFile) + return obj + +Factory = ToolBitFactory() diff --git a/src/Mod/Path/PathScripts/PathToolBitCmd.py b/src/Mod/Path/PathScripts/PathToolBitCmd.py index e3e9a2d7ab..b651997aac 100644 --- a/src/Mod/Path/PathScripts/PathToolBitCmd.py +++ b/src/Mod/Path/PathScripts/PathToolBitCmd.py @@ -47,7 +47,7 @@ class CommandToolBitCreate: def Activated(self): import PathScripts.PathToolBitGui as PathToolBitGui - obj = PathToolBitGui.Create() + obj = PathToolBit.Factory.Create() obj.ViewObject.Proxy.setCreate(obj.ViewObject) class CommandToolBitSave: diff --git a/src/Mod/Path/PathScripts/PathToolBitGui.py b/src/Mod/Path/PathScripts/PathToolBitGui.py index 977a3fa683..9b35fb69ba 100644 --- a/src/Mod/Path/PathScripts/PathToolBitGui.py +++ b/src/Mod/Path/PathScripts/PathToolBitGui.py @@ -213,7 +213,7 @@ class ToolBitSelector(object): def createTool(self): PathLog.track() - tool = Create() + tool = PathToolBit.Factory.Create() def accept(): self.editor.accept() @@ -253,22 +253,16 @@ class ToolBitSelector(object): self.form.tools.itemSelectionChanged.connect(self.updateSelection) self.form.tools.doubleClicked.connect(self.form.accept) -def Create(name = 'ToolBit'): - '''Create(name = 'ToolBit') ... creates a new tool bit. - It is assumed the tool will be edited immediately so the internal bit body is still attached.''' - FreeCAD.ActiveDocument.openTransaction(translate('PathToolBit', 'Create ToolBit')) - tool = PathToolBit.Create(name) - PathIconViewProvider.Attach(tool.ViewObject, name) - FreeCAD.ActiveDocument.commitTransaction() - return tool +class ToolBitGuiFactory(PathToolBit.ToolBitFactory): -def CreateFrom(path, name = 'ToolBit'): - '''CreateFrom(path, name = 'ToolBit') ... creates an instance of a tool stored in path''' - FreeCAD.ActiveDocument.openTransaction(translate('PathToolBit', 'Create ToolBit instance')) - tool = PathToolBit.CreateFrom(path, name) - PathIconViewProvider.Attach(tool.ViewObject, name) - FreeCAD.ActiveDocument.commitTransaction() - return tool + def Create(self, name='ToolBit', templateFile=None): + '''Create(name = 'ToolBit') ... creates a new tool bit. + It is assumed the tool will be edited immediately so the internal bit body is still attached.''' + FreeCAD.ActiveDocument.openTransaction(translate('PathToolBit', 'Create ToolBit')) + tool = PathToolBit.ToolBitFactory.Create(self, name, templateFile) + PathIconViewProvider.Attach(tool.ViewObject, name) + FreeCAD.ActiveDocument.commitTransaction() + return tool def GetToolFile(parent = None): if parent is None: @@ -292,10 +286,13 @@ def GetToolFiles(parent = None): def LoadTool(parent = None): '''LoadTool(parent=None) ... Open a file dialog to load a tool from a file.''' foo = GetToolFile(parent) - return CreateFrom(foo) if foo else foo + return PathToolBit.Factory.CreateFrom(foo) if foo else foo def LoadTools(parent = None): '''LoadTool(parent=None) ... Open a file dialog to load a tool from a file.''' - return [CreateFrom(foo) for foo in GetToolFiles(parent)] + return [PathToolBit.Factory.CreateFrom(foo) for foo in GetToolFiles(parent)] + +# Set the factory so all tools are created with UI +PathToolBit.Factory = ToolBitGuiFactory() PathIconViewProvider.RegisterViewProvider('ToolBit', ViewProvider) diff --git a/src/Mod/Path/PathScripts/PathToolBitLibraryGui.py b/src/Mod/Path/PathScripts/PathToolBitLibraryGui.py index bcea963cc6..bd976dd404 100644 --- a/src/Mod/Path/PathScripts/PathToolBitLibraryGui.py +++ b/src/Mod/Path/PathScripts/PathToolBitLibraryGui.py @@ -183,7 +183,7 @@ class ToolBitLibrary(object): item = self.model.item(row, 0) toolNr = int(item.data(PySide.QtCore.Qt.EditRole)) toolPath = item.data(_PathRole) - tools.append((toolNr, PathToolBitGui.CreateFrom(toolPath))) + tools.append((toolNr, PathToolBit.Factory.CreateFrom(toolPath))) return tools def toolDelete(self): diff --git a/src/Mod/Path/PathScripts/PathToolController.py b/src/Mod/Path/PathScripts/PathToolController.py index 46bb4fabfc..59e6fcc86a 100644 --- a/src/Mod/Path/PathScripts/PathToolController.py +++ b/src/Mod/Path/PathScripts/PathToolController.py @@ -26,6 +26,7 @@ import FreeCAD import Path import PathScripts.PathLog as PathLog +import PathScripts.PathToolBit as PathToolBit from PySide import QtCore @@ -67,11 +68,7 @@ class ToolController: obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", QtCore.QT_TRANSLATE_NOOP("PathToolController", "The active tool")) obj.ToolNumber = (0, 0, 10000, 1) - if cTool: - obj.addProperty("Path::PropertyTool", "Tool", "Base", QtCore.QT_TRANSLATE_NOOP("PathToolController", "The tool used by this controller")) - else: - obj.addProperty("App::PropertyLink", "Tool", "Base", QtCore.QT_TRANSLATE_NOOP("PathToolController", "The tool used by this controller")) - + self.ensureUseLegacyTool(obj, cTool) obj.addProperty("App::PropertyFloat", "SpindleSpeed", "Tool", QtCore.QT_TRANSLATE_NOOP("PathToolController", "The speed of the cutting spindle in RPM")) obj.addProperty("App::PropertyEnumeration", "SpindleDir", "Tool", QtCore.QT_TRANSLATE_NOOP("PathToolController", "Direction of spindle rotation")) obj.SpindleDir = ['Forward', 'Reverse'] @@ -92,31 +89,44 @@ class ToolController: def setFromTemplate(self, obj, template): '''setFromTemplate(obj, xmlItem) ... extract properties from xmlItem and assign to receiver.''' PathLog.track(obj.Name, template) - if template.get(ToolControllerTemplate.Version) and 1 == int(template.get(ToolControllerTemplate.Version)): - if template.get(ToolControllerTemplate.Label): - obj.Label = template.get(ToolControllerTemplate.Label) - if template.get(ToolControllerTemplate.VertFeed): - obj.VertFeed = template.get(ToolControllerTemplate.VertFeed) - if template.get(ToolControllerTemplate.HorizFeed): - obj.HorizFeed = template.get(ToolControllerTemplate.HorizFeed) - if template.get(ToolControllerTemplate.VertRapid): - obj.VertRapid = template.get(ToolControllerTemplate.VertRapid) - if template.get(ToolControllerTemplate.HorizRapid): - obj.HorizRapid = template.get(ToolControllerTemplate.HorizRapid) - if template.get(ToolControllerTemplate.SpindleSpeed): - obj.SpindleSpeed = float(template.get(ToolControllerTemplate.SpindleSpeed)) - if template.get(ToolControllerTemplate.SpindleDir): - obj.SpindleDir = template.get(ToolControllerTemplate.SpindleDir) - if template.get(ToolControllerTemplate.ToolNumber): - obj.ToolNumber = int(template.get(ToolControllerTemplate.ToolNumber)) - if template.get(ToolControllerTemplate.Tool): - obj.Tool.setFromTemplate(template.get(ToolControllerTemplate.Tool)) - if template.get(ToolControllerTemplate.Expressions): - for exprDef in template.get(ToolControllerTemplate.Expressions): - if exprDef[ToolControllerTemplate.ExprExpr]: - obj.setExpression(exprDef[ToolControllerTemplate.ExprProp], exprDef[ToolControllerTemplate.ExprExpr]) + version = 0 + if template.get(ToolControllerTemplate.Version): + version = int(template.get(ToolControllerTemplate.Version)) + if version == 1 or version == 2: + if template.get(ToolControllerTemplate.Label): + obj.Label = template.get(ToolControllerTemplate.Label) + if template.get(ToolControllerTemplate.VertFeed): + obj.VertFeed = template.get(ToolControllerTemplate.VertFeed) + if template.get(ToolControllerTemplate.HorizFeed): + obj.HorizFeed = template.get(ToolControllerTemplate.HorizFeed) + if template.get(ToolControllerTemplate.VertRapid): + obj.VertRapid = template.get(ToolControllerTemplate.VertRapid) + if template.get(ToolControllerTemplate.HorizRapid): + obj.HorizRapid = template.get(ToolControllerTemplate.HorizRapid) + if template.get(ToolControllerTemplate.SpindleSpeed): + obj.SpindleSpeed = float(template.get(ToolControllerTemplate.SpindleSpeed)) + if template.get(ToolControllerTemplate.SpindleDir): + obj.SpindleDir = template.get(ToolControllerTemplate.SpindleDir) + if template.get(ToolControllerTemplate.ToolNumber): + obj.ToolNumber = int(template.get(ToolControllerTemplate.ToolNumber)) + if template.get(ToolControllerTemplate.Tool): + toolVersion = template.get(ToolControllerTemplate.Tool).get(ToolControllerTemplate.Version) + if toolVersion == 1: + self.ensureUseLegacyTool(obj, True) + obj.Tool.setFromTemplate(template.get(ToolControllerTemplate.Tool)) + else: + self.ensureUseLegacyTool(obj, False) + obj.Tool = PathToolBit.Factory.CreateFromAttrs(template.get(ToolControllerTemplate.Tool)) + if obj.Tool and obj.Tool.ViewObject and obj.Tool.ViewObject.Visibility: + obj.ViewObject.Visibility = False + if template.get(ToolControllerTemplate.Expressions): + for exprDef in template.get(ToolControllerTemplate.Expressions): + if exprDef[ToolControllerTemplate.ExprExpr]: + obj.setExpression(exprDef[ToolControllerTemplate.ExprProp], exprDef[ToolControllerTemplate.ExprExpr]) + else: + PathLog.error(translate('PathToolController', "Unsupported PathToolController template version %s") % template.get(ToolControllerTemplate.Version)) else: - PathLog.error(translate('PathToolController', "Unsupported PathToolController template version %s") % template.get(ToolControllerTemplate.Version)) + PathLog.error(translate('PathToolController', 'PathToolController template has no version - corrupted template file?')) def templateAttrs(self, obj): '''templateAttrs(obj) ... answer a dictionary with all properties that should be stored for a template.''' @@ -131,7 +141,10 @@ class ToolController: attrs[ToolControllerTemplate.HorizRapid] = ("%s" % (obj.HorizRapid)) attrs[ToolControllerTemplate.SpindleSpeed] = obj.SpindleSpeed attrs[ToolControllerTemplate.SpindleDir] = obj.SpindleDir - attrs[ToolControllerTemplate.Tool] = obj.Tool.templateAttrs() + if self.usesLegacyTool(obj): + attrs[ToolControllerTemplate.Tool] = obj.Tool.templateAttrs() + else: + attrs[ToolControllerTemplate.Tool] = obj.Tool.Proxy.templateAttrs(obj.Tool) expressions = [] for expr in obj.ExpressionEngine: PathLog.debug('%s: %s' % (expr[0], expr[1])) @@ -169,6 +182,15 @@ class ToolController: '''returns True if the tool being controlled is a legacy tool''' return isinstance(obj.Tool, Path.Tool) + def ensureUseLegacyTool(self, obj, legacy): + if not hasattr(obj, 'Tool') or (legacy != self.usesLegacyTool(obj)): + if hasattr(obj, 'Tool'): + obj.removeProperty('Tool') + if legacy: + obj.addProperty("Path::PropertyTool", "Tool", "Base", QtCore.QT_TRANSLATE_NOOP("PathToolController", "The tool used by this controller")) + else: + obj.addProperty("App::PropertyLink", "Tool", "Base", QtCore.QT_TRANSLATE_NOOP("PathToolController", "The tool used by this controller")) + def Create(name = 'Default Tool', tool=None, toolNumber=1, assignViewProvider=True): PathLog.track(tool, toolNumber) diff --git a/src/Mod/Path/PathScripts/PathToolControllerGui.py b/src/Mod/Path/PathScripts/PathToolControllerGui.py index f0f088e445..3a82f0fc41 100644 --- a/src/Mod/Path/PathScripts/PathToolControllerGui.py +++ b/src/Mod/Path/PathScripts/PathToolControllerGui.py @@ -118,7 +118,7 @@ class ViewProvider: def claimChildren(self): obj = self.vobj.Object - if not obj.Proxy.usesLegacyTool(obj): + if obj and obj.Proxy and not obj.Proxy.usesLegacyTool(obj): return [obj.Tool] return []