From bcfd92d388a25142b94c4bc3ff02750e8a911394 Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Tue, 28 Aug 2018 21:51:45 -0700 Subject: [PATCH] Refactored job creation dialog to be re-used for model selection dialog. --- src/Mod/Path/CMakeLists.txt | 1 + .../Path/Gui/Resources/panels/DlgJobCreate.ui | 10 - src/Mod/Path/PathScripts/PathJob.py | 4 +- src/Mod/Path/PathScripts/PathJobCmd.py | 77 +------ src/Mod/Path/PathScripts/PathJobDlg.py | 211 ++++++++++++++++++ src/Mod/Path/PathScripts/PathJobGui.py | 53 ++--- 6 files changed, 243 insertions(+), 113 deletions(-) create mode 100644 src/Mod/Path/PathScripts/PathJobDlg.py diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index 0f87dd5849..37a60d27d3 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -60,6 +60,7 @@ SET(PathScripts_SRCS PathScripts/PathInspect.py PathScripts/PathJob.py PathScripts/PathJobCmd.py + PathScripts/PathJobDlg.py PathScripts/PathJobGui.py PathScripts/PathLog.py PathScripts/PathMillFace.py diff --git a/src/Mod/Path/Gui/Resources/panels/DlgJobCreate.ui b/src/Mod/Path/Gui/Resources/panels/DlgJobCreate.ui index 818ea2cb83..35f6c6500a 100644 --- a/src/Mod/Path/Gui/Resources/panels/DlgJobCreate.ui +++ b/src/Mod/Path/Gui/Resources/panels/DlgJobCreate.ui @@ -67,16 +67,6 @@ - - - Base Models - - - - - - - diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/PathScripts/PathJob.py index 482b3f41d9..f0cd09aedb 100644 --- a/src/Mod/Path/PathScripts/PathJob.py +++ b/src/Mod/Path/PathScripts/PathJob.py @@ -66,7 +66,7 @@ def isArchPanelSheet(obj): return hasattr(obj, 'Proxy') and isinstance(obj.Proxy, ArchPanel.PanelSheet) def isResourceClone(obj, propLink, resourceName): - if hasattr(propLink, 'PathResource') and resourceName == propLink.PathResource: + if hasattr(propLink, 'PathResource') and (resourceName is None or resourceName == propLink.PathResource): return True return False @@ -175,7 +175,7 @@ class ObjectJob: # base doesn't depend on anything inside job for base in obj.Model.Group: - PathLog.debug("taking down base " % base.Label) + PathLog.debug("taking down base %s" % base.Label) if isResourceClone(obj, base, 'Model'): PathUtil.clearExpressionEngine(base) doc.removeObject(base.Name) diff --git a/src/Mod/Path/PathScripts/PathJobCmd.py b/src/Mod/Path/PathScripts/PathJobCmd.py index 7cb6c8f0c3..655a4bf130 100644 --- a/src/Mod/Path/PathScripts/PathJobCmd.py +++ b/src/Mod/Path/PathScripts/PathJobCmd.py @@ -25,13 +25,12 @@ import FreeCAD import FreeCADGui import PathScripts.PathJob as PathJob +import PathScripts.PathJobDlg as PathJobDlg import PathScripts.PathLog as PathLog import PathScripts.PathPreferences as PathPreferences import PathScripts.PathStock as PathStock import PathScripts.PathUtil as PathUtil -import glob import json -import os from PySide import QtCore, QtGui @@ -39,69 +38,11 @@ from PySide import QtCore, QtGui def translate(context, text, disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) -class DlgJobCreate: - DataObject = QtCore.Qt.ItemDataRole.UserRole - - def __init__(self, parent=None): - self.dialog = FreeCADGui.PySideUic.loadUi(":/panels/DlgJobCreate.ui") - self.items = [] - - sel = FreeCADGui.Selection.getSelection() - if sel: - selected = [s.Label for s in sel] - else: - selected = None - index = 0 - for base in sorted(PathJob.ObjectJob.baseCandidates(), key=lambda o: o.Label): - item = QtGui.QListWidgetItem(base.Label) - item.setData(self.DataObject, base) - item.setCheckState(QtCore.Qt.CheckState.Checked if base.Label in selected else QtCore.Qt.CheckState.Unchecked) - if PathUtil.isSolid(base): - self.dialog.solidList.addItem(item) - else: - self.dialog.twoDList.addItem(item) - self.items.append(item) - - 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.jobTemplate.addItem('', '') - for name in sorted(template.keys()): - if template[name] == selectTemplate: - index = self.dialog.jobTemplate.count() - self.dialog.jobTemplate.addItem(name, template[name]) - self.dialog.jobTemplate.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_*.json''' - PathLog.track(path) - return glob.glob(path + '/job_*.json') - - def getModels(self): - '''answer the base models selected for the job''' - return [item.data(self.DataObject) for item in self.items if item.checkState() == QtCore.Qt.CheckState.Checked] - - def getTemplate(self): - '''answer the file name of the template to be assigned''' - return self.dialog.jobTemplate.itemData(self.dialog.jobTemplate.currentIndex()) - - def exec_(self): - return self.dialog.exec_() +if False: + PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) + PathLog.trackModule(PathLog.thisModule()) +else: + PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) class CommandJobCreate: ''' @@ -120,7 +61,9 @@ class CommandJobCreate: return FreeCAD.ActiveDocument is not None def Activated(self): - dialog = DlgJobCreate() + dialog = PathJobDlg.JobCreate() + dialog.setupTemplate() + dialog.setupModel() if dialog.exec_() == 1: models = dialog.getModels() if models: @@ -280,7 +223,7 @@ class CommandJobTemplateExport: def Activated(self): job = self.GetJob() - dialog = DlgJobTemplateExport(job) + dialog = PathJobDlg.JobTemplateExport(job) if dialog.exec_() == 1: self.SaveDialog(job, dialog) diff --git a/src/Mod/Path/PathScripts/PathJobDlg.py b/src/Mod/Path/PathScripts/PathJobDlg.py new file mode 100644 index 0000000000..8f3b2fa26b --- /dev/null +++ b/src/Mod/Path/PathScripts/PathJobDlg.py @@ -0,0 +1,211 @@ +# -*- coding: utf-8 -*- + +# *************************************************************************** +# * * +# * Copyright (c) 2018 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.PathPreferences as PathPreferences +import PathScripts.PathStock as PathStock +import PathScripts.PathUtil as PathUtil +import glob +import os + +from PySide import QtCore, QtGui + +# Qt tanslation handling +def translate(context, text, disambig=None): + return QtCore.QCoreApplication.translate(context, text, disambig) + +if False: + PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) + PathLog.trackModule(PathLog.thisModule()) +else: + PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) + +class JobCreate: + DataObject = QtCore.Qt.ItemDataRole.UserRole + + def __init__(self, parent=None, sel=None): + self.dialog = FreeCADGui.PySideUic.loadUi(":/panels/DlgJobCreate.ui") + self.items = [] + self.dialog.templateGroup.hide() + self.dialog.modelGroup.hide() + + def setupTitle(self, title): + self.dialog.setWindowTitle(title) + + def setupModel(self, job = None): + if job: + sel = [PathUtil.getPublicObject(job.Proxy.baseObject(job, obj)) for obj in job.Model.Group] + xxx = job.Model.Group + [job.Stock] + else: + sel = FreeCADGui.Selection.getSelection() + xxx = [] + + if sel: + selected = [s.Label for s in sel] + else: + selected = [] + + index = 0 + for base in sorted(PathJob.ObjectJob.baseCandidates(), key=lambda o: o.Label): + if not base in xxx and not PathJob.isResourceClone(job, base, None): + item = QtGui.QListWidgetItem(base.Label) + item.setData(self.DataObject, base) + item.setCheckState(QtCore.Qt.CheckState.Checked if base.Label in selected else QtCore.Qt.CheckState.Unchecked) + if PathUtil.isSolid(base): + self.dialog.solidList.addItem(item) + else: + self.dialog.twoDList.addItem(item) + self.items.append(item) + self.dialog.modelGroup.show() + + + def setupTemplate(self): + 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.jobTemplate.addItem('', '') + for name in sorted(template.keys()): + if template[name] == selectTemplate: + index = self.dialog.jobTemplate.count() + self.dialog.jobTemplate.addItem(name, template[name]) + self.dialog.jobTemplate.setCurrentIndex(index) + self.dialog.templateGroup.show() + + 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_*.json''' + PathLog.track(path) + return glob.glob(path + '/job_*.json') + + def getModels(self): + '''answer the base models selected for the job''' + return [item.data(self.DataObject) for item in self.items if item.checkState() == QtCore.Qt.CheckState.Checked] + + def getTemplate(self): + '''answer the file name of the template to be assigned''' + return self.dialog.jobTemplate.itemData(self.dialog.jobTemplate.currentIndex()) + + def exec_(self): + return self.dialog.exec_() + + +class JobTemplateExport: + DataObject = QtCore.Qt.ItemDataRole.UserRole + + def __init__(self, job, parent=None): + self.job = job + self.dialog = FreeCADGui.PySideUic.loadUi(":/panels/DlgJobTemplateExport.ui") + + if job.PostProcessor: + ppHint = "%s %s %s" % (job.PostProcessor, job.PostProcessorArgs, job.PostProcessorOutputFile) + self.dialog.postProcessingHint.setText(ppHint) + else: + self.dialog.postProcessingGroup.setEnabled(False) + self.dialog.postProcessingGroup.setChecked(False) + + if job.Stock and not PathJob.isResourceClone(job, 'Stock', 'Stock'): + stockType = PathStock.StockType.FromStock(job.Stock) + if stockType == PathStock.StockType.FromBase: + seHint = translate('PathJob', "Base -/+ %.2f/%.2f %.2f/%.2f %.2f/%.2f") % (job.Stock.ExtXneg, job.Stock.ExtXpos, job.Stock.ExtYneg, job.Stock.ExtYpos, job.Stock.ExtZneg, job.Stock.ExtZpos) + self.dialog.stockPlacement.setChecked(False) + elif stockType == PathStock.StockType.CreateBox: + seHint = translate('PathJob', "Box: %.2f x %.2f x %.2f") % (job.Stock.Length, job.Stock.Width, job.Stock.Height) + elif stockType == PathStock.StockType.CreateCylinder: + seHint = translate('PathJob', "Cylinder: %.2f x %.2f") % (job.Stock.Radius, job.Stock.Height) + else: + seHint = '-' + PathLog.error(translate('PathJob', 'Unsupported stock type')) + self.dialog.stockExtentHint.setText(seHint) + spHint = "%s" % job.Stock.Placement + self.dialog.stockPlacementHint.setText(spHint) + + rapidChanged = not job.SetupSheet.Proxy.hasDefaultToolRapids() + depthsChanged = not job.SetupSheet.Proxy.hasDefaultOperationDepths() + heightsChanged = not job.SetupSheet.Proxy.hasDefaultOperationHeights() + settingsChanged = rapidChanged or depthsChanged or heightsChanged + self.dialog.settingsGroup.setChecked(settingsChanged) + self.dialog.settingToolRapid.setChecked(rapidChanged) + self.dialog.settingOperationDepths.setChecked(depthsChanged) + self.dialog.settingOperationHeights.setChecked(heightsChanged) + + for tc in sorted(job.ToolController, key=lambda o: o.Label): + item = QtGui.QListWidgetItem(tc.Label) + item.setData(self.DataObject, tc) + item.setCheckState(QtCore.Qt.CheckState.Checked) + self.dialog.toolsList.addItem(item) + + self.dialog.toolsGroup.clicked.connect(self.checkUncheckTools) + + def checkUncheckTools(self): + state = QtCore.Qt.CheckState.Checked if self.dialog.toolsGroup.isChecked() else QtCore.Qt.CheckState.Unchecked + for i in range(self.dialog.toolsList.count()): + self.dialog.toolsList.item(i).setCheckState(state) + + def includePostProcessing(self): + return self.dialog.postProcessingGroup.isChecked() + + def includeToolControllers(self): + tcs = [] + for i in range(self.dialog.toolsList.count()): + item = self.dialog.toolsList.item(i) + if item.checkState() == QtCore.Qt.CheckState.Checked: + tcs.append(item.data(self.DataObject)) + return tcs + + def includeStock(self): + return self.dialog.stockGroup.isChecked() + def includeStockExtent(self): + return self.dialog.stockExtent.isChecked() + def includeStockPlacement(self): + return self.dialog.stockPlacement.isChecked() + + def includeSettings(self): + return self.dialog.settingsGroup.isChecked() + def includeSettingToolRapid(self): + return self.dialog.settingToolRapid.isChecked() + def includeSettingOperationHeights(self): + return self.dialog.settingOperationHeights.isChecked() + def includeSettingOperationDepths(self): + return self.dialog.settingOperationDepths.isChecked() + + def exec_(self): + return self.dialog.exec_() + diff --git a/src/Mod/Path/PathScripts/PathJobGui.py b/src/Mod/Path/PathScripts/PathJobGui.py index b0ba1e49e0..2b3ab22573 100644 --- a/src/Mod/Path/PathScripts/PathJobGui.py +++ b/src/Mod/Path/PathScripts/PathJobGui.py @@ -27,7 +27,7 @@ import DraftVecUtils import FreeCAD import FreeCADGui import PathScripts.PathJob as PathJob -import PathScripts.PathJobCmd as PathJobCmd +import PathScripts.PathJobDlg as PathJobDlg import PathScripts.PathGeom as PathGeom import PathScripts.PathGui as PathGui import PathScripts.PathLog as PathLog @@ -171,37 +171,13 @@ class ViewProvider: def updateData(self, obj, prop): PathLog.track(obj.Label, prop) # make sure the resource view providers are setup properly - if prop == 'Model': + if prop == 'Model' and self.obj.Model: for base in self.obj.Model.Group: if base.ViewObject and base.ViewObject.Proxy and not PathJob.isArchPanelSheet(base): base.ViewObject.Proxy.onEdit(_OpenCloseResourceEditor) if prop == 'Stock' and self.obj.Stock and self.obj.Stock.ViewObject and self.obj.Stock.ViewObject.Proxy: self.obj.Stock.ViewObject.Proxy.onEdit(_OpenCloseResourceEditor) - def baseObjectViewObject(self, obj): - return [PathUtil.getPublicObject(base).ViewObject for base in self.obj.Proxy.baseObjects(obj)] - - def baseObjectSaveVisibility(self, obj): - baseVO = self.baseObjectViewObject(self.obj) - baseOrigVisibility = [] - for vo in baseVO: - baseOrigVisibility = vo.Visibility - vo.Visibility = False - self.baseOrigVisibility = baseOrigVisibility - - for base in obj.Model.Group: - if base.ViewObject: - base.ViewObject.Visibility = True - - def baseObjectRestoreVisibility(self, obj): - baseVO = self.baseObjectViewObject(self.obj) - if self.baseOrigVisibility: - for vo, visibility in zip(baseVO, self.baseOrigVisibility): - vo.Visibility = visibility - else: - for vo in baseVO: - vo.Visibility = False - def setupModelVisibility(self, obj): baseVisibility = [] origVisibility = [] @@ -216,6 +192,12 @@ class ViewProvider: self.baseVisibility = baseVisibility self.baseOrigVisibility = origVisibility + def resetModelVisibility(self, obj): + for base, baseVisibility, origVisibility in zip(obj.Model.Group, self.baseVisibility, self.baseOrigVisibility): + if base.ViewObject: + orig = PathUtil.getPublicObject(obj.Proxy.baseObject(obj, base)) + base.ViewObject.Visibility = baseVisibility + orig.ViewObject.Visibility = origVisibility def setupEditVisibility(self, obj): self.setupModelVisibility(obj) @@ -225,11 +207,7 @@ class ViewProvider: self.obj.Stock.ViewObject.Visibility = True def resetEditVisibility(self, obj): - for base, baseVisibility, origVisibility in zip(obj.Model.Group, self.baseVisibility, self.baseOrigVisibility): - if base.ViewObject: - orig = PathUtil.getPublicObject(obj.Proxy.baseObject(obj, base)) - base.ViewObject.Visibility = baseVisibility - orig.ViewObject.Visibility = origVisibility + self.resetModelVisibility(obj) if obj.Stock and obj.Stock.ViewObject: obj.Stock.ViewObject.Visibility = self.stockVisibility @@ -974,6 +952,15 @@ class TaskPanel: self.form.centerInStock.setEnabled(False) self.form.centerInStockXY.setEnabled(False) + def jobModelEdit(self): + dialog = PathJobDlg.JobCreate() + dialog.setupTitle(translate("Path_Job", "Model Selection")) + dialog.setupModel(self.obj) + if dialog.exec_() == 1: + models = dialog.getModels() + if models: + PathLog.error("shouldn't you be doing something here") + def tabPageChanged(self, index): if index == 0: # update the template with potential changes @@ -984,14 +971,12 @@ class TaskPanel: self.template.updateUI() def setupUi(self, activate): - self.setupGlobal.setupUi() - self.setupOps.setupUi() self.updateStockEditor(-1) self.setFields() # Info self.form.jobLabel.editingFinished.connect(self.getFields) - #self.form.jobModelEdit.clicked.connect(self.jobModelEdit) + self.form.jobModelEdit.clicked.connect(self.jobModelEdit) # Post Processor self.form.postProcessor.currentIndexChanged.connect(self.getFields)