diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt
index 5ade432462..098221bdb7 100644
--- a/src/Mod/Path/CMakeLists.txt
+++ b/src/Mod/Path/CMakeLists.txt
@@ -42,6 +42,7 @@ SET(PathScripts_SRCS
PathScripts/PathFaceProfile.py
PathScripts/PathFixture.py
PathScripts/PathGeom.py
+ PathScripts/PathGetPoint.py
PathScripts/PathHelix.py
PathScripts/PathHelixGui.py
PathScripts/PathHop.py
diff --git a/src/Mod/Path/Gui/Resources/Path.qrc b/src/Mod/Path/Gui/Resources/Path.qrc
index 7eb284ddde..d620a393d1 100644
--- a/src/Mod/Path/Gui/Resources/Path.qrc
+++ b/src/Mod/Path/Gui/Resources/Path.qrc
@@ -60,6 +60,7 @@
panels/JobEdit.ui
panels/PageBaseGeometryEdit.ui
panels/PageBaseHoleGeometryEdit.ui
+ panels/PageBaseLocationEdit.ui
panels/PageDepthsEdit.ui
panels/PageHeightsEdit.ui
panels/PageOpDrillingEdit.ui
diff --git a/src/Mod/Path/Gui/Resources/panels/PageBaseLocationEdit.ui b/src/Mod/Path/Gui/Resources/panels/PageBaseLocationEdit.ui
new file mode 100644
index 0000000000..913c251ec3
--- /dev/null
+++ b/src/Mod/Path/Gui/Resources/panels/PageBaseLocationEdit.ui
@@ -0,0 +1,94 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 415
+ 573
+
+
+
+ Form
+
+
+ -
+
+
-
+
+
+ <html><head/><body><p>List of locations to be processed.</p></body></html>
+
+
+ true
+
+
+
+ X
+
+
+
+
+ Y
+
+
+
+
+ -
+
+
+ <html><head/><body><p>Edit selected location.</p></body></html>
+
+
+ Edit
+
+
+
+ -
+
+
+ All locations will be processed using the same operation properties.
+
+
+ Qt::AutoText
+
+
+ true
+
+
+
+ -
+
+
+ <html><head/><body><p>Remove selected location from the list. The operation is no longer applied to them.</p></body></html>
+
+
+ Remove
+
+
+
+ -
+
+
+ <html><head/><body><p>Opens a newe dialog that lets you add arbitrary locations.</p></body></html>
+
+
+ Add
+
+
+
+
+
+
+
+
+ baseList
+ addLocation
+ removeLocation
+ editLocation
+
+
+
+
diff --git a/src/Mod/Path/PathScripts/PathCircularHoleBase.py b/src/Mod/Path/PathScripts/PathCircularHoleBase.py
index d47f8b8af8..988167c95b 100644
--- a/src/Mod/Path/PathScripts/PathCircularHoleBase.py
+++ b/src/Mod/Path/PathScripts/PathCircularHoleBase.py
@@ -104,7 +104,7 @@ class ObjectOp(PathOp.ObjectOp):
def opExecute(self, obj):
PathLog.track()
- if len(obj.Base) == 0:
+ if len(obj.Base) == 0 and len(obj.Locations) == 0:
# Arch PanelSheet
features = []
if self.baseIsArchPanel(obj, self.baseobject):
@@ -133,6 +133,8 @@ class ObjectOp(PathOp.ObjectOp):
if self.isHoleEnabled(obj, base, sub):
pos = self.holePosition(obj, base, sub)
holes.append({'x': pos.x, 'y': pos.y, 'r': self.holeDiameter(obj, base, sub)})
+ for location in obj.Locations:
+ holes.append({'x': location.x, 'y': location.y, 'r': 0})
if len(holes) > 0:
self.circularHoleExecute(obj, holes)
@@ -168,9 +170,9 @@ class ObjectOp(PathOp.ObjectOp):
def setDepths(self, obj, zmax, zmin, bb):
PathLog.track(obj.Label, zmax, zmin, bb)
if zmax is None:
- zmax = 5
+ zmax = bb.ZMax
if zmin is None:
- zmin = 0
+ zmin = bb.ZMin
if zmin > zmax:
zmax = zmin
diff --git a/src/Mod/Path/PathScripts/PathDrilling.py b/src/Mod/Path/PathScripts/PathDrilling.py
index 77a0fc4dbf..1a98c92d80 100644
--- a/src/Mod/Path/PathScripts/PathDrilling.py
+++ b/src/Mod/Path/PathScripts/PathDrilling.py
@@ -52,7 +52,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
def circularHoleFeatures(self, obj):
# drilling works on anything
- return PathOp.FeatureBaseGeometry
+ return PathOp.FeatureBaseGeometry | PathOp.FeatureLocations
def initCircularHoleOperation(self, obj):
@@ -71,6 +71,9 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
self.commandlist.append(Path.Command("(Begin Drilling)"))
+ # rapid to clearance height
+ self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))
+
tiplength = 0.0
if obj.AddTipLength:
tiplength = PathUtils.drillTipLength(self.tool)
@@ -78,14 +81,13 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
holes = PathUtils.sort_jobs(holes, ['x', 'y'])
self.commandlist.append(Path.Command('G90'))
self.commandlist.append(Path.Command(obj.ReturnLevel))
- # rapid to clearance height
- self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))
- # rapid to first hole location, with spindle still retracted:
- p0 = holes[0]
- self.commandlist.append(Path.Command('G0', {'X': p0['x'], 'Y': p0['y'], 'F': self.horizRapid}))
- # move tool to clearance plane
- self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))
+ # ml: I'm not sure whey these were here, they seem redundant
+ ## rapid to first hole location, with spindle still retracted:
+ #p0 = holes[0]
+ #self.commandlist.append(Path.Command('G0', {'X': p0['x'], 'Y': p0['y'], 'F': self.horizRapid}))
+ ## move tool to clearance plane
+ #self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))
cmd = "G81"
cmdParams = {}
@@ -118,6 +120,14 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
def opSetDefaultValues(self, obj):
obj.RetractHeight = 10
+ def opOnChanged(self, obj, prop):
+ super(self.__class__, self).opOnChanged(obj, prop)
+ if prop == 'Locations' and not 'Restore' in obj.State and obj.Locations and not obj.Base:
+ if not hasattr(self, 'baseobject'):
+ job = PathUtils.findParentJob(obj)
+ if job and job.Base:
+ self.setupDepthsFrom(obj, [], job.Base)
+
def Create(name):
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
proxy = ObjectDrilling(obj)
diff --git a/src/Mod/Path/PathScripts/PathGetPoint.py b/src/Mod/Path/PathScripts/PathGetPoint.py
new file mode 100644
index 0000000000..91e1dadf9f
--- /dev/null
+++ b/src/Mod/Path/PathScripts/PathGetPoint.py
@@ -0,0 +1,158 @@
+# -*- 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 Draft
+import FreeCAD
+import FreeCADGui
+
+from PySide import QtCore, QtGui
+from pivy import coin
+
+class TaskPanel:
+
+ def __init__(self, formOrig, formPoint):
+ self.formOrig = formOrig
+ self.formPoint = formPoint
+
+ self.setupUi()
+ self.buttonBox = None
+
+ def setupUi(self):
+ self.formPoint.buttonBox.accepted.connect(self.pointAccept)
+ self.formPoint.buttonBox.rejected.connect(self.pointReject)
+
+ self.formPoint.ifValueX.editingFinished.connect(self.updatePoint)
+ self.formPoint.ifValueY.editingFinished.connect(self.updatePoint)
+ self.formPoint.ifValueZ.editingFinished.connect(self.updatePoint)
+
+ def addEscapeShortcut(self):
+ # The only way I could get to intercept the escape key, or really any key was
+ # by creating an action with a shortcut .....
+ self.escape = QtGui.QAction(self.formPoint)
+ self.escape.setText('Done')
+ self.escape.setShortcut(QtGui.QKeySequence.fromString('Esc'))
+ QtCore.QObject.connect(self.escape, QtCore.SIGNAL('triggered()'), self.pointDone)
+ self.formPoint.addAction(self.escape)
+
+ def removeEscapeShortcut(self):
+ if self.escape:
+ self.formPoint.removeAction(self.escape)
+ self.escape = None
+
+ def getPoint(self, whenDone, start=None):
+
+ def displayPoint(p):
+ self.formPoint.ifValueX.setText(FreeCAD.Units.Quantity(p.x, FreeCAD.Units.Length).UserString)
+ self.formPoint.ifValueY.setText(FreeCAD.Units.Quantity(p.y, FreeCAD.Units.Length).UserString)
+ self.formPoint.ifValueZ.setText(FreeCAD.Units.Quantity(p.z, FreeCAD.Units.Length).UserString)
+ self.formPoint.ifValueX.setFocus()
+ self.formPoint.ifValueX.selectAll()
+
+ def mouseMove(cb):
+ event = cb.getEvent()
+ pos = event.getPosition()
+ cntrl = event.wasCtrlDown()
+ shift = event.wasShiftDown()
+ self.pt = FreeCADGui.Snapper.snap(pos, lastpoint=start, active=cntrl, constrain=shift)
+ plane = FreeCAD.DraftWorkingPlane
+ p = plane.getLocalCoords(self.pt)
+ displayPoint(p)
+
+ def click(cb):
+ event = cb.getEvent()
+ if event.getButton() == 1 and event.getState() == coin.SoMouseButtonEvent.DOWN:
+ accept()
+
+ def accept():
+ if start:
+ self.pointAccept()
+ else:
+ self.pointAcceptAndContinue()
+
+ def cancel():
+ self.pointCancel()
+
+ self.pointWhenDone = whenDone
+ self.formOrig.hide()
+ self.formPoint.show()
+ self.addEscapeShortcut()
+ if start:
+ displayPoint(start)
+ else:
+ displayPoint(FreeCAD.Vector(0, 0, 0))
+
+ self.view = Draft.get3DView()
+ self.pointCbClick = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), click)
+ self.pointCbMove = self.view.addEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), mouseMove)
+
+ if self.buttonBox:
+ self.buttonBox.setEnabled(False)
+ FreeCADGui.Snapper.forceGridOff=True
+
+ def pointFinish(self, ok, cleanup = True):
+ obj = FreeCADGui.Snapper.lastSnappedObject
+
+ if cleanup:
+ self.removeGlobalCallbacks()
+ FreeCADGui.Snapper.off()
+ if self.buttonBox:
+ self.buttonBox.setEnabled(True)
+ self.removeEscapeShortcut()
+ self.formPoint.hide()
+ self.formOrig.show()
+ self.formOrig.setFocus()
+
+ if ok:
+ self.pointWhenDone(self.pt, obj)
+ else:
+ self.pointWhenDone(None, None)
+
+ def pointDone(self):
+ self.pointFinish(False)
+
+ def pointReject(self):
+ self.pointFinish(False)
+
+ def pointAccept(self):
+ self.pointFinish(True)
+
+ def pointAcceptAndContinue(self):
+ self.pointFinish(True, False)
+
+ def removeGlobalCallbacks(self):
+ if hasattr(self, 'view') and self.view:
+ if self.pointCbClick:
+ self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.pointCbClick)
+ self.pointCbClick = None
+ if self.pointCbMove:
+ self.view.removeEventCallbackPivy(coin.SoLocation2Event.getClassTypeId(), self.pointCbMove)
+ self.pointCbMove = None
+ self.view = None
+
+ def updatePoint(self):
+ x = FreeCAD.Units.Quantity(self.formPoint.ifValueX.text()).Value
+ y = FreeCAD.Units.Quantity(self.formPoint.ifValueY.text()).Value
+ z = FreeCAD.Units.Quantity(self.formPoint.ifValueZ.text()).Value
+ self.pt = FreeCAD.Vector(x, y, z)
+
diff --git a/src/Mod/Path/PathScripts/PathOp.py b/src/Mod/Path/PathScripts/PathOp.py
index 1bf9151259..db293e659b 100644
--- a/src/Mod/Path/PathScripts/PathOp.py
+++ b/src/Mod/Path/PathScripts/PathOp.py
@@ -50,10 +50,11 @@ FeatureHeights = 0x0004
FeatureStartPoint = 0x0008
FeatureFinishDepth = 0x0010
FeatureStepDown = 0x0020
-FeatureBaseVertexes = 0x1000
-FeatureBaseEdges = 0x2000
-FeatureBaseFaces = 0x4000
-FeatureBasePanels = 0x8000
+FeatureBaseVertexes = 0x0100
+FeatureBaseEdges = 0x0200
+FeatureBaseFaces = 0x0400
+FeatureBasePanels = 0x0800
+FeatureLocations = 0x1000
FeatureBaseGeometry = FeatureBaseVertexes | FeatureBaseFaces | FeatureBaseEdges | FeatureBasePanels
@@ -66,27 +67,32 @@ class ObjectOp(object):
obj.addProperty("App::PropertyString", "Comment", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "An optional comment for this Operation"))
obj.addProperty("App::PropertyString", "UserLabel", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "User Assigned Label"))
- if FeatureBaseGeometry & self.opFeatures(obj):
+ features = self.opFeatures(obj)
+
+ if FeatureBaseGeometry & features:
obj.addProperty("App::PropertyLinkSubList", "Base", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The base geometry for this operation"))
- if FeatureTool & self.opFeatures(obj):
+ if FeatureLocations & features:
+ obj.addProperty("App::PropertyVectorList", "Locations", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "Base locations for this operation"))
+
+ if FeatureTool & features:
obj.addProperty("App::PropertyLink", "ToolController", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The tool controller that will be used to calculate the path"))
- if FeatureDepths & self.opFeatures(obj):
+ if FeatureDepths & features:
obj.addProperty("App::PropertyDistance", "StartDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Starting Depth of Tool- first cut depth in Z"))
obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Final Depth of Tool- lowest value in Z"))
- if FeatureStepDown & self.opFeatures(obj):
+ if FeatureStepDown & features:
obj.addProperty("App::PropertyDistance", "StepDown", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Incremental Step Down of Tool"))
- if FeatureFinishDepth & self.opFeatures(obj):
+ if FeatureFinishDepth & features:
obj.addProperty("App::PropertyDistance", "FinishDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Maximum material removed on final pass."))
- if FeatureHeights & self.opFeatures(obj):
+ if FeatureHeights & features:
obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "The height needed to clear clamps and obstructions"))
obj.addProperty("App::PropertyDistance", "SafeHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Rapid Safety Height between locations."))
- if FeatureStartPoint & self.opFeatures(obj):
+ if FeatureStartPoint & features:
obj.addProperty("App::PropertyVector", "StartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "The start point of this path"))
obj.addProperty("App::PropertyBool", "UseStartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if specifying a Start Point"))
@@ -116,21 +122,23 @@ class ObjectOp(object):
obj.Active = True
- if FeatureTool & self.opFeatures(obj):
+ features = self.opFeatures(obj)
+
+ if FeatureTool & features:
obj.ToolController = PathUtils.findToolController(obj)
- if FeatureDepths & self.opFeatures(obj):
+ if FeatureDepths & features:
obj.StartDepth = 1.0
obj.FinalDepth = 0.0
- if FeatureStepDown & self.opFeatures(obj):
+ if FeatureStepDown & features:
obj.StepDown = 1.0
- if FeatureHeights & self.opFeatures(obj):
+ if FeatureHeights & features:
obj.ClearanceHeight = 10.0
obj.SafeHeight = 8.0
- if FeatureStartPoint & self.opFeatures(obj):
+ if FeatureStartPoint & features:
obj.UseStartPoint = False
self.opSetDefaultValues(obj)
diff --git a/src/Mod/Path/PathScripts/PathOpGui.py b/src/Mod/Path/PathScripts/PathOpGui.py
index 30cac5acf9..cacf200214 100644
--- a/src/Mod/Path/PathScripts/PathOpGui.py
+++ b/src/Mod/Path/PathScripts/PathOpGui.py
@@ -24,6 +24,7 @@
import FreeCAD
import FreeCADGui
+import PathScripts.PathGetPoint as PathGetPoint
import PathScripts.PathLog as PathLog
import PathScripts.PathSelection as PathSelection
import PathScripts.PathOp as PathOp
@@ -157,6 +158,8 @@ class TaskPanelPage(object):
# subclass interface
def initPage(self, obj):
pass
+ def modifyStandardButtons(self, buttonBox):
+ pass
def getForm(self):
pass
def getFields(self, obj):
@@ -316,6 +319,108 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
self.setFields(obj)
+class TaskPanelBaseLocationPage(TaskPanelPage):
+
+ DataLocation = QtCore.Qt.ItemDataRole.UserRole
+
+ def getForm(self):
+ self.formLoc = FreeCADGui.PySideUic.loadUi(":/panels/PageBaseLocationEdit.ui")
+ self.formPts = FreeCADGui.PySideUic.loadUi(":/panels/PointEdit.ui")
+ form = QtGui.QWidget()
+ self.layout = QtGui.QVBoxLayout(form)
+ form.setWindowTitle(self.formLoc.windowTitle())
+ form.setSizePolicy(self.formLoc.sizePolicy())
+ self.formLoc.setParent(form)
+ self.formPts.setParent(form)
+ self.layout.addWidget(self.formLoc)
+ self.layout.addWidget(self.formPts)
+ self.formPts.hide()
+ self.getPoint = PathGetPoint.TaskPanel(self.formLoc, self.formPts)
+ return form
+
+ def modifyStandardButtons(self, buttonBox):
+ self.getPoint.buttonBox = buttonBox
+
+ def getTitle(self, obj):
+ return translate("PathOp", "Base Location")
+ def getFields(self, obj):
+ pass
+
+ def setFields(self, obj):
+ self.formLoc.baseList.blockSignals(True)
+ self.formLoc.baseList.clearContents()
+ self.formLoc.baseList.setRowCount(0)
+ for location in self.obj.Locations:
+ self.formLoc.baseList.insertRow(self.formLoc.baseList.rowCount())
+
+ item = QtGui.QTableWidgetItem("%.2f" % location.x)
+ item.setData(self.DataLocation, location.x)
+ self.formLoc.baseList.setItem(self.formLoc.baseList.rowCount()-1, 0, item)
+
+ item = QtGui.QTableWidgetItem("%.2f" % location.y)
+ item.setData(self.DataLocation, location.y)
+ self.formLoc.baseList.setItem(self.formLoc.baseList.rowCount()-1, 1, item)
+ self.formLoc.baseList.resizeColumnToContents(0)
+ self.formLoc.baseList.blockSignals(False)
+
+ def removeLocation(self):
+ deletedRows = []
+ selected = self.formLoc.baseList.selectedItems()
+ for item in selected:
+ row = self.formLoc.baseList.row(item)
+ if not row in deletedRows:
+ deletedRows.append(row)
+ self.formLoc.baseList.removeRow(row)
+ self.updateLocations()
+ FreeCAD.ActiveDocument.recompute()
+
+ def updateLocations(self):
+ PathLog.track()
+ locations = []
+ for i in range(self.formLoc.baseList.rowCount()):
+ x = self.formLoc.baseList.item(i, 0).data(self.DataLocation)
+ y = self.formLoc.baseList.item(i, 1).data(self.DataLocation)
+ location = FreeCAD.Vector(x, y, 0)
+ locations.append(location)
+ self.obj.Locations = locations
+
+ def addLocation(self):
+ self.getPoint.getPoint(self.addLocationAt)
+
+ def addLocationAt(self, point, obj):
+ if point:
+ locations = self.obj.Locations
+ locations.append(point)
+ self.obj.Locations = locations
+ FreeCAD.ActiveDocument.recompute()
+
+ def editLocation(self):
+ selected = self.formLoc.baseList.selectedItems()
+ if selected:
+ row = self.formLoc.baseList.row(item)
+ self.editRow = row
+ x = self.formLoc.baseList.item(row, 0).data(self.DataLocation)
+ y = self.formLoc.baseList.item(row, 1).data(self.DataLocation)
+ start = FreeCAD.Vector(x, y, 0)
+ self.getPoint.getPoint(self.editLocationAt, start)
+
+ def editLocationAt(self, point, obj):
+ if point:
+ self.formLoc.baseList.item(self.editRow, 0).setData(self.DataLocation, point.x)
+ self.formLoc.baseList.item(self.editRow, 1).setData(self.DataLocation, point.y)
+ self.updateLocations()
+ FreeCAD.ActiveDocument.recompute()
+
+ def registerSignalHandlers(self, obj):
+ self.formLoc.addLocation.clicked.connect(self.addLocation)
+ self.formLoc.removeLocation.clicked.connect(self.removeLocation)
+ self.formLoc.editLocation.clicked.connect(self.editLocation)
+
+ def pageUpdateData(self, obj, prop):
+ if prop in ['Locations']:
+ self.setFields(obj)
+
+
class TaskPanelHeightsPage(TaskPanelPage):
def getForm(self):
return FreeCADGui.PySideUic.loadUi(":/panels/PageHeightsEdit.ui")
@@ -400,6 +505,12 @@ class TaskPanel(object):
else:
self.featurePages.append(TaskPanelBaseGeometryPage(obj, features))
+ if PathOp.FeatureLocations & features:
+ if hasattr(opPage, 'taskPanelBaseLocationPage'):
+ self.featurePages.append(opPage.taskPanelBaseLocationPage(obj, features))
+ else:
+ self.featurePages.append(TaskPanelBaseLocationPage(obj, features))
+
if PathOp.FeatureDepths & features:
if hasattr(opPage, 'taskPanelDepthsPage'):
self.featurePages.append(opPage.taskPanelDepthsPage(obj, features))
@@ -483,6 +594,10 @@ class TaskPanel(object):
self.setClean()
FreeCAD.ActiveDocument.recompute()
+ def modifyStandardButtons(self, buttonBox):
+ for page in self.featurePages:
+ page.modifyStandardButtons(buttonBox)
+
def panelGetFields(self):
PathLog.track()
for page in self.featurePages: