diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/PathScripts/PathJob.py index d68b24cdcb..a6c027b722 100644 --- a/src/Mod/Path/PathScripts/PathJob.py +++ b/src/Mod/Path/PathScripts/PathJob.py @@ -58,6 +58,7 @@ class JobTemplate: PostProcessorOutputFile = 'Output' SetupSheet = 'SetupSheet' Stock = 'Stock' + # TCs are grouped under Tools in a job, the template refers to them directly though ToolController = 'ToolController' Version = 'Version' @@ -120,7 +121,7 @@ class ObjectJob: obj.addProperty("App::PropertyLink", "Stock", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Solid object to be used as stock.")) obj.addProperty("App::PropertyLink", "Operations", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Compound path of all operations in the order they are processed.")) - obj.addProperty("App::PropertyLinkList", "ToolController", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Collection of tool controllers available for this job.")) + #obj.addProperty("App::PropertyLinkList", "ToolController", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Collection of tool controllers available for this job.")) obj.addProperty("App::PropertyBool", "SplitOutput", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "Split output into multiple gcode files")) obj.addProperty("App::PropertyEnumeration", "OrderOutputBy", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "If multiple WCS, order the output this way")) @@ -150,6 +151,7 @@ class ObjectJob: self.setupSetupSheet(obj) self.setupBaseModel(obj, models) + self.setupToolTable(obj) self.tooltip = None self.tooltipArgs = None @@ -191,6 +193,18 @@ class ObjectJob: obj.Base = None obj.removeProperty('Base') + def setupToolTable(self, obj): + if not hasattr(obj, 'Tools'): + obj.addProperty("App::PropertyLink", "Tools", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "Collection of all tool controllers for the job")) + toolTable = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", "Tools") + toolTable.Label = 'Tools' + if toolTable.ViewObject: + toolTable.ViewObject.Visibility = False + if hasattr(obj, 'ToolController'): + toolTable.addObjects(obj.ToolController) + obj.removeProperty('ToolController') + obj.Tools = toolTable + def removeBase(self, obj, base, removeFromModel): if isResourceClone(obj, base, None): PathUtil.clearExpressionEngine(base) @@ -234,14 +248,16 @@ class ObjectJob: # Tool controllers might refer to either legacy tool or toolbit PathLog.debug('taking down tool controller') - for tc in obj.ToolController: + for tc in obj.Tools.Group: if hasattr(tc.Tool, "Proxy"): PathUtil.clearExpressionEngine(tc.Tool) doc.removeObject(tc.Tool.Name) PathUtil.clearExpressionEngine(tc) tc.Proxy.onDelete(tc) doc.removeObject(tc.Name) - obj.ToolController = [] + obj.Tools.Group = [] + doc.removeObject(obj.Tools.Name) + obj.Tools = None # SetupSheet PathUtil.clearExpressionEngine(obj.SetupSheet) @@ -268,6 +284,7 @@ class ObjectJob: self.setupBaseModel(obj) self.fixupOperations(obj) self.setupSetupSheet(obj) + self.setupToolTable(obj) obj.setEditorMode('Operations', 2) # hide obj.setEditorMode('Placement', 2) @@ -334,7 +351,7 @@ class ObjectJob: obj.Stock = PathStock.CreateFromTemplate(obj, attrs.get(JobTemplate.Stock)) PathLog.debug("setting tool controllers (%d)" % len(tcs)) - obj.ToolController = tcs + obj.Tools.Group = tcs else: PathLog.error(translate('PathJob', "Unsupported PathJob template version %s") % attrs.get(JobTemplate.Version)) if not tcs: @@ -414,13 +431,12 @@ class ObjectJob: op.Path.Center = self.obj.Operations.Path.Center def addToolController(self, tc): - group = self.obj.ToolController + group = self.obj.Tools.Group PathLog.debug("addToolController(%s): %s" % (tc.Label, [t.Label for t in group])) if tc.Name not in [str(t.Name) for t in group]: tc.setExpression('VertRapid', "%s.%s" % (self.setupSheet.expressionReference(), PathSetupSheet.Template.VertRapid)) tc.setExpression('HorizRapid', "%s.%s" % (self.setupSheet.expressionReference(), PathSetupSheet.Template.HorizRapid)) - group.append(tc) - self.obj.ToolController = group + self.obj.Tools.addObject(tc) Notification.updateTC.emit(self.obj, tc) def allOperations(self): diff --git a/src/Mod/Path/PathScripts/PathJobCmd.py b/src/Mod/Path/PathScripts/PathJobCmd.py index 9b600dc32b..a3b26ac128 100644 --- a/src/Mod/Path/PathScripts/PathJobCmd.py +++ b/src/Mod/Path/PathScripts/PathJobCmd.py @@ -146,7 +146,7 @@ class CommandJobTemplateExport: attrs.pop(PathJob.JobTemplate.PostProcessorOutputFile, None) # tool controller settings - toolControllers = dialog.includeToolControllers() if dialog else job.ToolController + toolControllers = dialog.includeToolControllers() if dialog else job.Tools.Group if toolControllers: tcAttrs = [tc.Proxy.templateAttrs(tc) for tc in toolControllers] attrs[PathJob.JobTemplate.ToolController] = tcAttrs diff --git a/src/Mod/Path/PathScripts/PathJobDlg.py b/src/Mod/Path/PathScripts/PathJobDlg.py index a28466eb3c..c7e98edda5 100644 --- a/src/Mod/Path/PathScripts/PathJobDlg.py +++ b/src/Mod/Path/PathScripts/PathJobDlg.py @@ -338,7 +338,7 @@ class JobTemplateExport: self.dialog.settingsOpsList.addItem(item) self.dialog.toolsList.clear() - for tc in sorted(job.ToolController, key=lambda o: o.Label): + for tc in sorted(job.Tools.Group, key=lambda o: o.Label): item = QtGui.QListWidgetItem(tc.Label) item.setData(self.DataObject, tc) item.setCheckState(QtCore.Qt.CheckState.Checked) diff --git a/src/Mod/Path/PathScripts/PathJobGui.py b/src/Mod/Path/PathScripts/PathJobGui.py index a85c437fdf..f5d2fa9db2 100644 --- a/src/Mod/Path/PathScripts/PathJobGui.py +++ b/src/Mod/Path/PathScripts/PathJobGui.py @@ -210,7 +210,7 @@ class ViewProvider: return ":/icons/Path_Job.svg" def claimChildren(self): - children = self.obj.ToolController + children = [] children.append(self.obj.Operations) if hasattr(self.obj, 'Model'): # unfortunately this function is called before the object has been fully loaded @@ -222,6 +222,8 @@ class ViewProvider: if hasattr(self.obj, 'SetupSheet'): # when loading a job that didn't have a setup sheet they might not've been created yet children.append(self.obj.SetupSheet) + if hasattr(self.obj, 'Tools'): + children.append(self.obj.Tools) return children def onDelete(self, vobj, arg2=None): @@ -707,7 +709,7 @@ class TaskPanel: vUnit = FreeCAD.Units.Quantity(1, FreeCAD.Units.Velocity).getUserPreferred()[2] - for row, tc in enumerate(sorted(self.obj.ToolController, key=lambda tc: tc.Label)): + for row, tc in enumerate(sorted(self.obj.Tools.Group, key=lambda tc: tc.Label)): self.form.activeToolController.addItem(tc.Label, tc) if tc == select: index = row @@ -847,7 +849,7 @@ class TaskPanel: # can only delete what is selected delete = edit # ... but we want to make sure there's at least one TC left - if len(self.obj.ToolController) == len(self.form.toolControllerList.selectedItems()): + if len(self.obj.Tools.Group) == len(self.form.toolControllerList.selectedItems()): delete = False # ... also don't want to delete any TCs that are already used if delete: diff --git a/src/Mod/Path/PathScripts/PathSanity.py b/src/Mod/Path/PathScripts/PathSanity.py index 09664be146..0d1517e4f7 100644 --- a/src/Mod/Path/PathScripts/PathSanity.py +++ b/src/Mod/Path/PathScripts/PathSanity.py @@ -517,7 +517,7 @@ class CommandPathSanity: data = {} try: - for TC in obj.ToolController: + for TC in obj.Tools.Group: if not hasattr(TC.Tool, 'BitBody'): self.squawk("PathSanity", "Tool number {} is a legacy tool. Legacy tools not \ diff --git a/src/Mod/Path/PathScripts/PathToolControllerGui.py b/src/Mod/Path/PathScripts/PathToolControllerGui.py index 62709086e0..33e735a08d 100644 --- a/src/Mod/Path/PathScripts/PathToolControllerGui.py +++ b/src/Mod/Path/PathScripts/PathToolControllerGui.py @@ -165,12 +165,12 @@ class CommandPathToolController(object): tool = PathToolBitGui.ToolBitSelector().getTool() if tool: toolNr = None - for tc in job.ToolController: + for tc in job.Tools.Group: if tc.Tool == tool: toolNr = tc.ToolNumber break if not toolNr: - toolNr = max([tc.ToolNumber for tc in job.ToolController]) + 1 + toolNr = max([tc.ToolNumber for tc in job.Tools.Group]) + 1 tc = Create("TC: {}".format(tool.Label), tool, toolNr) job.Proxy.addToolController(tc) FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/Path/PathScripts/PathUtils.py b/src/Mod/Path/PathScripts/PathUtils.py index 6c7afdf4fd..d2e18e7184 100644 --- a/src/Mod/Path/PathScripts/PathUtils.py +++ b/src/Mod/Path/PathScripts/PathUtils.py @@ -403,7 +403,7 @@ def getToolControllers(obj, proxy=None): PathLog.debug("op={} ({})".format(obj.Label, type(obj))) if job: - return [c for c in job.ToolController if proxy.isToolSupported(obj, c.Tool)] + return [tc for tc in job.Tools.Group if proxy.isToolSupported(obj, tc.Tool)] return [] diff --git a/src/Mod/Path/PathTests/TestPathHelix.py b/src/Mod/Path/PathTests/TestPathHelix.py index 0fb76c9f1a..a3dc545156 100644 --- a/src/Mod/Path/PathTests/TestPathHelix.py +++ b/src/Mod/Path/PathTests/TestPathHelix.py @@ -62,7 +62,7 @@ class TestPathHelix(PathTestUtils.PathTestBase): def test02(self): '''Verify Helix generates proper holes for rotated model''' - self.job.ToolController[0].Tool.Diameter = 0.5 + self.job.Tools.Group[0].Tool.Diameter = 0.5 op = PathHelix.Create('Helix') proxy = op.Proxy @@ -87,7 +87,7 @@ class TestPathHelix(PathTestUtils.PathTestBase): self.doc.Body.Placement.Rotation = FreeCAD.Rotation(deg, 0, 0) self.job = PathJob.Create('Job', [self.doc.Body]) - self.job.ToolController[0].Tool.Diameter = 0.5 + self.job.Tools.Group[0].Tool.Diameter = 0.5 op = PathHelix.Create('Helix') proxy = op.Proxy @@ -109,7 +109,7 @@ class TestPathHelix(PathTestUtils.PathTestBase): self.clone.Placement.Rotation = FreeCAD.Rotation(deg, 0, 0) self.job = PathJob.Create('Job', [self.clone]) - self.job.ToolController[0].Tool.Diameter = 0.5 + self.job.Tools.Group[0].Tool.Diameter = 0.5 op = PathHelix.Create('Helix') proxy = op.Proxy