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 +
Gui/InputField.h
+
+
+ + +
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: