Added suppor for default OutputFile with templates and a policy on how to deal with file name conflicts.

This commit is contained in:
ml
2016-10-23 22:23:38 -07:00
committed by wmayer
parent a66b4683ba
commit 27f47f84dd
6 changed files with 327 additions and 84 deletions

View File

@@ -28,6 +28,7 @@ from PySide import QtCore, QtGui
import os
import glob
from PathScripts.PathPostProcessor import PostProcessor
from PathScripts.PathPost import CommandPathPost as PathPost
import Draft
@@ -47,12 +48,24 @@ except AttributeError:
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
class OutputPolicy:
Default = 'Use default'
Dialog = 'Open File Dialog'
DialogOnConflict = 'Open File Dialog on conflict'
Overwrite = 'Overwrite existing file'
AppendID = 'Append Unique ID on conflict'
All = [Default, Dialog, DialogOnConflict, Overwrite, AppendID]
class ObjectPathJob:
def __init__(self, obj):
# obj.addProperty("App::PropertyFile", "PostProcessor", "CodeOutput", "Select the Post Processor file for this project")
obj.addProperty("App::PropertyFile", "OutputFile", "CodeOutput", QtCore.QT_TRANSLATE_NOOP("App::Property","The NC output file for this project"))
obj.OutputFile = PathPost.defaultOutputFile()
obj.setEditorMode("OutputFile", 0) # set to default mode
obj.addProperty("App::PropertyEnumeration", "OutputPolicy", "CodeOutput", QtCore.QT_TRANSLATE_NOOP("App::Property","The policy on how to save output files and resolve name conflicts"))
obj.OutputPolicy = OutputPolicy.All
obj.OutputPolicy = OutputPolicy.Default
obj.addProperty("App::PropertyString", "Description", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","An optional description for this job"))
obj.addProperty("App::PropertyEnumeration", "PostProcessor", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property","Select the Post Processor"))
@@ -270,6 +283,8 @@ class TaskPanel:
self.obj.Label = str(self.form.leLabel.text())
if hasattr(self.obj, "OutputFile"):
self.obj.OutputFile = str(self.form.leOutputFile.text())
if hasattr(self.obj, "OutputPolicy"):
self.obj.OutputPolicy = str(self.form.cboOutputPolicy.currentText())
oldlist = self.obj.Group
newlist = []
@@ -291,21 +306,23 @@ class TaskPanel:
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.OutputFile)
self.selectComboBoxText(self.form.cboOutputPolicy, self.obj.OutputPolicy)
postindex = self.form.cboPostProcessor.findText(
self.obj.PostProcessor, QtCore.Qt.MatchFixedString)
if postindex >= 0:
self.form.cboPostProcessor.blockSignals(True)
self.form.cboPostProcessor.setCurrentIndex(postindex)
self.form.cboPostProcessor.blockSignals(False)
# make sure the proxy loads post processor script values and settings
self.obj.Proxy.onChanged(self.obj, "PostProcessor")
self.updateTooltips()
self.selectComboBoxText(self.form.cboPostProcessor, self.obj.PostProcessor)
self.obj.Proxy.onChanged(self.obj, "PostProcessor")
self.updateTooltips()
for child in self.obj.Group:
self.form.PathsList.addItem(child.Name)
@@ -335,6 +352,7 @@ class TaskPanel:
# Connect Signals and Slots
self.form.cboPostProcessor.currentIndexChanged.connect(self.getFields)
self.form.leOutputFile.editingFinished.connect(self.getFields)
self.form.cboOutputPolicy.currentIndexChanged.connect(self.getFields)
self.form.leLabel.editingFinished.connect(self.getFields)
self.form.btnSelectFile.clicked.connect(self.setFile)
self.form.PathsList.indexesMoved.connect(self.getFields)

View File

@@ -42,6 +42,85 @@ except AttributeError:
class CommandPathPost:
DefaultOutputFile = "DefaultOutputFile"
DefaultOutputPolicy = "DefaultOutputPolicy"
@classmethod
def saveDefaults(cls, path, policy):
preferences = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
preferences.SetString(cls.DefaultOutputFile, path)
preferences.SetString(cls.DefaultOutputPolicy, policy)
@classmethod
def defaultOutputFile(cls):
preferences = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
return preferences.GetString(cls.DefaultOutputFile, "")
@classmethod
def defaultOutputPolicy(cls):
preferences = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
return preferences.GetString(cls.DefaultOutputPolicy, "")
def resolveFileName(self, job):
path = "tmp.tap"
if job.OutputFile:
path = job.OutputFile
filename = path
if '%D' in filename:
D = FreeCAD.ActiveDocument.FileName
if D:
D = os.path.dirname(D)
else:
FreeCAD.Console.PrintError("Please save document in order to resolve output path!\n")
return None
filename = filename.replace('%D', D)
if '%d' in filename:
d = FreeCAD.ActiveDocument.Label
filename = filename.replace('%d', d)
if '%j' in filename:
j = job.Label
filename = filename.replace('%j', j)
if '%M' in filename:
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")
M = pref.GetString("MacroPath", FreeCAD.getUserAppDataDir())
filename = filename.replace('%M', M)
policy = job.OutputPolicy
if not policy or policy == 'Use default':
policy = self.defaultOutputPolicy()
openDialog = policy == 'Open File Dialog'
if os.path.isdir(filename) or not os.path.isdir(os.path.dirname(filename)):
# Either the entire filename resolves into a directory or the parent directory doesn't exist.
# Either way I don't know what to do - ask for help
openDialog = True
if os.path.isfile(filename) and not openDialog:
if policy == 'Open File Dialog on conflict':
openDialog = True
elif policy == 'Append Unique ID on conflict':
fn, ext = os.path.splitext(filename)
nr = fn[-3:]
n = 1
if nr.isdigit():
n = int(nr)
while os.path.isfile("%s%03d%s" % (fn, n, ext)):
n = n + 1
filename = "%s%03d%s" % (fn, n, ext)
if openDialog:
foo = QtGui.QFileDialog.getSaveFileName(QtGui.qApp.activeWindow(), "Output File", filename)
if foo:
filename = foo[0]
else:
filename = None
#print("resolveFileName(%s, %s) -> '%s'" % (path, policy, filename))
return filename
def GetResources(self):
return {'Pixmap': 'Path-Post',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Post", "Post Process"),
@@ -64,7 +143,6 @@ class CommandPathPost:
# default to the dumper post and default .tap file
postname = "dumper"
filename = "tmp.tap"
postArgs = ""
print "in activated %s" %(obj)
@@ -73,7 +151,7 @@ class CommandPathPost:
# output filename
if hasattr(obj[0], "Group") and hasattr(obj[0], "Path"):
# # Check for a selected post post processor if it's set
proj = obj[0]
job = obj[0]
if hasattr(obj[0], "PostProcessor"):
postobj = obj[0]
@@ -85,15 +163,17 @@ class CommandPathPost:
lessextn = os.path.splitext(postobj.PostProcessor)[0]
postname = os.path.split(lessextn)[1]
if proj.OutputFile:
filename = proj.OutputFile
if hasattr(postobj, "PostProcessorArgs"):
postArgs = postobj.PostProcessorArgs
processor = PostProcessor.load(postname)
processor.export(obj, filename, postArgs)
filename = self.resolveFileName(job)
if filename:
processor = PostProcessor.load(postname)
processor.export(obj, filename, postArgs)
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.commitTransaction()
else:
FreeCAD.ActiveDocument.abortTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:

View File

@@ -26,6 +26,7 @@ import FreeCAD
import FreeCADGui
from PySide import QtCore, QtGui
from PathScripts.PathPostProcessor import PostProcessor
from PathScripts.PathPost import CommandPathPost as PathPost
class Page:
@@ -46,6 +47,17 @@ class Page:
blacklist.append(item.text())
PostProcessor.saveDefaults(processor, args, blacklist)
path = str(self.form.leOutputFile.text())
policy = str(self.form.cboOutputPolicy.currentText())
PathPost.saveDefaults(path, policy)
def selectComboEntry(self, widget, text):
index = widget.findText(text, QtCore.Qt.MatchFixedString)
if index >= 0:
widget.blockSignals(True)
widget.setCurrentIndex(index)
widget.blockSignals(False)
def loadSettings(self):
self.form.defaultPostProcessor.addItem("")
blacklist = PostProcessor.blacklist()
@@ -58,18 +70,15 @@ class Page:
item.setCheckState(QtCore.Qt.CheckState.Checked)
item.setFlags( QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsUserCheckable)
self.form.postProcessorList.addItem(item)
postindex = self.form.defaultPostProcessor.findText(PostProcessor.default(), QtCore.Qt.MatchFixedString)
if postindex >= 0:
self.form.defaultPostProcessor.blockSignals(True)
self.form.defaultPostProcessor.setCurrentIndex(postindex)
self.form.defaultPostProcessor.blockSignals(False)
self.selectComboEntry(self.form.defaultPostProcessor, PostProcessor.default())
self.form.defaultPostProcessorArgs.setText(PostProcessor.defaultArgs())
self.form.leOutputFile.setText(PathPost.defaultOutputFile())
self.selectComboEntry(self.form.cboOutputPolicy, PathPost.defaultOutputPolicy())
self.form.postProcessorList.itemEntered.connect(self.setProcessorListTooltip)
self.form.defaultPostProcessor.currentIndexChanged.connect(self.updateDefaultPostProcessorToolTip)
self.form.browseFileSystem.clicked.connect(self.browseFileSystem)
def getPostProcessor(self, name):
if not name in self.processor.keys():
@@ -100,3 +109,8 @@ class Page:
else:
self.form.defaultPostProcessor.setToolTip(self.postProcessorDefaultTooltip)
self.form.defaultPostProcessorArgs.setToolTip(self.postProcessorArgsDefaultTooltip)
def browseFileSystem(self):
foo = QtGui.QFileDialog.getExistingDirectory(QtGui.qApp.activeWindow(), "Path - Output File/Directory", self.form.defaultOutputPath.text())
if foo:
self.form.defaultOutputPath.setText(foo)