diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt
index 18f604075b..97f182e73d 100644
--- a/src/Mod/Path/CMakeLists.txt
+++ b/src/Mod/Path/CMakeLists.txt
@@ -45,6 +45,7 @@ SET(PathScripts_SRCS
PathScripts/PathHop.py
PathScripts/PathInspect.py
PathScripts/PathJob.py
+ PathScripts/PathJobGui.py
PathScripts/PathLog.py
PathScripts/PathMillFace.py
PathScripts/PathMillFaceGui.py
diff --git a/src/Mod/Path/Gui/Resources/Path.qrc b/src/Mod/Path/Gui/Resources/Path.qrc
index a80ce319fe..ff7c5a6786 100644
--- a/src/Mod/Path/Gui/Resources/Path.qrc
+++ b/src/Mod/Path/Gui/Resources/Path.qrc
@@ -69,6 +69,7 @@
panels/PageOpHelixEdit.ui
panels/PageOpPocketFullEdit.ui
panels/PageOpProfileFullEdit.ui
+ panels/PathEdit.ui
panels/PointEdit.ui
panels/SurfaceEdit.ui
panels/ToolControl.ui
diff --git a/src/Mod/Path/Gui/Resources/panels/DlgJobCreate.ui b/src/Mod/Path/Gui/Resources/panels/DlgJobCreate.ui
index 8a2eba7842..7f6ebcc220 100644
--- a/src/Mod/Path/Gui/Resources/panels/DlgJobCreate.ui
+++ b/src/Mod/Path/Gui/Resources/panels/DlgJobCreate.ui
@@ -6,65 +6,52 @@
0
0
- 400
- 208
+ 365
+ 147
Dialog
-
-
- QFormLayout::AllNonFixedFieldsGrow
-
- -
-
-
- Base Model
-
+
+
-
+
+
+
-
+
+
+ true
+
+
+ <html><head/><body><p>Select a template to be used for the job.</p><p><br/></p><p>In case there are no templates you can create one through the popup menu of an existing job. Name the file job_*.xml and place it in the macro or the path directory (see preferences) in order to be selectable from this list.</p><p><br/></p><p>Note that the result is a plain xml file and can be edited by hand. Any properties not specified in the template will be set to their default value.</p></body></html>
+
+
+
+ -
+
+
+ Base Model
+
+
+
+ -
+
+
+ Template
+
+
+
+ -
+
+
+
- -
-
-
- -
-
-
- Template
-
-
-
- -
-
-
- true
-
-
- <html><head/><body><p>Select a template to be used for the job.</p><p><br/></p><p>In case there are no templates you can create one through the popup menu of an existing job. Name the file job_*.xml and place it in the macro or the path directory (see preferences) in order to be selectable from this list.</p><p><br/></p><p>Note that the result is a plain xml file and can be edited by hand. Any properties not specified in the template will be set to their default value.</p></body></html>
-
-
-
- -
-
-
- Stock
-
-
-
- -
-
-
+
-
+
+
false
-
-
-
- coming soon
-
-
-
-
- -
-
Qt::Horizontal
diff --git a/src/Mod/Path/Gui/Resources/panels/PathEdit.ui b/src/Mod/Path/Gui/Resources/panels/PathEdit.ui
new file mode 100644
index 0000000000..fa58a5c809
--- /dev/null
+++ b/src/Mod/Path/Gui/Resources/panels/PathEdit.ui
@@ -0,0 +1,811 @@
+
+
+ PathEdit
+
+
+
+ 0
+ 0
+ 400
+ 608
+
+
+
+ Job Edit
+
+
+ 1
+
+
+
+ General
+
+
+
-
+
+
+ 0
+
+
+
+
+ 0
+ 0
+ 378
+ 477
+
+
+
+ Info
+
+
+
+ QFormLayout::AllNonFixedFieldsGrow
+
+
-
+
+
+ Label
+
+
+
+ -
+
+
+ -
+
+
+ Model
+
+
+
+ -
+
+
+ false
+
+
+
+ -
+
+
+ false
+
+
+ Material
+
+
+
+ -
+
+
+ false
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 378
+ 477
+
+
+
+ Template
+
+
+ -
+
+
+ General
+
+
+ true
+
+
+
-
+
+
+ Material
+
+
+ true
+
+
+
+
+
+
+ -
+
+
+ Setup
+
+
+ true
+
+
+
-
+
+
+ Stock
+
+
+ true
+
+
+
+ -
+
+
+ Post Processor
+
+
+ true
+
+
+
+
+
+
+ -
+
+
+ Tools
+
+
+ true
+
+
+
+
+ -
+
+
+ Operations
+
+
+ true
+
+
+
-
+
+
+ Default Values
+
+
+ true
+
+
+
+
+
+
+ -
+
+
+ QDialogButtonBox::Save
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+ Setup
+
+
+ -
+
+
+ true
+
+
+ 0
+
+
+
+
+ 0
+ 0
+ 378
+ 403
+
+
+
+ Layout
+
+
+
-
+
+
+ Stock
+
+
+
-
+
+
+ Ext. X
+
+
+
+ -
+
+
+ Ext. Y
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ -
+
+
+ Ext. Z
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+ Orientation
+
+
+
-
+
+
+ X-Axis
+
+
+
+ -
+
+
+ Y-Axis
+
+
+
+ -
+
+
+ Z-Axis
+
+
+
+
+
+
+ -
+
+
+ Alignment
+
+
+
-
+
+
+ Set Origin
+
+
+
+ -
+
+
+ Move to Origin
+
+
+
+ -
+
+
+ Center in Stock
+
+
+
+ -
+
+
+ XY in Stock
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 378
+ 403
+
+
+
+ Post Processor
+
+
+ -
+
+
+ -
+
+
+ Processor
+
+
+
+ -
+
+
+ Output File
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ Arguments
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ ...
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 378
+ 403
+
+
+
+ Fixtures
+
+
+ -
+
+
+ false
+
+
+ Coming Soon
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 378
+ 403
+
+
+
+ Vise
+
+
+ -
+
+
+ false
+
+
+ Coming Soon
+
+
+
+
+
+
+
+
+
+
+
+ Tools
+
+
+ -
+
+
+ 0
+
+
+
+
+ 0
+ 0
+ 378
+ 514
+
+
+
+ Tool Controller
+
+
+
-
+
+
+ 71
+
+
+
+ Name
+
+
+
+
+ Tool
+
+
+
+
+ H-Feed
+
+
+
+
+ V-Feed
+
+
+
+
+ Spindle
+
+
+
+
+ -
+
+
+
-
+
+
+ false
+
+
+ Edit
+
+
+
+ -
+
+
+ Add
+
+
+
+ -
+
+
+ false
+
+
+ Remove
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Workplan
+
+
+ -
+
+
+ 0
+
+
+
+
+ 0
+ 0
+ 378
+ 477
+
+
+
+ Operations
+
+
+
-
+
+
+
+ QFormLayout::AllNonFixedFieldsGrow
+
+
-
+
+
+ Active Tool
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
-
+
+
+
+
+
+ -
+
+
+
-
+
+
+ Edit
+
+
+
+ -
+
+
+ Delete
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 395
+ 462
+
+
+
+ Default Values
+
+
+ -
+
+
+ Operation
+
+
+ true
+
+
+ false
+
+
+
-
+
+
+ Milling
+
+
+
+ -
+
+
-
+
+ conventional
+
+
+ -
+
+ climb
+
+
+
+
+ -
+
+
+ Tool Compensated
+
+
+
+
+
+
+ -
+
+
+ Heights
+
+
+ true
+
+
+ false
+
+
+
-
+
+
+ Safe
+
+
+
+ -
+
+
+ -
+
+
+ Clearance
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+ Depths
+
+
+ true
+
+
+ false
+
+
+
-
+
+
+ Step Down
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Gui::InputField
+ QLineEdit
+
+
+
+
+
+
diff --git a/src/Mod/Path/InitGui.py b/src/Mod/Path/InitGui.py
index 5018636afd..3182e43176 100644
--- a/src/Mod/Path/InitGui.py
+++ b/src/Mod/Path/InitGui.py
@@ -58,7 +58,7 @@ class PathWorkbench (Workbench):
from PathScripts import PathHelixGui
from PathScripts import PathHop
from PathScripts import PathInspect
- from PathScripts import PathJob
+ from PathScripts import PathJobGui
from PathScripts import PathMillFaceGui
from PathScripts import PathPlane
from PathScripts import PathPocketGui
diff --git a/src/Mod/Path/PathScripts/PathDressupDogbone.py b/src/Mod/Path/PathScripts/PathDressupDogbone.py
index dd18ff9b51..bc6e05f8fe 100644
--- a/src/Mod/Path/PathScripts/PathDressupDogbone.py
+++ b/src/Mod/Path/PathScripts/PathDressupDogbone.py
@@ -985,7 +985,7 @@ class ViewProviderDressup:
'''this makes sure that the base operation is added back to the project and visible'''
FreeCADGui.ActiveDocument.getObject(arg1.Object.Base.Name).Visibility = True
job = PathUtils.findParentJob(arg1.Object)
- PathUtils.addObjectToJob(arg1.Object.Base, job)
+ job.addOperation(arg1.Object.Base)
arg1.Object.Base = None
return True
@@ -996,7 +996,7 @@ def Create(base, name = 'DogboneDressup'):
obj = FreeCAD.ActiveDocument.addObject('Path::FeaturePython', 'DogboneDressup')
dbo = ObjectDressup(obj, base)
job = PathUtils.findParentJob(base)
- PathUtils.addObjectToJob(obj, job)
+ job.addOperation(obj)
if FreeCAD.GuiUp:
ViewProviderDressup(obj.ViewObject)
diff --git a/src/Mod/Path/PathScripts/PathDressupHoldingTags.py b/src/Mod/Path/PathScripts/PathDressupHoldingTags.py
index 5e551f3a18..e50a81634b 100644
--- a/src/Mod/Path/PathScripts/PathDressupHoldingTags.py
+++ b/src/Mod/Path/PathScripts/PathDressupHoldingTags.py
@@ -968,7 +968,7 @@ def Create(baseObject, name = 'DressupTag'):
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TagDressup")
dbo = ObjectTagDressup(obj, baseObject)
job = PathUtils.findParentJob(baseObject)
- PathUtils.addObjectToJob(obj, job)
+ job.addOperation(obj)
dbo.setup(obj, True)
return obj
diff --git a/src/Mod/Path/PathScripts/PathDressupRampEntry.py b/src/Mod/Path/PathScripts/PathDressupRampEntry.py
index a06184da97..7dcf302685 100644
--- a/src/Mod/Path/PathScripts/PathDressupRampEntry.py
+++ b/src/Mod/Path/PathScripts/PathDressupRampEntry.py
@@ -563,7 +563,7 @@ class ViewProviderDressup:
'''this makes sure that the base operation is added back to the project and visible'''
FreeCADGui.ActiveDocument.getObject(arg1.Object.Base.Name).Visibility = True
job = PathUtils.findParentJob(self.obj)
- PathUtils.addObjectToJob(arg1.Object.Base, job)
+ job.addOperation(arg1.Object.Base)
arg1.Object.Base = None
return True
diff --git a/src/Mod/Path/PathScripts/PathDressupTag.py b/src/Mod/Path/PathScripts/PathDressupTag.py
index 58f6a5bb2b..fa6a4fde79 100644
--- a/src/Mod/Path/PathScripts/PathDressupTag.py
+++ b/src/Mod/Path/PathScripts/PathDressupTag.py
@@ -242,7 +242,7 @@ def Create(baseObject, name = 'DressupTag'):
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TagDressup")
dbo = ObjectDressup(obj, baseObject)
job = PathUtils.findParentJob(baseObject)
- PathUtils.addObjectToJob(obj, job)
+ job.adddOperation(obj)
dbo.assignDefaultValues()
return obj
diff --git a/src/Mod/Path/PathScripts/PathDressupTagGui.py b/src/Mod/Path/PathScripts/PathDressupTagGui.py
index 763bf8810a..71efea0bb2 100644
--- a/src/Mod/Path/PathScripts/PathDressupTagGui.py
+++ b/src/Mod/Path/PathScripts/PathDressupTagGui.py
@@ -522,7 +522,8 @@ class PathDressupTagViewProvider:
if self.obj.Base.ViewObject:
self.obj.Base.ViewObject.Visibility = True
job = PathUtils.findParentJob(self.obj)
- PathUtils.addObjectToJob(arg1.Object.Base, job)
+ job.addOperation(arg1.Object.Base)
+ arg1.Object.Base = None
#if self.debugDisplay():
# self.vobj.Debug.removeObjectsFromDocument()
# self.vobj.Debug.Document.removeObject(self.vobj.Debug.Name)
diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/PathScripts/PathJob.py
index 17caea870d..7b0bf790d1 100644
--- a/src/Mod/Path/PathScripts/PathJob.py
+++ b/src/Mod/Path/PathScripts/PathJob.py
@@ -23,31 +23,21 @@
# ***************************************************************************
import ArchPanel
-import Draft
import FreeCAD
-import Path
import PathScripts.PathLog as PathLog
import PathScripts.PathToolController as PathToolController
import PathScripts.PathUtil as PathUtil
-import glob
import xml.etree.ElementTree as xml
-import os
-import sys
-from PySide import QtCore, QtGui
-from PathScripts.PathPostProcessor import PostProcessor
from PathScripts.PathPreferences import PathPreferences
+from PathScripts.PathPostProcessor import PostProcessor
+from PySide import QtCore
-# xrange is not available in python3
-if sys.version_info.major >= 3:
- xrange = range
-
-PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
-#PathLog.trackModule()
-
-FreeCADGui = None
-if FreeCAD.GuiUp:
- import FreeCADGui
+if True:
+ PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
+ PathLog.trackModule()
+else:
+ PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
"""Path Job object and FreeCAD command"""
@@ -65,15 +55,24 @@ class JobTemplate:
Description = 'desc'
ToolController = 'ToolController'
-class ObjectPathJob:
+class ObjectJob:
def __init__(self, obj, base, template = None):
self.obj = obj
obj.addProperty("App::PropertyFile", "PostProcessorOutputFile", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property","The NC output file for this project"))
- obj.PostProcessorOutputFile = PathPreferences.defaultOutputFile()
- obj.setEditorMode("PostProcessorOutputFile", 0) # set to default mode
-
obj.addProperty("App::PropertyEnumeration", "PostProcessor", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property","Select the Post Processor"))
+ obj.addProperty("App::PropertyString", "PostProcessorArgs", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property", "Arguments for the Post Processor (specific to the script)"))
+
+ obj.addProperty("App::PropertyString", "Description", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","An optional description for this job"))
+ obj.addProperty("App::PropertyDistance", "GeometryTolerance", "Geometry", QtCore.QT_TRANSLATE_NOOP("App::Property", "For computing Paths; smaller increases accuracy, but slows down computation"))
+
+ obj.addProperty("App::PropertyLink", "Base", "Base", QtCore.QT_TRANSLATE_NOOP("PathJob", "The base object for all operations"))
+ 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.PostProcessorOutputFile = PathPreferences.defaultOutputFile()
+ #obj.setEditorMode("PostProcessorOutputFile", 0) # set to default mode
obj.PostProcessor = postProcessors = PathPreferences.allEnabledPostProcessors()
defaultPostProcessor = PathPreferences.defaultPostProcessor()
# Check to see if default post processor hasn't been 'lost' (This can happen when Macro dir has changed)
@@ -81,26 +80,34 @@ class ObjectPathJob:
obj.PostProcessor = defaultPostProcessor
else:
obj.PostProcessor = postProcessors[0]
- obj.addProperty("App::PropertyString", "PostProcessorArgs", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property", "Arguments for the Post Processor (specific to the script)"))
obj.PostProcessorArgs = PathPreferences.defaultPostProcessorArgs()
-
- obj.addProperty("App::PropertyString", "Description", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","An optional description for this job"))
- obj.addProperty("App::PropertyDistance", "GeometryTolerance", "Geometry",
- QtCore.QT_TRANSLATE_NOOP("App::Property", "For computing Paths; smaller increases accuracy, but slows down computation"))
obj.GeometryTolerance = PathPreferences.defaultGeometryTolerance()
- obj.addProperty("App::PropertyLink", "Base", "Base", "The base object for all operations")
- obj.Base = base
+ ops = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython", "Operations")
+ obj.Operations = ops
+ obj.setEditorMode('Operations', 2) # hide
+ obj.setEditorMode('Placement', 2)
+ obj.Base = base
obj.Proxy = self
- if FreeCAD.GuiUp:
- ViewProviderJob(obj.ViewObject)
self.assignTemplate(obj, template)
+ def onDelete(self, obj, arg2=None):
+ for tc in obj.ToolController:
+ FreeCAD.ActiveDocument.removeObject(tc.Name)
+ obj.ToolController = []
+ for op in obj.Operations.Group:
+ FreeCAD.ActiveDocument.removeObject(op.Name)
+ obj.Operations.Group = []
+ FreeCAD.ActiveDocument.removeObject(obj.Operations.Name)
+ obj.Operations = None
+
+
def assignTemplate(self, obj, template):
'''assignTemplate(obj, template) ... extract the properties from the given template file and assign to receiver.
This will also create any TCs stored in the template.'''
+ tcs = []
if template:
tree = xml.parse(template)
for job in tree.getroot().iter(JobTemplate.Job):
@@ -117,9 +124,11 @@ class ObjectPathJob:
if job.get(JobTemplate.Description):
obj.Description = job.get(JobTemplate.Description)
for tc in tree.getroot().iter(JobTemplate.ToolController):
- PathToolController.CommandPathToolController.FromTemplate(obj, tc)
+ tcs.append(PathToolController.CommandPathToolController.FromTemplate(tc))
else:
- PathToolController.CommandPathToolController.Create(obj.Name)
+ tcs.append(PathToolController.CommandPathToolController.Create(obj.Name))
+ PathLog.debug("setting tool controllers (%d)" % len(tcs))
+ obj.ToolController = tcs
def templateAttrs(self, obj):
'''templateAttrs(obj) ... answer a dictionary with all properties of the receiver that should be stored in a template file.'''
@@ -140,27 +149,14 @@ class ObjectPathJob:
def __setstate__(self, state):
return None
- def onChanged(self, obj, prop):
- mode = 2
- obj.setEditorMode('Placement', mode)
-
- if prop == "PostProcessor" and obj.PostProcessor:
- processor = PostProcessor.load(obj.PostProcessor)
- self.tooltip = processor.tooltip
- self.tooltipArgs = processor.tooltipArgs
-
def execute(self, obj):
- cmds = []
- for child in obj.Group:
- if child.isDerivedFrom("Path::Feature"):
- if obj.UsePlacements:
- for c in child.Path.Commands:
- cmds.append(c.transform(child.Placement))
- else:
- cmds.extend(child.Path.Commands)
- if cmds:
- path = Path.Path(cmds)
- obj.Path = path
+ obj.Path = obj.Operations.Path
+
+ def addOperation(self, op):
+ group = self.obj.Operations.Group
+ if op not in group:
+ group.append(op)
+ self.obj.Operations.Group = group
@classmethod
def baseCandidates(cls):
@@ -172,328 +168,8 @@ class ObjectPathJob:
'''Answer true if the given object can be used as a Base for a job.'''
return PathUtil.isValidBaseObject(obj) or (hasattr(obj, 'Proxy') and isinstance(obj.Proxy, ArchPanel.PanelSheet))
+def Create(name, base, template = None):
+ obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
+ proxy = ObjectJob(obj, base, template)
+ return obj
-class ViewProviderJob:
-
- def __init__(self, vobj):
- vobj.Proxy = self
- mode = 2
- vobj.setEditorMode('BoundingBox', mode)
- vobj.setEditorMode('DisplayMode', mode)
- vobj.setEditorMode('Selectable', mode)
- vobj.setEditorMode('ShapeColor', mode)
- vobj.setEditorMode('Transparency', mode)
- self.taskPanel = None
-
- def __getstate__(self): # mandatory
- return None
-
- def __setstate__(self, state): # mandatory
- return None
-
- def deleteObjectsOnReject(self):
- return hasattr(self, 'deleteOnReject') and self.deleteOnReject
-
- def setEdit(self, vobj, mode=0):
- FreeCADGui.Control.closeDialog()
- self.taskPanel = TaskPanel(vobj, self.deleteObjectsOnReject())
- FreeCADGui.Control.showDialog(self.taskPanel)
- self.taskPanel.setupUi()
- self.deleteOnReject = False
- return True
-
- def unsetEdit(self, vobj, mode):
- if self.taskPanel:
- self.taskPanel.reject()
-
- def resetTaskPanel(self):
- self.taskPanel = None
-
- def getIcon(self):
- return ":/icons/Path-Job.svg"
-
- def onChanged(self, vobj, prop):
- mode = 2
- vobj.setEditorMode('BoundingBox', mode)
- vobj.setEditorMode('DisplayMode', mode)
- vobj.setEditorMode('Selectable', mode)
- vobj.setEditorMode('ShapeColor', mode)
- vobj.setEditorMode('Transparency', mode)
-
-
-class TaskPanel:
- def __init__(self, vobj, deleteOnReject):
- FreeCAD.ActiveDocument.openTransaction(translate("Path_Job", "Edit Job"))
- self.vobj = vobj
- self.obj = vobj.Object
- self.deleteOnReject = deleteOnReject
- self.form = FreeCADGui.PySideUic.loadUi(":/panels/JobEdit.ui")
- #self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/JobEdit.ui")
-
- currentPostProcessor = self.obj.PostProcessor
- postProcessors = PathPreferences.allEnabledPostProcessors(['', currentPostProcessor])
- for post in postProcessors:
- self.form.cboPostProcessor.addItem(post)
- # update the enumeration values, just to make sure all selections are valid
- self.obj.PostProcessor = postProcessors
- self.obj.PostProcessor = currentPostProcessor
-
- for o in ObjectPathJob.baseCandidates():
- self.form.cboBaseObject.addItem(o.Label, o)
-
-
- self.postProcessorDefaultTooltip = self.form.cboPostProcessor.toolTip()
- self.postProcessorArgsDefaultTooltip = self.form.cboPostProcessorArgs.toolTip()
-
- def accept(self):
- PathLog.debug('accept')
- self.getFields()
- FreeCAD.ActiveDocument.commitTransaction()
- self.vobj.Proxy.resetTaskPanel()
- FreeCADGui.ActiveDocument.resetEdit()
- FreeCADGui.Control.closeDialog()
- FreeCAD.ActiveDocument.recompute()
-
- def reject(self):
- PathLog.debug('reject')
- FreeCADGui.Control.closeDialog()
- FreeCAD.ActiveDocument.abortTransaction()
- if self.deleteOnReject:
- PathLog.info("Uncreate Job")
- FreeCAD.ActiveDocument.openTransaction(translate("Path_Job", "Uncreate Job"))
- for child in self.obj.Group:
- FreeCAD.ActiveDocument.removeObject(child.Name)
- FreeCAD.ActiveDocument.removeObject(self.obj.Name)
- FreeCAD.ActiveDocument.commitTransaction()
- FreeCAD.ActiveDocument.recompute()
- self.vobj.Proxy.resetTaskPanel()
- return True
-
- def updateTooltips(self):
- if hasattr(self.obj, "Proxy") and hasattr(self.obj.Proxy, "tooltip") and self.obj.Proxy.tooltip:
- self.form.cboPostProcessor.setToolTip(self.obj.Proxy.tooltip)
- if hasattr(self.obj.Proxy, "tooltipArgs") and self.obj.Proxy.tooltipArgs:
- self.form.cboPostProcessorArgs.setToolTip(self.obj.Proxy.tooltipArgs)
- else:
- self.form.cboPostProcessorArgs.setToolTip(self.postProcessorArgsDefaultTooltip)
- else:
- self.form.cboPostProcessor.setToolTip(self.postProcessorDefaultTooltip)
- self.form.cboPostProcessorArgs.setToolTip(self.postProcessorArgsDefaultTooltip)
-
- def getFields(self):
- '''sets properties in the object to match the form'''
- if self.obj:
- self.obj.PostProcessor = str(self.form.cboPostProcessor.currentText())
- self.obj.PostProcessorArgs = str(self.form.cboPostProcessorArgs.displayText())
- self.obj.Label = str(self.form.leLabel.text())
- self.obj.PostProcessorOutputFile = str(self.form.leOutputFile.text())
-
- oldlist = self.obj.Group
- newlist = []
-
- for index in xrange(self.form.PathsList.count()):
- item = self.form.PathsList.item(index)
- for olditem in oldlist:
- if olditem.Label == item.text():
- newlist.append(olditem)
- self.obj.Group = newlist
-
- selObj = self.form.cboBaseObject.itemData(self.form.cboBaseObject.currentIndex())
- if self.form.chkCreateClone.isChecked():
- selObj = Draft.clone(selObj)
- self.obj.Base = selObj
-
- self.updateTooltips()
-
- self.obj.Proxy.execute(self.obj)
-
- def selectComboBoxText(self, widget, text):
- index = widget.findText(text, QtCore.Qt.MatchFixedString)
- if index >= 0:
- widget.blockSignals(True)
- widget.setCurrentIndex(index)
- widget.blockSignals(False)
-
- def setFields(self):
- '''sets fields in the form to match the object'''
-
- self.form.leLabel.setText(self.obj.Label)
- self.form.leOutputFile.setText(self.obj.PostProcessorOutputFile)
-
- self.selectComboBoxText(self.form.cboPostProcessor, self.obj.PostProcessor)
- self.form.cboPostProcessorArgs.setText(self.obj.PostProcessorArgs)
- self.obj.Proxy.onChanged(self.obj, "PostProcessor")
- self.updateTooltips()
-
- self.form.PathsList.clear()
- for child in self.obj.Group:
- self.form.PathsList.addItem(child.Label)
-
- baseindex = -1
- if self.obj.Base:
- baseindex = self.form.cboBaseObject.findText(self.obj.Base.Label, QtCore.Qt.MatchFixedString)
- else:
- for o in FreeCADGui.Selection.getCompleteSelection():
- baseindex = self.form.cboBaseObject.findText(o.Label, QtCore.Qt.MatchFixedString)
- if baseindex >= 0:
- self.form.cboBaseObject.setCurrentIndex(baseindex)
-
-
- def open(self):
- pass
-
- def setFile(self):
- filename = QtGui.QFileDialog.getSaveFileName(self.form, translate("Path_Job", "Select Output File"), None, translate("Path_Job", "All Files (*.*)"))
- if filename and filename[0]:
- self.obj.PostProcessorOutputFile = str(filename[0])
- self.setFields()
-
- def setupUi(self):
- # Connect Signals and Slots
- self.form.cboPostProcessor.currentIndexChanged.connect(self.getFields)
- self.form.cboPostProcessorArgs.editingFinished.connect(self.getFields)
- self.form.leOutputFile.editingFinished.connect(self.getFields)
- self.form.leLabel.editingFinished.connect(self.getFields)
- self.form.btnSelectFile.clicked.connect(self.setFile)
- self.form.PathsList.indexesMoved.connect(self.getFields)
- self.form.cboBaseObject.currentIndexChanged.connect(self.getFields)
-
- self.setFields()
-
-class DlgJobCreate:
-
- def __init__(self, parent=None):
- self.dialog = FreeCADGui.PySideUic.loadUi(":/panels/DlgJobCreate.ui")
- sel = FreeCADGui.Selection.getSelection()
- if sel:
- selected = sel[0].Label
- else:
- selected = None
- index = 0
- for base in ObjectPathJob.baseCandidates():
- if base.Label == selected:
- index = self.dialog.cbModel.count()
- self.dialog.cbModel.addItem(base.Label)
- self.dialog.cbModel.setCurrentIndex(index)
-
- templateFiles = []
- for path in PathPreferences.searchPaths():
- templateFiles.extend(self.templateFilesIn(path))
-
- template = {}
- for tFile in templateFiles:
- name = os.path.split(os.path.splitext(tFile)[0])[1][4:]
- if name in template:
- basename = name
- i = 0
- while name in template:
- i = i + 1
- name = basename + " (%s)" % i
- PathLog.track(name, tFile)
- template[name] = tFile
- selectTemplate = PathPreferences.defaultJobTemplate()
- index = 0
- self.dialog.cbTemplate.addItem('', '')
- for name in sorted(template.keys()):
- if template[name] == selectTemplate:
- index = self.dialog.cbTemplate.count()
- self.dialog.cbTemplate.addItem(name, template[name])
- self.dialog.cbTemplate.setCurrentIndex(index)
-
- def templateFilesIn(self, path):
- '''templateFilesIn(path) ... answer all file in the given directory which fit the job template naming convention.
- PathJob template files are name job_*.xml'''
- PathLog.track(path)
- return glob.glob(path + '/job_*.xml')
-
- def getModel(self):
- '''answer the base model selected for the job'''
- label = self.dialog.cbModel.currentText()
- return filter(lambda obj: obj.Label == label, FreeCAD.ActiveDocument.Objects)[0]
-
- def getTemplate(self):
- '''answer the file name of the template to be assigned'''
- return self.dialog.cbTemplate.itemData(self.dialog.cbTemplate.currentIndex())
-
- def exec_(self):
- return self.dialog.exec_()
-
-class CommandJobCreate:
- '''
- Command used to creat a command.
- When activated the command opens a dialog allowing the user to select a base object (has to be a solid)
- and a template to be used for the initial creation.
- '''
-
- def GetResources(self):
- return {'Pixmap': 'Path-Job',
- 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Job", "Job"),
- 'Accel': "P, J",
- 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Job", "Creates a Path Job object")}
-
- def IsActive(self):
- return FreeCAD.ActiveDocument is not None
-
- def Activated(self):
- dialog = DlgJobCreate()
- if dialog.exec_() == 1:
- self.Execute(dialog.getModel(), dialog.getTemplate())
- FreeCAD.ActiveDocument.recompute()
-
- @classmethod
- def Execute(cls, base, template):
- FreeCADGui.addModule('PathScripts.PathJob')
- FreeCAD.ActiveDocument.openTransaction(translate("Path_Job", "Create Job"))
- try:
- FreeCADGui.doCommand('App.ActiveDocument.addObject("Path::FeatureCompoundPython", "Job")')
- if template:
- template = "'%s'" % template
- else:
- template = 'None'
- FreeCADGui.doCommand('PathScripts.PathJob.ObjectPathJob(App.ActiveDocument.ActiveObject, App.ActiveDocument.%s, %s)' % (base.Name, template))
- FreeCAD.ActiveDocument.commitTransaction()
- except:
- PathLog.error(sys.exc_info())
- FreeCAD.ActiveDocument.abortTransaction()
-
-class CommandJobExportTemplate:
- '''
- Command to export a template of a given job.
- Opens a dialog to select the file to store the template in. If the template is stored in Path's
- file path (see preferences) and named in accordance with job_*.xml it will automatically be found
- on Job creation and be available for selection.
- '''
-
- def GetResources(self):
- return {'Pixmap': 'Path-Job',
- 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Job", "Export Template"),
- 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Job", "Exports Path Job as a template to be used for other jobs")}
-
- def IsActive(self):
- return FreeCAD.ActiveDocument is not None
-
- def Activated(self):
- job = FreeCADGui.Selection.getSelection()[0]
- foo = QtGui.QFileDialog.getSaveFileName(QtGui.qApp.activeWindow(),
- "Path - Job Template",
- PathPreferences.filePath(),
- "job_*.xml")[0]
- if foo:
- self.Execute(job, foo)
-
- @classmethod
- def Execute(cls, job, path):
- root = xml.Element('PathJobTemplate')
- xml.SubElement(root, JobTemplate.Job, job.Proxy.templateAttrs(job))
- for obj in job.Group:
- if hasattr(obj, 'Tool') and hasattr(obj, 'SpindleDir'):
- tc = xml.SubElement(root, JobTemplate.ToolController, obj.Proxy.templateAttrs(obj))
- tc.append(xml.fromstring(obj.Tool.Content))
- xml.ElementTree(root).write(path)
-
-if FreeCAD.GuiUp:
- # register the FreeCAD command
- FreeCADGui.addCommand('Path_Job', CommandJobCreate())
- FreeCADGui.addCommand('Path_ExportTemplate', CommandJobExportTemplate())
-
-FreeCAD.Console.PrintLog("Loading PathJob... done\n")
diff --git a/src/Mod/Path/PathScripts/PathJobGui.py b/src/Mod/Path/PathScripts/PathJobGui.py
new file mode 100644
index 0000000000..5fa3def0d3
--- /dev/null
+++ b/src/Mod/Path/PathScripts/PathJobGui.py
@@ -0,0 +1,373 @@
+# -*- coding: utf-8 -*-
+
+# ***************************************************************************
+# * *
+# * Copyright (c) 2017 sliptonic *
+# * *
+# * This program is free software; you can redistribute it and/or modify *
+# * it under the terms of the GNU Lesser General Public License (LGPL) *
+# * as published by the Free Software Foundation; either version 2 of *
+# * the License, or (at your option) any later version. *
+# * for detail see the LICENCE text file. *
+# * *
+# * This program is distributed in the hope that it will be useful, *
+# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+# * GNU Library General Public License for more details. *
+# * *
+# * You should have received a copy of the GNU Library General Public *
+# * License along with this program; if not, write to the Free Software *
+# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+# * USA *
+# * *
+# ***************************************************************************
+
+import FreeCAD
+import FreeCADGui
+import PathScripts.PathJob as PathJob
+import PathScripts.PathLog as PathLog
+import PathScripts.PathToolController as PathToolController
+
+import glob
+import os
+import sys
+import xml.etree.ElementTree as xml
+
+from PathScripts.PathPreferences import PathPreferences
+from PySide import QtCore, QtGui
+
+# Qt tanslation handling
+def translate(context, text, disambig=None):
+ return QtCore.QCoreApplication.translate(context, text, disambig)
+
+class ViewProvider:
+
+ def __init__(self, vobj):
+ vobj.Proxy = self
+ mode = 2
+ vobj.setEditorMode('BoundingBox', mode)
+ vobj.setEditorMode('DisplayMode', mode)
+ vobj.setEditorMode('Selectable', mode)
+ vobj.setEditorMode('ShapeColor', mode)
+ vobj.setEditorMode('Transparency', mode)
+ self.taskPanel = None
+
+ def attach(self, vobj):
+ self.vobj = vobj
+ self.obj = vobj.Object
+
+ def __getstate__(self): # mandatory
+ return None
+
+ def __setstate__(self, state): # mandatory
+ return None
+
+ def deleteObjectsOnReject(self):
+ return hasattr(self, 'deleteOnReject') and self.deleteOnReject
+
+ def setEdit(self, vobj, mode=0):
+ FreeCADGui.Control.closeDialog()
+ self.taskPanel = TaskPanel(vobj, self.deleteObjectsOnReject())
+ FreeCADGui.Control.showDialog(self.taskPanel)
+ self.taskPanel.setupUi()
+ self.deleteOnReject = False
+ return True
+
+ def unsetEdit(self, vobj, mode):
+ if self.taskPanel:
+ self.taskPanel.reject()
+
+ def resetTaskPanel(self):
+ self.taskPanel = None
+
+ def getIcon(self):
+ return ":/icons/Path-Job.svg"
+
+ def onChanged(self, vobj, prop):
+ mode = 2
+ vobj.setEditorMode('BoundingBox', mode)
+ vobj.setEditorMode('DisplayMode', mode)
+ vobj.setEditorMode('Selectable', mode)
+ vobj.setEditorMode('ShapeColor', mode)
+ vobj.setEditorMode('Transparency', mode)
+
+ def claimChildren(self):
+ children = self.obj.ToolController
+ children.append(self.obj.Operations)
+ return children
+
+class TaskPanel:
+ def __init__(self, vobj, deleteOnReject):
+ FreeCAD.ActiveDocument.openTransaction(translate("Path_Job", "Edit Job"))
+ self.vobj = vobj
+ self.obj = vobj.Object
+ self.deleteOnReject = deleteOnReject
+ self.form = FreeCADGui.PySideUic.loadUi(":/panels/PathEdit.ui")
+
+ currentPostProcessor = self.obj.PostProcessor
+ postProcessors = PathPreferences.allEnabledPostProcessors(['', currentPostProcessor])
+ for post in postProcessors:
+ self.form.postProcessor.addItem(post)
+ # update the enumeration values, just to make sure all selections are valid
+ self.obj.PostProcessor = postProcessors
+ self.obj.PostProcessor = currentPostProcessor
+
+ for o in PathJob.ObjectJob.baseCandidates():
+ self.form.infoModel.addItem(o.Label, o)
+
+
+ self.postProcessorDefaultTooltip = self.form.postProcessor.toolTip()
+ self.postProcessorArgsDefaultTooltip = self.form.postProcessorArguments.toolTip()
+
+ def accept(self):
+ PathLog.debug('accept')
+ self.getFields()
+ FreeCAD.ActiveDocument.commitTransaction()
+ self.vobj.Proxy.resetTaskPanel()
+ FreeCADGui.ActiveDocument.resetEdit()
+ FreeCADGui.Control.closeDialog()
+ FreeCAD.ActiveDocument.recompute()
+
+ def reject(self):
+ PathLog.debug('reject')
+ FreeCADGui.Control.closeDialog()
+ FreeCAD.ActiveDocument.abortTransaction()
+ if self.deleteOnReject:
+ PathLog.info("Uncreate Job")
+ FreeCAD.ActiveDocument.openTransaction(translate("Path_Job", "Uncreate Job"))
+ FreeCAD.ActiveDocument.removeObject(self.obj.Name)
+ FreeCAD.ActiveDocument.commitTransaction()
+ FreeCAD.ActiveDocument.recompute()
+ self.vobj.Proxy.resetTaskPanel()
+ return True
+
+ def updateTooltips(self):
+ if hasattr(self.obj, "Proxy") and hasattr(self.obj.Proxy, "tooltip") and self.obj.Proxy.tooltip:
+ self.form.postProcessor.setToolTip(self.obj.Proxy.tooltip)
+ if hasattr(self.obj.Proxy, "tooltipArgs") and self.obj.Proxy.tooltipArgs:
+ self.form.postProcessorArguments.setToolTip(self.obj.Proxy.tooltipArgs)
+ else:
+ self.form.postProcessorArguments.setToolTip(self.postProcessorArgsDefaultTooltip)
+ else:
+ self.form.postProcessor.setToolTip(self.postProcessorDefaultTooltip)
+ self.form.postProcessorArguments.setToolTip(self.postProcessorArgsDefaultTooltip)
+
+ def getFields(self):
+ '''sets properties in the object to match the form'''
+ if self.obj:
+ self.obj.PostProcessor = str(self.form.postProcessor.currentText())
+ self.obj.PostProcessorArgs = str(self.form.postProcessorArguments.displayText())
+ self.obj.PostProcessorOutputFile = str(self.form.postProcessorOutputFile.text())
+
+ self.obj.Label = str(self.form.infoLabel.text())
+ self.obj.Group = [self.form.operationsList.item(i).data() for i in range(self.form.operationsList.count())]
+
+ selObj = self.form.infoModel.itemData(self.form.infoModel.currentIndex())
+ #if self.form.chkCreateClone.isChecked():
+ # selObj = Draft.clone(selObj)
+ self.obj.Base = selObj
+
+ self.updateTooltips()
+
+ self.obj.Proxy.execute(self.obj)
+
+ def selectComboBoxText(self, widget, text):
+ index = widget.findText(text, QtCore.Qt.MatchFixedString)
+ if index >= 0:
+ widget.blockSignals(True)
+ widget.setCurrentIndex(index)
+ widget.blockSignals(False)
+
+ def setFields(self):
+ '''sets fields in the form to match the object'''
+
+ self.form.infoLabel.setText(self.obj.Label)
+ self.form.postProcessorOutputFile.setText(self.obj.PostProcessorOutputFile)
+
+ self.selectComboBoxText(self.form.postProcessor, self.obj.PostProcessor)
+ self.form.postProcessorArguments.setText(self.obj.PostProcessorArgs)
+ self.obj.Proxy.onChanged(self.obj, "PostProcessor")
+ self.updateTooltips()
+
+ self.form.operationsList.clear()
+ for child in self.obj.Group:
+ item = QtGui.QListWidgetItem(child.Label)
+ item.setData(self.DataObject, child)
+ self.form.operationsList.addItem(item)
+
+ baseindex = -1
+ if self.obj.Base:
+ baseindex = self.form.infoModel.findText(self.obj.Base.Label, QtCore.Qt.MatchFixedString)
+ else:
+ for o in FreeCADGui.Selection.getCompleteSelection():
+ baseindex = self.form.infoModel.findText(o.Label, QtCore.Qt.MatchFixedString)
+ if baseindex >= 0:
+ self.form.infoModel.setCurrentIndex(baseindex)
+
+
+ def open(self):
+ pass
+
+ def setPostProcessorOutputFile(self):
+ filename = QtGui.QFileDialog.getSaveFileName(self.form, translate("Path_Job", "Select Output File"), None, translate("Path_Job", "All Files (*.*)"))
+ if filename and filename[0]:
+ self.obj.PostProcessorOutputFile = str(filename[0])
+ self.setFields()
+
+ def setupUi(self):
+ # Info
+ self.form.infoLabel.editingFinished.connect(self.getFields)
+ self.form.infoModel.currentIndexChanged.connect(self.getFields)
+
+ # Post Processor
+ self.form.postProcessor.currentIndexChanged.connect(self.getFields)
+ self.form.postProcessorArguments.editingFinished.connect(self.getFields)
+ self.form.postProcessorOutputFile.editingFinished.connect(self.getFields)
+ self.form.postProcessorSetOutputFile.clicked.connect(self.setPostProcessorOutputFile)
+
+ self.form.operationsList.indexesMoved.connect(self.getFields)
+
+ self.setFields()
+
+class DlgJobCreate:
+
+ def __init__(self, parent=None):
+ self.dialog = FreeCADGui.PySideUic.loadUi(":/panels/DlgJobCreate.ui")
+ sel = FreeCADGui.Selection.getSelection()
+ if sel:
+ selected = sel[0].Label
+ else:
+ selected = None
+ index = 0
+ for base in PathJob.ObjectJob.baseCandidates():
+ if base.Label == selected:
+ index = self.dialog.cbModel.count()
+ self.dialog.cbModel.addItem(base.Label)
+ self.dialog.cbModel.setCurrentIndex(index)
+
+ templateFiles = []
+ for path in PathPreferences.searchPaths():
+ templateFiles.extend(self.templateFilesIn(path))
+
+ template = {}
+ for tFile in templateFiles:
+ name = os.path.split(os.path.splitext(tFile)[0])[1][4:]
+ if name in template:
+ basename = name
+ i = 0
+ while name in template:
+ i = i + 1
+ name = basename + " (%s)" % i
+ PathLog.track(name, tFile)
+ template[name] = tFile
+ selectTemplate = PathPreferences.defaultJobTemplate()
+ index = 0
+ self.dialog.cbTemplate.addItem('', '')
+ for name in sorted(template.keys()):
+ if template[name] == selectTemplate:
+ index = self.dialog.cbTemplate.count()
+ self.dialog.cbTemplate.addItem(name, template[name])
+ self.dialog.cbTemplate.setCurrentIndex(index)
+
+ def templateFilesIn(self, path):
+ '''templateFilesIn(path) ... answer all file in the given directory which fit the job template naming convention.
+ PathJob template files are name job_*.xml'''
+ PathLog.track(path)
+ return glob.glob(path + '/job_*.xml')
+
+ def getModel(self):
+ '''answer the base model selected for the job'''
+ label = self.dialog.cbModel.currentText()
+ return filter(lambda obj: obj.Label == label, FreeCAD.ActiveDocument.Objects)[0]
+
+ def getTemplate(self):
+ '''answer the file name of the template to be assigned'''
+ return self.dialog.cbTemplate.itemData(self.dialog.cbTemplate.currentIndex())
+
+ def exec_(self):
+ return self.dialog.exec_()
+
+def Create(base, template):
+ FreeCADGui.addModule('PathScripts.PathJob')
+ FreeCAD.ActiveDocument.openTransaction(translate("Path_Job", "Create Job"))
+ #try:
+ obj = PathJob.Create('Job', base, template)
+ ViewProvider(obj.ViewObject)
+ FreeCAD.ActiveDocument.commitTransaction()
+ #except:
+ # PathLog.error(sys.exc_info())
+ # FreeCAD.ActiveDocument.abortTransaction()
+
+class CommandJobCreate:
+ '''
+ Command used to creat a command.
+ When activated the command opens a dialog allowing the user to select a base object (has to be a solid)
+ and a template to be used for the initial creation.
+ '''
+
+ def GetResources(self):
+ return {'Pixmap': 'Path-Job',
+ 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Job", "Job"),
+ 'Accel': "P, J",
+ 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Job", "Creates a Path Job object")}
+
+ def IsActive(self):
+ return FreeCAD.ActiveDocument is not None
+
+ def Activated(self):
+ dialog = DlgJobCreate()
+ if dialog.exec_() == 1:
+ self.Execute(dialog.getModel(), dialog.getTemplate())
+ FreeCAD.ActiveDocument.recompute()
+
+ @classmethod
+ def Execute(cls, base, template):
+ FreeCADGui.addModule('PathScripts.PathJobGui')
+ if template:
+ template = "'%s'" % template
+ else:
+ template = 'None'
+ FreeCADGui.doCommand('PathScripts.PathJobGui.Create(App.ActiveDocument.%s, %s)' % (base.Name, template))
+
+class CommandJobExportTemplate:
+ '''
+ Command to export a template of a given job.
+ Opens a dialog to select the file to store the template in. If the template is stored in Path's
+ file path (see preferences) and named in accordance with job_*.xml it will automatically be found
+ on Job creation and be available for selection.
+ '''
+
+ def GetResources(self):
+ return {'Pixmap': 'Path-Job',
+ 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Job", "Export Template"),
+ 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Job", "Exports Path Job as a template to be used for other jobs")}
+
+ def IsActive(self):
+ return FreeCAD.ActiveDocument is not None
+
+ def Activated(self):
+ job = FreeCADGui.Selection.getSelection()[0]
+ foo = QtGui.QFileDialog.getSaveFileName(QtGui.qApp.activeWindow(),
+ "Path - Job Template",
+ PathPreferences.filePath(),
+ "job_*.xml")[0]
+ if foo:
+ self.Execute(job, foo)
+
+ @classmethod
+ def Execute(cls, job, path):
+ root = xml.Element('PathJobTemplate')
+ xml.SubElement(root, JobTemplate.Job, job.Proxy.templateAttrs(job))
+ for obj in job.Group:
+ if hasattr(obj, 'Tool') and hasattr(obj, 'SpindleDir'):
+ tc = xml.SubElement(root, JobTemplate.ToolController, obj.Proxy.templateAttrs(obj))
+ tc.append(xml.fromstring(obj.Tool.Content))
+ xml.ElementTree(root).write(path)
+
+if FreeCAD.GuiUp:
+ # register the FreeCAD command
+ FreeCADGui.addCommand('Path_Job', CommandJobCreate())
+ FreeCADGui.addCommand('Path_ExportTemplate', CommandJobExportTemplate())
+
+FreeCAD.Console.PrintLog("Loading PathJob... done\n")
+
diff --git a/src/Mod/Path/PathScripts/PathPost.py b/src/Mod/Path/PathScripts/PathPost.py
index a75525259b..3713714542 100644
--- a/src/Mod/Path/PathScripts/PathPost.py
+++ b/src/Mod/Path/PathScripts/PathPost.py
@@ -225,7 +225,7 @@ class CommandPathPost:
targetlist = []
for o in FreeCAD.ActiveDocument.Objects:
if hasattr(o, "Proxy"):
- if isinstance(o.Proxy, PathJob.ObjectPathJob):
+ if isinstance(o.Proxy, PathJob.ObjectJob):
targetlist.append(o.Label)
PathLog.debug("Possible post objects: {}".format(targetlist))
if len(targetlist) > 1:
@@ -246,14 +246,13 @@ class CommandPathPost:
# Then post-the ordered list
postlist = []
currTool = None
- for obj in job.Group:
+ for obj in job.Operations.Group:
PathLog.debug("obj: {}".format(obj.Name))
- if not isinstance(obj.Proxy, PathToolController.ToolController):
- tc = PathUtil.toolControllerForOp(obj)
- if tc is not None:
- if tc.ToolNumber != currTool:
- postlist.append(tc)
- postlist.append(obj)
+ tc = PathUtil.toolControllerForOp(obj)
+ if tc is not None:
+ if tc.ToolNumber != currTool:
+ postlist.append(tc)
+ postlist.append(obj)
fail = True
rc = ''
diff --git a/src/Mod/Path/PathScripts/PathToolController.py b/src/Mod/Path/PathScripts/PathToolController.py
index 6cbed2fa57..15ccf73c68 100644
--- a/src/Mod/Path/PathScripts/PathToolController.py
+++ b/src/Mod/Path/PathScripts/PathToolController.py
@@ -35,7 +35,7 @@ import xml.etree.ElementTree as xml
from FreeCAD import Units
from PySide import QtCore, QtGui
-if False:
+if True:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
else:
@@ -78,6 +78,7 @@ class ToolController:
def assignTemplate(self, obj, template):
'''assignTemplate(obj, xmlItem) ... extract properties from xmlItem and assign to receiver.'''
+ PathLog.track(obj.Label, template)
if template.get(ToolControllerTemplate.VertFeed):
obj.VertFeed = template.get(ToolControllerTemplate.VertFeed)
if template.get(ToolControllerTemplate.HorizFeed):
@@ -135,12 +136,13 @@ class ToolController:
PathLog.track('prop: {} state: {}'.format(prop, obj.State))
if 'Path' == prop and 'Restore' not in obj.State:
- PathLog.debug("--- dirty deeds")
- job = PathScripts.PathUtils.findParentJob(obj)
- if job is not None:
- for g in job.Group:
- if not(isinstance(g.Proxy, PathScripts.PathToolController.ToolController)):
- g.touch()
+ PathLog.warning('Markus you gotta do something about TC changes')
+ # PathLog.debug("--- dirty deeds")
+ # job = PathScripts.PathUtils.findParentJob(obj)
+ # if job is not None:
+ # for g in job.Group:
+ # if not(isinstance(g.Proxy, PathScripts.PathToolController.ToolController)):
+ # g.touch()
def getTool(self, obj):
'''returns the tool associated with this tool controller'''
@@ -219,19 +221,8 @@ class CommandPathToolController:
PathLog.track()
self.Create()
-# FreeCAD.ActiveDocument.openTransaction(translate("Path_ToolController", "Create Tool Controller Object"))
-
-# obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TC")
-# PathScripts.PathToolController.ToolController(obj)
-# PathScripts.PathToolController._ViewProviderToolController(obj.ViewObject)
-
-# PathUtils.addToJob(obj)
-
-# FreeCAD.ActiveDocument.commitTransaction()
-# FreeCAD.ActiveDocument.recompute()
-
@staticmethod
- def Create(jobname=None, assignViewProvider=True, tool=None, toolNumber=1):
+ def Create(assignViewProvider=True, tool=None, toolNumber=1):
PathLog.track("tool: {} with toolNumber: {}".format(tool, toolNumber))
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "Default Tool")
@@ -248,10 +239,10 @@ class CommandPathToolController:
tool.Material = "HighSpeedSteel"
obj.Tool = tool
obj.ToolNumber = toolNumber
- PathScripts.PathUtils.addToJob(obj, jobname)
+ return obj
@staticmethod
- def FromTemplate(job, template, assignViewProvider=True):
+ def FromTemplate(template, assignViewProvider=True):
PathLog.track()
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", template.get(ToolControllerTemplate.Label))
@@ -261,7 +252,7 @@ class CommandPathToolController:
tc.assignTemplate(obj, template)
- PathScripts.PathUtils.addToJob(obj, job.Name)
+ return obj
class TaskPanel:
diff --git a/src/Mod/Path/PathScripts/PathToolLibraryManager.py b/src/Mod/Path/PathScripts/PathToolLibraryManager.py
index 8b30c7ea99..b40864918d 100644
--- a/src/Mod/Path/PathScripts/PathToolLibraryManager.py
+++ b/src/Mod/Path/PathScripts/PathToolLibraryManager.py
@@ -159,7 +159,7 @@ class ToolLibraryManager():
# Get ToolTables from any open CNC jobs
for o in FreeCAD.ActiveDocument.Objects:
if hasattr(o, "Proxy"):
- if isinstance(o.Proxy, PathScripts.PathJob.ObjectPathJob):
+ if isinstance(o.Proxy, PathScripts.PathJob.ObjectJob):
tablelist.append(o.Label)
return tablelist
@@ -546,7 +546,7 @@ class EditorPanel():
tool = self.TLM.getTool(currList, int(toolnum))
PathLog.debug('tool: {}, toolnum: {}'.format(tool, toolnum))
for job in FreeCAD.ActiveDocument.findObjects("Path::Feature"):
- if isinstance(job.Proxy, PathScripts.PathJob.ObjectPathJob) and job.Label == targetlist:
+ if isinstance(job.Proxy, PathScripts.PathJob.ObjectJob) and job.Label == targetlist:
label = "T{}: {}".format(toolnum, tool.Name)
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython",label)
diff --git a/src/Mod/Path/PathScripts/PathUtils.py b/src/Mod/Path/PathScripts/PathUtils.py
index 028c94144d..79b2e6f060 100644
--- a/src/Mod/Path/PathScripts/PathUtils.py
+++ b/src/Mod/Path/PathScripts/PathUtils.py
@@ -355,18 +355,14 @@ def changeTool(obj, job):
def getToolControllers(obj):
'''returns all the tool controllers'''
- controllers = []
try:
- parent = findParentJob(obj)
+ job = findParentJob(obj)
except:
- parent = None
+ job = None
- if parent is not None and hasattr(parent, 'Group'):
- sibs = parent.Group
- for g in sibs:
- if isinstance(g.Proxy, PathScripts.PathToolController.ToolController):
- controllers.append(g)
- return controllers
+ if job:
+ return job.ToolController
+ return []
def findToolController(obj, name=None):
@@ -417,7 +413,7 @@ def findParentJob(obj):
'''retrieves a parent job object for an operation or other Path object'''
PathLog.track()
for i in obj.InList:
- if isinstance(i.Proxy, PathScripts.PathJob.ObjectPathJob):
+ if isinstance(i.Proxy, PathScripts.PathJob.ObjectJob):
return i
if i.TypeId == "Path::FeaturePython" or i.TypeId == "Path::FeatureCompoundPython":
grandParent = findParentJob(i)
@@ -431,33 +427,14 @@ def GetJobs(jobname=None):
PathLog.track()
jobs = []
for o in FreeCAD.ActiveDocument.Objects:
- if "Proxy" in o.PropertiesList:
- if isinstance(o.Proxy, PathJob.ObjectPathJob):
- if jobname is not None:
- if o.Name == jobname:
- jobs.append(o)
- else:
+ if hasattr(o, 'Proxy') and isinstance(o.Proxy, PathJob.ObjectJob):
+ if jobname is not None:
+ if o.Name == jobname:
jobs.append(o)
+ else:
+ jobs.append(o)
return jobs
-def addObjectToJob(obj, job):
- '''
- addObjectToJob(obj, job) ... adds object to given job.
- '''
- g = job.Group
- g.append(obj)
- job.Group = g
- return job
-
-def addObjectToJob(obj, job):
- '''
- addObjectToJob(obj, job) ... adds object to given job.
- '''
- g = job.Group
- g.append(obj)
- job.Group = g
- return job
-
def addToJob(obj, jobname=None):
'''adds a path object to a job
obj = obj
@@ -490,7 +467,7 @@ def addToJob(obj, jobname=None):
job = [i for i in jobs if i.Label == form.cboProject.currentText()][0]
if obj:
- addObjectToJob(obj, job)
+ job.Proxy.addOperation(obj)
return job
def rapid(x=None, y=None, z=None):
diff --git a/src/Mod/Path/PathScripts/post/centroid_post.py b/src/Mod/Path/PathScripts/post/centroid_post.py
index 5c46077711..fd9591cee5 100644
--- a/src/Mod/Path/PathScripts/post/centroid_post.py
+++ b/src/Mod/Path/PathScripts/post/centroid_post.py
@@ -153,7 +153,7 @@ def export(objectslist, filename, argstring):
global UNITS
global UNIT_FORMAT
- # ISJOB = (len(objectslist) == 1) and isinstance(objectslist[0].Proxy, PathScripts.PathJob.ObjectPathJob)
+ # ISJOB = (len(objectslist) == 1) and isinstance(objectslist[0].Proxy, PathScripts.PathJob.ObjectJob)
# print("isjob: {} {}".format(ISJOB, len(objectslist)))
# if len(objectslist) > 1: