From b4d04280592dd5dec161645ca650a729543b9fcb Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Thu, 14 Sep 2017 16:35:22 -0700 Subject: [PATCH] Changed PathJob to deal with JSON template files instead of XML. --- src/Mod/Path/PathScripts/PathJob.py | 56 ++++++++++++++------------ src/Mod/Path/PathScripts/PathJobCmd.py | 38 ++++++++--------- src/Mod/Path/PathScripts/PathJobGui.py | 2 +- src/Mod/Path/PathScripts/PathStock.py | 14 +++---- src/Mod/Path/TestPathApp.py | 22 +++++----- 5 files changed, 70 insertions(+), 62 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/PathScripts/PathJob.py index cb3d6fbe62..b1487da669 100644 --- a/src/Mod/Path/PathScripts/PathJob.py +++ b/src/Mod/Path/PathScripts/PathJob.py @@ -30,7 +30,7 @@ import PathScripts.PathLog as PathLog import PathScripts.PathStock as PathStock import PathScripts.PathToolController as PathToolController import PathScripts.PathUtil as PathUtil -import xml.etree.ElementTree as xml +import json from PathScripts.PathPreferences import PathPreferences from PathScripts.PathPostProcessor import PostProcessor @@ -81,7 +81,7 @@ def createResourceClone(obj, orig, name, icon): class ObjectJob: - def __init__(self, obj, base, template = None): + def __init__(self, obj, base, templateFile = None): self.obj = obj obj.addProperty("App::PropertyFile", "PostProcessorOutputFile", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property","The NC output file for this project")) obj.addProperty("App::PropertyEnumeration", "PostProcessor", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property","Select the Post Processor")) @@ -115,7 +115,7 @@ class ObjectJob: obj.Base = createResourceClone(obj, base, 'Base', 'BaseGeometry') obj.Proxy = self - self.setFromTemplate(obj, template) + self.setFromTemplateFile(obj, templateFile) if not obj.Stock: obj.Stock = PathStock.CreateFromBase(obj) if obj.Stock.ViewObject: @@ -165,29 +165,33 @@ class ObjectJob: return obj.Base.Objects[0] return obj.Base - def setFromTemplate(self, obj, template): - '''setFromTemplate(obj, template) ... extract the properties from the given template file and assign to receiver. + def setFromTemplateFile(self, obj, template): + '''setFromTemplateFile(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): - if job.get(JobTemplate.GeometryTolerance): - obj.GeometryTolerance = float(job.get(JobTemplate.GeometryTolerance)) - if job.get(JobTemplate.PostProcessor): - obj.PostProcessor = job.get(JobTemplate.PostProcessor) - if job.get(JobTemplate.PostProcessorArgs): - obj.PostProcessorArgs = job.get(JobTemplate.PostProcessorArgs) - else: - obj.PostProcessorArgs = '' - if job.get(JobTemplate.PostProcessorOutputFile): - obj.PostProcessorOutputFile = job.get(JobTemplate.PostProcessorOutputFile) - if job.get(JobTemplate.Description): - obj.Description = job.get(JobTemplate.Description) - for tc in tree.getroot().iter(JobTemplate.ToolController): - tcs.append(PathToolController.FromTemplate(tc)) - for stock in tree.getroot().iter(JobTemplate.Stock): - obj.Stock = PathStock.CreateFromTemplate(self, stock) + with open(unicode(template), 'rb') as fp: + attrs = json.load(fp) + + if attrs.get(JobTemplate.GeometryTolerance): + obj.GeometryTolerance = float(attrs.get(JobTemplate.GeometryTolerance)) + if attrs.get(JobTemplate.PostProcessor): + obj.PostProcessor = attrs.get(JobTemplate.PostProcessor) + if attrs.get(JobTemplate.PostProcessorArgs): + obj.PostProcessorArgs = attrs.get(JobTemplate.PostProcessorArgs) + else: + obj.PostProcessorArgs = '' + if attrs.get(JobTemplate.PostProcessorOutputFile): + obj.PostProcessorOutputFile = attrs.get(JobTemplate.PostProcessorOutputFile) + if attrs.get(JobTemplate.Description): + obj.Description = attrs.get(JobTemplate.Description) + + + if attrs.get(JobTemplate.ToolController): + for tc in attrs.get(JobTemplate.ToolController): + tcs.append(PathToolController.FromTemplate(tc)) + if attrs.get(JobTemplate.Stock): + obj.Stock = PathStock.CreateFromTemplate(obj, attrs.get(JobTemplate.Stock)) else: tcs.append(PathToolController.Create()) PathLog.debug("setting tool controllers (%d)" % len(tcs)) @@ -258,8 +262,10 @@ class ObjectJob: '''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): +def Create(name, base, templateFile = None): + '''Create(name, base, templateFile=None) ... creates a new job and all it's resources. + If a template file is specified the new job is initialized with the values from the template.''' obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) - proxy = ObjectJob(obj, base, template) + proxy = ObjectJob(obj, base, templateFile) return obj diff --git a/src/Mod/Path/PathScripts/PathJobCmd.py b/src/Mod/Path/PathScripts/PathJobCmd.py index 85317c6f6d..b91599c362 100644 --- a/src/Mod/Path/PathScripts/PathJobCmd.py +++ b/src/Mod/Path/PathScripts/PathJobCmd.py @@ -28,8 +28,8 @@ import PathScripts.PathJob as PathJob import PathScripts.PathLog as PathLog import PathScripts.PathStock as PathStock import glob +import json import os -import xml.etree.ElementTree as xml from PathScripts.PathPreferences import PathPreferences from PySide import QtCore, QtGui @@ -80,9 +80,9 @@ class DlgJobCreate: 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''' + PathJob template files are name job_*.json''' PathLog.track(path) - return glob.glob(path + '/job_*.xml') + return glob.glob(path + '/job_*.json') def getModel(self): '''answer the base model selected for the job''' @@ -197,7 +197,7 @@ class CommandJobTemplateExport: ''' 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 + file path (see preferences) and named in accordance with job_*.json it will automatically be found on Job creation and be available for selection. ''' @@ -216,29 +216,31 @@ class CommandJobTemplateExport: foo = QtGui.QFileDialog.getSaveFileName(QtGui.qApp.activeWindow(), "Path - Job Template", PathPreferences.filePath(), - "job_*.xml")[0] + "job_*.json")[0] if foo: self.Execute(job, foo, dialog) @classmethod def Execute(cls, job, path, dialog=None): - root = xml.Element('PathJobTemplate') - jobAttributes = job.Proxy.templateAttrs(job) + attrs = job.Proxy.templateAttrs(job) if dialog and not dialog.includePostProcessing(): - jobAttributes.pop(PathJob.JobTemplate.PostProcessor, None) - jobAttributes.pob(PathJob.JobTemplate.PostProcessorArgs, None) - jobAttributes.pob(PathJob.JobTemplate.PostProcessorOutputFile, None) - xml.SubElement(root, PathJob.JobTemplate.Job, jobAttributes) - tcs = dialog.includeToolControllers() if dialog else job.ToolController - for tc in tcs: - element = xml.SubElement(root, PathJob.JobTemplate.ToolController, tc.Proxy.templateAttrs(tc)) - element.append(xml.fromstring(tc.Tool.Content)) + attrs.pop(PathJob.JobTemplate.PostProcessor, None) + attrs.pob(PathJob.JobTemplate.PostProcessorArgs, None) + attrs.pob(PathJob.JobTemplate.PostProcessorOutputFile, None) + toolControllers = dialog.includeToolControllers() if dialog else job.ToolController + if toolControllers: + tcAttrs = [tc.Proxy.templateAttrs(tc) for tc in toolControllers] + attrs[PathJob.JobTemplate.ToolController] = tcAttrs + stockAttrs = None if dialog: if dialog.includeStock(): - xml.SubElement(root, PathJob.JobTemplate.Stock, PathStock.TemplateAttributes(job.Stock, dialog.includeStockExtent(), dialog.includeStockPlacement())) + stockAttrs = PathStock.TemplateAttributes(job.Stock, dialog.includeStockExtent(), dialog.includeStockPlacement()) else: - xml.SubElement(root, PathJob.JobTemplate.Stock, PathStock.TemplateAttributes(job.Stock)) - xml.ElementTree(root).write(path) + stockAttrs = PathStock.TemplateAttributes(job.Stock) + if stockAttrs: + attrs[PathJob.JobTemplate.Stock] = stockAttrs + with open(unicode(path), 'wb') as fp: + json.dump(attrs, fp, sort_keys=True, indent=2) if FreeCAD.GuiUp: # register the FreeCAD command diff --git a/src/Mod/Path/PathScripts/PathJobGui.py b/src/Mod/Path/PathScripts/PathJobGui.py index 79346ec91e..9dfef3cc2a 100644 --- a/src/Mod/Path/PathScripts/PathJobGui.py +++ b/src/Mod/Path/PathScripts/PathJobGui.py @@ -202,7 +202,7 @@ class StockEdit(object): obj.Document.removeObject(self.obj.Stock.Name) obj.Stock = stock if stock.ViewObject and stock.ViewObject.Proxy: - stock.ViewObject.Proxy.onEdit(OpenCloseResourceEditor) + stock.ViewObject.Proxy.onEdit(_OpenCloseResourceEditor) def setLengthField(self, widget, prop): widget.setText(FreeCAD.Units.Quantity(prop.Value, FreeCAD.Units.Length).UserString) diff --git a/src/Mod/Path/PathScripts/PathStock.py b/src/Mod/Path/PathScripts/PathStock.py index 3d41985f8b..077b1eca03 100644 --- a/src/Mod/Path/PathScripts/PathStock.py +++ b/src/Mod/Path/PathScripts/PathStock.py @@ -258,14 +258,14 @@ def TemplateAttributes(stock, includeExtent=True, includePlacement=True): if includePlacement: pos = stock.Placement.Base - attrs['posX'] = ("%f" % pos.x) - attrs['posY'] = ("%f" % pos.y) - attrs['posZ'] = ("%f" % pos.z) + attrs['posX'] = pos.x + attrs['posY'] = pos.y + attrs['posZ'] = pos.z rot = stock.Placement.Rotation - attrs['rotX'] = ("%f" % rot.Q[0]) - attrs['rotY'] = ("%f" % rot.Q[1]) - attrs['rotZ'] = ("%f" % rot.Q[2]) - attrs['rotW'] = ("%f" % rot.Q[3]) + attrs['rotX'] = rot.Q[0] + attrs['rotY'] = rot.Q[1] + attrs['rotZ'] = rot.Q[2] + attrs['rotW'] = rot.Q[3] return attrs diff --git a/src/Mod/Path/TestPathApp.py b/src/Mod/Path/TestPathApp.py index c79aee75d1..f8ca143226 100644 --- a/src/Mod/Path/TestPathApp.py +++ b/src/Mod/Path/TestPathApp.py @@ -24,15 +24,15 @@ import TestApp -#from PathTests.TestPathLog import TestPathLog -#from PathTests.TestPathCore import TestPathCore -##from PathTests.TestPathPost import PathPostTestCases -#from PathTests.TestPathGeom import TestPathGeom -#from PathTests.TestPathUtil import TestPathUtil -#from PathTests.TestPathDepthParams import depthTestCases -#from PathTests.TestPathDressupHoldingTags import TestHoldingTags -#from PathTests.TestPathDressupDogbone import TestDressupDogbone -#from PathTests.TestPathStock import TestPathStock -#from PathTests.TestPathTool import TestPathTool -#from PathTests.TestPathTooltable import TestPathTooltable +from PathTests.TestPathLog import TestPathLog +from PathTests.TestPathCore import TestPathCore +#from PathTests.TestPathPost import PathPostTestCases +from PathTests.TestPathGeom import TestPathGeom +from PathTests.TestPathUtil import TestPathUtil +from PathTests.TestPathDepthParams import depthTestCases +from PathTests.TestPathDressupHoldingTags import TestHoldingTags +from PathTests.TestPathDressupDogbone import TestDressupDogbone +from PathTests.TestPathStock import TestPathStock +from PathTests.TestPathTool import TestPathTool +from PathTests.TestPathTooltable import TestPathTooltable from PathTests.TestPathToolController import TestPathToolController