diff --git a/src/Mod/Draft/draftguitools/gui_lines.py b/src/Mod/Draft/draftguitools/gui_lines.py
index d297d34ac8..eba740fb45 100644
--- a/src/Mod/Draft/draftguitools/gui_lines.py
+++ b/src/Mod/Draft/draftguitools/gui_lines.py
@@ -122,9 +122,13 @@ class Line(gui_base_original.Creator):
if not self.isWire and len(self.node) == 2:
self.finish(False, cont=True)
if len(self.node) > 2:
+ # The wire is closed
if (self.point - self.node[0]).Length < utils.tolerance():
self.undolast()
- self.finish(True, cont=True)
+ if len(self.node) > 2:
+ self.finish(True, cont=True)
+ else:
+ self.finish(False, cont=True)
def finish(self, closed=False, cont=False):
"""Terminate the operation and close the polyline if asked.
diff --git a/src/Mod/Path/Gui/Resources/panels/PathEdit.ui b/src/Mod/Path/Gui/Resources/panels/PathEdit.ui
index d71044c96f..44d768ff13 100644
--- a/src/Mod/Path/Gui/Resources/panels/PathEdit.ui
+++ b/src/Mod/Path/Gui/Resources/panels/PathEdit.ui
@@ -31,8 +31,8 @@
0
0
- 549
- 628
+ 146
+ 378
@@ -112,8 +112,8 @@
0
0
- 98
- 28
+ 96
+ 26
@@ -281,7 +281,7 @@
G54
- Checked
+ Unchecked
-
@@ -431,8 +431,8 @@
0
0
- 536
- 1291
+ 545
+ 896
@@ -1002,8 +1002,8 @@
0
0
- 419
- 548
+ 213
+ 321
@@ -1096,7 +1096,7 @@
-
-
+
<html><head/><body><p>ClearanceHeightOffset - can be used by expressions to set the default ClearanceHeight for new operations.</p><p><br/></p><p>Default: "3 mm"</p></body></html>
@@ -1123,7 +1123,7 @@
-
-
+
<html><head/><body><p>SafeHeightOffset can be for expressions to set the SafeHeight for new operations.</p><p><br/></p><p>Default: "5 mm"</p></body></html>
@@ -1185,8 +1185,8 @@
0
0
- 549
- 628
+ 317
+ 173
@@ -1285,8 +1285,8 @@
0
0
- 208
- 160
+ 138
+ 112
@@ -1310,7 +1310,7 @@
-
-
+
0
@@ -1330,7 +1330,7 @@
-
-
+
0
diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/PathScripts/PathJob.py
index a6c027b722..8ddf574c13 100644
--- a/src/Mod/Path/PathScripts/PathJob.py
+++ b/src/Mod/Path/PathScripts/PathJob.py
@@ -56,6 +56,9 @@ class JobTemplate:
PostProcessor = 'Post'
PostProcessorArgs = 'PostArgs'
PostProcessorOutputFile = 'Output'
+ Fixtures = 'Fixtures'
+ OrderOutputBy = 'OrderOutputBy'
+ SplitOutput = 'SplitOutput'
SetupSheet = 'SetupSheet'
Stock = 'Stock'
# TCs are grouped under Tools in a job, the template refers to them directly though
@@ -121,7 +124,6 @@ class ObjectJob:
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.addProperty("App::PropertyBool", "SplitOutput", "Output", QtCore.QT_TRANSLATE_NOOP("PathJob", "Split output into multiple gcode files"))
obj.addProperty("App::PropertyEnumeration", "OrderOutputBy", "WCS", QtCore.QT_TRANSLATE_NOOP("PathJob", "If multiple WCS, order the output this way"))
@@ -350,6 +352,15 @@ class ObjectJob:
if attrs.get(JobTemplate.Stock):
obj.Stock = PathStock.CreateFromTemplate(obj, attrs.get(JobTemplate.Stock))
+ if attrs.get(JobTemplate.Fixtures):
+ obj.Fixtures = [x for y in attrs.get(JobTemplate.Fixtures) for x in y]
+
+ if attrs.get(JobTemplate.OrderOutputBy):
+ obj.OrderOutputBy = attrs.get(JobTemplate.OrderOutputBy)
+
+ if attrs.get(JobTemplate.SplitOutput):
+ obj.SplitOutput = attrs.get(JobTemplate.SplitOutput)
+
PathLog.debug("setting tool controllers (%d)" % len(tcs))
obj.Tools.Group = tcs
else:
@@ -364,6 +375,9 @@ class ObjectJob:
if obj.PostProcessor:
attrs[JobTemplate.PostProcessor] = obj.PostProcessor
attrs[JobTemplate.PostProcessorArgs] = obj.PostProcessorArgs
+ attrs[JobTemplate.Fixtures] = [{f: True} for f in obj.Fixtures]
+ attrs[JobTemplate.OrderOutputBy] = obj.OrderOutputBy
+ attrs[JobTemplate.SplitOutput] = obj.SplitOutput
if obj.PostProcessorOutputFile:
attrs[JobTemplate.PostProcessorOutputFile] = obj.PostProcessorOutputFile
attrs[JobTemplate.GeometryTolerance] = str(obj.GeometryTolerance.Value)
diff --git a/src/Mod/Path/PathScripts/PathSetupSheet.py b/src/Mod/Path/PathScripts/PathSetupSheet.py
index 87203d6a95..9cdfb0596c 100644
--- a/src/Mod/Path/PathScripts/PathSetupSheet.py
+++ b/src/Mod/Path/PathScripts/PathSetupSheet.py
@@ -34,7 +34,7 @@ __doc__ = "A container for all default values and job specific configuration val
_RegisteredOps = {}
-PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
+PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
# PathLog.trackModule(PathLog.thisModule())
@@ -55,11 +55,15 @@ class Template:
StartDepthExpression = 'StartDepthExpression'
FinalDepthExpression = 'FinalDepthExpression'
StepDownExpression = 'StepDownExpression'
+ Fixtures = 'Fixtures'
+ OrderOutputBy = 'OrderOutputBy'
+ SplitOutput = 'SplitOutput'
All = [HorizRapid, VertRapid, CoolantMode, SafeHeightOffset, SafeHeightExpression, ClearanceHeightOffset, ClearanceHeightExpression, StartDepthExpression, FinalDepthExpression, StepDownExpression]
def _traverseTemplateAttributes(attrs, codec):
+ PathLog.debug(attrs)
coded = {}
for key, value in PathUtil.keyValueIter(attrs):
if type(value) == dict:
diff --git a/src/Mod/Path/PathScripts/PathSetupSheetGui.py b/src/Mod/Path/PathScripts/PathSetupSheetGui.py
index 7b06816ed7..d2ceb3956b 100644
--- a/src/Mod/Path/PathScripts/PathSetupSheetGui.py
+++ b/src/Mod/Path/PathScripts/PathSetupSheetGui.py
@@ -26,7 +26,6 @@ import PathScripts.PathGui as PathGui
import PathScripts.PathIconViewProvider as PathIconViewProvider
import PathScripts.PathLog as PathLog
import PathScripts.PathSetupSheet as PathSetupSheet
-# import PathScripts.PathSetupSheetOpPrototype as PathSetupSheetOpPrototype
import PathScripts.PathSetupSheetOpPrototypeGui as PathSetupSheetOpPrototypeGui
import PathScripts.PathUtil as PathUtil
@@ -37,18 +36,22 @@ __author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Task panel editor for a SetupSheet"
+
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
+
LOGLEVEL = False
+
if LOGLEVEL:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
+
class ViewProvider:
'''ViewProvider for a SetupSheet.
It's sole job is to provide an icon and invoke the TaskPanel on edit.'''
@@ -100,14 +103,11 @@ class ViewProvider:
def doubleClicked(self, vobj):
self.setEdit(vobj)
+
class Delegate(QtGui.QStyledItemDelegate):
PropertyRole = QtCore.Qt.UserRole + 1
EditorRole = QtCore.Qt.UserRole + 2
-
- #def paint(self, painter, option, index):
- # #PathLog.track(index.column(), type(option))
-
def createEditor(self, parent, option, index):
# pylint: disable=unused-argument
if index.data(self.EditorRole) is None:
@@ -130,6 +130,7 @@ class Delegate(QtGui.QStyledItemDelegate):
# pylint: disable=unused-argument
widget.setGeometry(option.rect)
+
class OpTaskPanel:
'''Editor for an operation's property default values.
The implementation is a simplified generic property editor with basically 3 fields
@@ -168,16 +169,16 @@ class OpTaskPanel:
self.model = QtGui.QStandardItemModel(len(self.props), 3, self.form)
self.model.setHorizontalHeaderLabels(['Set', 'Property', 'Value'])
- for i,name in enumerate(self.props):
+ for i, name in enumerate(self.props):
prop = self.prototype.getProperty(name)
isset = hasattr(self.obj, self.propertyName(name))
if isset:
prop.setValue(getattr(self.obj, self.propertyName(name)))
self.model.setData(self.model.index(i, 0), isset, QtCore.Qt.EditRole)
- self.model.setData(self.model.index(i, 1), name, QtCore.Qt.EditRole)
- self.model.setData(self.model.index(i, 2), prop, Delegate.PropertyRole)
- self.model.setData(self.model.index(i, 2), prop.displayString(), QtCore.Qt.DisplayRole)
+ self.model.setData(self.model.index(i, 1), name, QtCore.Qt.EditRole)
+ self.model.setData(self.model.index(i, 2), prop, Delegate.PropertyRole)
+ self.model.setData(self.model.index(i, 2), prop.displayString(), QtCore.Qt.DisplayRole)
self.model.item(i, 0).setCheckable(True)
self.model.item(i, 0).setText('')
@@ -206,7 +207,7 @@ class OpTaskPanel:
def accept(self):
propertiesCreatedRemoved = False
- for i,name in enumerate(self.props):
+ for i, name in enumerate(self.props):
prop = self.prototype.getProperty(name)
propName = self.propertyName(name)
enabled = self.model.item(i, 0).checkState() == QtCore.Qt.Checked
@@ -229,7 +230,7 @@ class OpsDefaultEditor:
def __init__(self, obj, form):
self.form = form
self.obj = obj
- self.ops = sorted([OpTaskPanel(self.obj, name, op) for name, op in PathUtil.keyValueIter(PathSetupSheet._RegisteredOps)], key = lambda op: op.name) # pylint: disable=protected-access
+ self.ops = sorted([OpTaskPanel(self.obj, name, op) for name, op in PathUtil.keyValueIter(PathSetupSheet._RegisteredOps)], key=lambda op: op.name)
if form:
parent = form.tabOpDefaults
for op in self.ops:
@@ -245,10 +246,6 @@ class OpsDefaultEditor:
def accept(self):
if any([op.accept() for op in self.ops]):
PathLog.track()
- #sel = FreeCADGui.Selection.getSelection()
- #FreeCADGui.Selection.clearSelection()
- #for o in sel:
- # FreeCADGui.Selection.addSelection(o)
def getFields(self):
pass
@@ -264,7 +261,7 @@ class OpsDefaultEditor:
self.currentOp = self.form.opDefaultOp.itemData(current)
self.currentOp.form.show()
- def updateModel(self, recomp = True):
+ def updateModel(self, recomp=True):
PathLog.track()
self.getFields()
self.updateUI()
@@ -281,6 +278,7 @@ class OpsDefaultEditor:
if self.form:
self.form.opDefaultOp.currentIndexChanged.connect(self.updateUI)
+
class GlobalEditor(object):
'''Editor for the global properties which affect almost every operation.'''
@@ -293,7 +291,6 @@ class GlobalEditor(object):
self.safeHeightOffs = None
self.rapidHorizontal = None
self.rapidVertical = None
- #self.coolantMode = None
def reject(self):
pass
@@ -308,16 +305,15 @@ class GlobalEditor(object):
if val != value:
PathUtil.setProperty(self.obj, name, value)
- updateExpression('StartDepthExpression', self.form.setupStartDepthExpr)
- updateExpression('FinalDepthExpression', self.form.setupFinalDepthExpr)
- updateExpression('StepDownExpression', self.form.setupStepDownExpr)
- updateExpression('ClearanceHeightExpression', self.form.setupClearanceHeightExpr)
- updateExpression('SafeHeightExpression', self.form.setupSafeHeightExpr)
+ updateExpression('StartDepthExpression', self.form.setupStartDepthExpr)
+ updateExpression('FinalDepthExpression', self.form.setupFinalDepthExpr)
+ updateExpression('StepDownExpression', self.form.setupStepDownExpr)
+ updateExpression('ClearanceHeightExpression', self.form.setupClearanceHeightExpr)
+ updateExpression('SafeHeightExpression', self.form.setupSafeHeightExpr)
self.clearanceHeightOffs.updateProperty()
self.safeHeightOffs.updateProperty()
self.rapidVertical.updateProperty()
self.rapidHorizontal.updateProperty()
- #self.coolantMode.updateProperty()
self.obj.CoolantMode = self.form.setupCoolantMode.currentText()
def selectInComboBox(self, name, combo):
@@ -330,18 +326,18 @@ class GlobalEditor(object):
def updateUI(self):
PathLog.track()
- self.form.setupStartDepthExpr.setText( self.obj.StartDepthExpression)
- self.form.setupFinalDepthExpr.setText( self.obj.FinalDepthExpression)
- self.form.setupStepDownExpr.setText( self.obj.StepDownExpression)
- self.form.setupClearanceHeightExpr.setText( self.obj.ClearanceHeightExpression)
- self.form.setupSafeHeightExpr.setText( self.obj.SafeHeightExpression)
+ self.form.setupStartDepthExpr.setText(self.obj.StartDepthExpression)
+ self.form.setupFinalDepthExpr.setText(self.obj.FinalDepthExpression)
+ self.form.setupStepDownExpr.setText(self.obj.StepDownExpression)
+ self.form.setupClearanceHeightExpr.setText(self.obj.ClearanceHeightExpression)
+ self.form.setupSafeHeightExpr.setText(self.obj.SafeHeightExpression)
self.clearanceHeightOffs.updateSpinBox()
self.safeHeightOffs.updateSpinBox()
self.rapidVertical.updateSpinBox()
self.rapidHorizontal.updateSpinBox()
self.selectInComboBox(self.obj.CoolantMode, self.form.setupCoolantMode)
- def updateModel(self, recomp = True):
+ def updateModel(self, recomp=True):
PathLog.track()
self.getFields()
self.updateUI()
@@ -359,6 +355,7 @@ class GlobalEditor(object):
self.form.setupCoolantMode.addItems(self.obj.CoolantModes)
self.setFields()
+
class TaskPanel:
'''TaskPanel for the SetupSheet - if it is being edited directly.'''
@@ -387,8 +384,6 @@ class TaskPanel:
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
- #FreeCADGui.Selection.removeObserver(self.s)
- #FreeCAD.ActiveDocument.recompute()
def getFields(self):
self.globalEditor.getFields()
@@ -411,11 +406,13 @@ class TaskPanel:
self.globalEditor.setupUi()
self.opsEditor.setupUi()
-def Create(name = 'SetupSheet'):
- '''Create(name = 'SetupSheet') ... creates a new setup sheet'''
+
+def Create(name='SetupSheet'):
+ '''Create(name='SetupSheet') ... creates a new setup sheet'''
FreeCAD.ActiveDocument.openTransaction(translate("Path_Job", "Create Job"))
ssheet = PathSetupSheet.Create(name)
PathIconViewProvider.Attach(ssheet, name)
return ssheet
+
PathIconViewProvider.RegisterViewProvider('SetupSheet', ViewProvider)