Skip to content

Commit

Permalink
Merge pull request #4213 from mlampert/feature/job-tool-group
Browse files Browse the repository at this point in the history
[Path]: Feature/job tool group
  • Loading branch information
sliptonic committed Jan 4, 2021
2 parents deaee22 + 254505e commit d5092d7
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 19 deletions.
30 changes: 23 additions & 7 deletions src/Mod/Path/PathScripts/PathJob.py
Expand Up @@ -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'

Expand Down Expand Up @@ -120,7 +121,7 @@ def __init__(self, obj, models, templateFile=None):

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"))
Expand Down Expand Up @@ -150,6 +151,7 @@ def __init__(self, obj, models, templateFile=None):

self.setupSetupSheet(obj)
self.setupBaseModel(obj, models)
self.setupToolTable(obj)

self.tooltip = None
self.tooltipArgs = None
Expand Down Expand Up @@ -191,6 +193,18 @@ def setupBaseModel(self, obj, models=None):
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)
Expand Down Expand Up @@ -234,14 +248,16 @@ def onDelete(self, obj, arg2=None):

# 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)
Expand All @@ -268,6 +284,7 @@ def onDocumentRestored(self, obj):
self.setupBaseModel(obj)
self.fixupOperations(obj)
self.setupSetupSheet(obj)
self.setupToolTable(obj)

obj.setEditorMode('Operations', 2) # hide
obj.setEditorMode('Placement', 2)
Expand Down Expand Up @@ -334,7 +351,7 @@ def setFromTemplateFile(self, obj, template):
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:
Expand Down Expand Up @@ -414,13 +431,12 @@ def addOperation(self, op, before=None, removeBefore=False):
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):
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/Path/PathScripts/PathJobCmd.py
Expand Up @@ -146,7 +146,7 @@ def Execute(cls, job, path, dialog=None):
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
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/Path/PathScripts/PathJobDlg.py
Expand Up @@ -338,7 +338,7 @@ def updateUI(self):
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)
Expand Down
8 changes: 5 additions & 3 deletions src/Mod/Path/PathScripts/PathJobGui.py
Expand Up @@ -210,7 +210,7 @@ def getIcon(self):
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
Expand All @@ -222,6 +222,8 @@ def claimChildren(self):
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):
Expand Down Expand Up @@ -707,7 +709,7 @@ def updateToolController(self):

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
Expand Down Expand Up @@ -847,7 +849,7 @@ def canDeleteTC(tc):
# 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:
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/Path/PathScripts/PathSanity.py
Expand Up @@ -517,7 +517,7 @@ def __toolData(self, obj):
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 \
Expand Down
4 changes: 2 additions & 2 deletions src/Mod/Path/PathScripts/PathToolControllerGui.py
Expand Up @@ -165,12 +165,12 @@ def Activated(self):
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()
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/Path/PathScripts/PathUtils.py
Expand Up @@ -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 []


Expand Down
6 changes: 3 additions & 3 deletions src/Mod/Path/PathTests/TestPathHelix.py
Expand Up @@ -62,7 +62,7 @@ def test01(self):
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
Expand All @@ -87,7 +87,7 @@ def test03(self):
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
Expand All @@ -109,7 +109,7 @@ def test04(self):
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
Expand Down

0 comments on commit d5092d7

Please sign in to comment.