diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index 988d210354..cd3c112546 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -50,6 +50,7 @@ SET(PathScripts_SRCS PathScripts/PathMillFace.py PathScripts/PathPlane.py PathScripts/PathPocket.py + PathScripts/PathPocketGui.py PathScripts/PathPost.py PathScripts/PathPostProcessor.py PathScripts/PathPreferences.py diff --git a/src/Mod/Path/Gui/Resources/Path.qrc b/src/Mod/Path/Gui/Resources/Path.qrc index 1dd5e481ae..b192c40a6d 100644 --- a/src/Mod/Path/Gui/Resources/Path.qrc +++ b/src/Mod/Path/Gui/Resources/Path.qrc @@ -61,9 +61,11 @@ panels/HoldingTagsEdit.ui panels/JobEdit.ui panels/MillFaceEdit.ui - panels/PageOpContourEdit.ui - panels/PageHeightsEdit.ui + panels/PageBaseGeometryEdit.ui panels/PageDepthsEdit.ui + panels/PageHeightsEdit.ui + panels/PageOpContourEdit.ui + panels/PageOpPocketEdit.ui panels/PocketEdit.ui panels/PointEdit.ui panels/ProfileEdgesEdit.ui diff --git a/src/Mod/Path/Gui/Resources/panels/PageBaseGeometryEdit.ui b/src/Mod/Path/Gui/Resources/panels/PageBaseGeometryEdit.ui new file mode 100644 index 0000000000..85534999a0 --- /dev/null +++ b/src/Mod/Path/Gui/Resources/panels/PageBaseGeometryEdit.ui @@ -0,0 +1,59 @@ + + + Form + + + + 0 + 0 + 400 + 560 + + + + Form + + + + + + + + Update + + + + + + + Remove + + + + + + + Add + + + + + + + + + + All objects will be processed using the same operation properties + + + true + + + + + + + + + + diff --git a/src/Mod/Path/Gui/Resources/panels/PageOpPocketEdit.ui b/src/Mod/Path/Gui/Resources/panels/PageOpPocketEdit.ui new file mode 100644 index 0000000000..41bec1a885 --- /dev/null +++ b/src/Mod/Path/Gui/Resources/panels/PageOpPocketEdit.ui @@ -0,0 +1,173 @@ + + + Form + + + + 0 + 0 + 398 + 330 + + + + Form + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Tool Controller + + + + + + + + + + + + + + + + Cut Mode + + + + + + + + Climb + + + + + Conventional + + + + + + + + Pattern + + + + + + + + ZigZag + + + + + Offset + + + + + Spiral + + + + + ZigZagOffset + + + + + Line + + + + + Grid + + + + + Triangle + + + + + + + + ZigZag Angle + + + + + + + + + + Step Over Percent + + + + + + + 1 + + + 100 + + + 10 + + + 100 + + + + + + + Material Allowance + + + + + + + + + + Use Start Point + + + + + + + + + + + Gui::InputField + QLineEdit +
Gui/InputField.h
+
+
+ + +
diff --git a/src/Mod/Path/InitGui.py b/src/Mod/Path/InitGui.py index 33866a8152..be13d90c3f 100644 --- a/src/Mod/Path/InitGui.py +++ b/src/Mod/Path/InitGui.py @@ -65,7 +65,7 @@ class PathWorkbench (Workbench): from PathScripts import PathJob from PathScripts import PathMillFace from PathScripts import PathPlane - from PathScripts import PathPocket + from PathScripts import PathPocketGui from PathScripts import PathPost from PathScripts import PathProfile from PathScripts import PathProfileEdges diff --git a/src/Mod/Path/PathScripts/PathAreaOp.py b/src/Mod/Path/PathScripts/PathAreaOp.py index 100035b0e0..8ba0b9ae1b 100644 --- a/src/Mod/Path/PathScripts/PathAreaOp.py +++ b/src/Mod/Path/PathScripts/PathAreaOp.py @@ -48,8 +48,11 @@ FeatureTool = 0x01 FeatureDepths = 0x02 FeatureHeights = 0x04 FeatureStartPoint = 0x08 -FeatureBaseGeometry = 0x10 -FeatureFinishDepth = 0x20 +FeatureBaseFaces = 0x10 +FeatureBaseEdges = 0x20 +FeatureFinishDepth = 0x40 + +FeatureBaseGeometry = FeatureBaseFaces | FeatureBaseEdges class ObjectOp(object): @@ -268,3 +271,39 @@ class ObjectOp(object): obj.Path = path return sim + def addBase(self, obj, base, sub=""): + PathLog.track() + baselist = obj.Base + if baselist is None: + baselist = [] + if len(baselist) == 0: # When adding the first base object, guess at heights + + try: + bb = base.Shape.BoundBox # parent boundbox + subobj = base.Shape.getElement(sub) + fbb = subobj.BoundBox # feature boundbox + obj.StartDepth = bb.ZMax + obj.ClearanceHeight = bb.ZMax + 5.0 + obj.SafeHeight = bb.ZMax + 3.0 + + if fbb.ZMax == fbb.ZMin and fbb.ZMax == bb.ZMax: # top face + obj.FinalDepth = bb.ZMin + elif fbb.ZMax > fbb.ZMin and fbb.ZMax == bb.ZMax: # vertical face, full cut + obj.FinalDepth = fbb.ZMin + elif fbb.ZMax > fbb.ZMin and fbb.ZMin > bb.ZMin: # internal vertical wall + obj.FinalDepth = fbb.ZMin + elif fbb.ZMax == fbb.ZMin and fbb.ZMax > bb.ZMin: # face/shelf + obj.FinalDepth = fbb.ZMin + else: # catch all + obj.FinalDepth = bb.ZMin + except: + obj.StartDepth = 5.0 + obj.ClearanceHeight = 10.0 + obj.SafeHeight = 8.0 + + item = (base, sub) + if item in baselist: + PathLog.warning(translate("Path", "this object already in the list" + "\n")) + else: + baselist.append(item) + obj.Base = baselist diff --git a/src/Mod/Path/PathScripts/PathAreaOpGui.py b/src/Mod/Path/PathScripts/PathAreaOpGui.py index 964181f06a..cf9258f4aa 100644 --- a/src/Mod/Path/PathScripts/PathAreaOpGui.py +++ b/src/Mod/Path/PathScripts/PathAreaOpGui.py @@ -81,8 +81,11 @@ class ViewProvider(object): return None class TaskPanelPage(object): + + # task panel interaction framework def __init__(self, obj): self.obj = obj + self.initPage(obj) self.form = self.getForm() self.setDirty() self.setTitle('-') @@ -102,12 +105,146 @@ class TaskPanelPage(object): def pageRegisterSignalHandlers(self): for signal in self.getSignalsForUpdate(self.obj): signal.connect(self.pageGetFields) + self.registerSignalHandlers(self.obj) def setTitle(self, title): self.title = title def getTitle(self, obj): return self.title + # subclass interface + def initPage(self, obj): + pass + def getForm(self): + pass + def getFields(self, obj): + pass + def setFields(self, obj): + pass + def getSignalsForUpdate(self, obj): + return [] + def registerSignalHandlers(self, obj): + pass + + # helpers + def selectInComboBox(self, name, combo): + index = combo.findText(name, QtCore.Qt.MatchFixedString) + if index >= 0: + combo.blockSignals(True) + combo.setCurrentIndex(index) + combo.blockSignals(False) + + def setupToolController(self, obj, combo): + controllers = PathUtils.getToolControllers(self.obj) + labels = [c.Label for c in controllers] + combo.blockSignals(True) + combo.addItems(labels) + combo.blockSignals(False) + + if obj.ToolController is None: + obj.ToolController = PathUtils.findToolController(obj) + if obj.ToolController is not None: + self.selectInComboBox(obj.ToolController.Label, combo) + +class TaskPanelBaseGeometryPage(TaskPanelPage): + DataObject = QtCore.Qt.ItemDataRole.UserRole + DataObjectSub = QtCore.Qt.ItemDataRole.UserRole + 1 + + def initPage(self, obj): + self.supports = PathAreaOp.FeatureBaseGeometry + + def getForm(self): + return FreeCADGui.PySideUic.loadUi(":/panels/PageBaseGeometryEdit.ui") + def getFields(self, obj): + pass + def setFields(self, obj): + self.form.baseList.blockSignals(True) + self.form.baseList.clear() + for base in self.obj.Base: + for sub in base[1]: + item = QtGui.QListWidgetItem("%s.%s" % (base[0].Label, sub)) + item.setData(self.DataObject, base[0]) + item.setData(self.DataObjectSub, sub) + self.form.baseList.addItem(item) + self.form.baseList.blockSignals(False) + + def itemActivated(self): + FreeCADGui.Selection.clearSelection() + for item in self.form.baseList.selectedItems(): + obj = item.data(self.DataObject) + sub = item.data(self.DataObjectSub) + if sub: + FreeCADGui.Selection.addSelection(obj, sub) + else: + FreeCADGui.Selection.addSelection(obj) + #FreeCADGui.updateGui() + + def supportsEdges(self): + return self.support & PathAreaOp.FeatureBaseEdges + def supportsFaces(self): + return self.support & PathAreaOp.FeatureBaseFaces + def featureName(self): + if self.supportsEdges() and self.supportsFaces(): + return 'features' + if self.supportsFaces(): + return 'faces' + if self.supportsEdges(): + return 'edges' + return 'nothing' + + def addBase(self): + selection = FreeCADGui.Selection.getSelectionEx() + + if len(selection) != 1: + PahtLog.error(translate("PathProject", "Please select %s from a single solid" % self.featureName())) + return + sel = selection[0] + if not sel.HasSubObjects: + PahtLog.error(translate("PathProject", "Please select %s of a solid" % self.featureName())) + return + if not self.supportsEdges() and selection[0].SubObjects[0].ShapeType == "Edge": + PahtLog.error(translate("PathProject", "Please select only %s of a solid" % self.featureName())) + return + if not self.supportsFaces() and selection[0].SubObjects[0].ShapeType == "Face": + PahtLog.error(translate("PathProject", "Please select only %s of a solid" % self.featureName())) + return + for i in sel.SubElementNames: + self.obj.Proxy.addBase(self.obj, sel.Object, i) + + self.obj.Proxy.execute(self.obj) + self.setFields() + + def deleteBase(self): + newlist = [] + for item in self.form.baseList.selectedItems(): + obj = item.data(self.DataObject) + sub = itme.data(self.DataObjectSub) + for base in self.obj.Base: + if base[0].Name != obj.Name and base[1] != sub: + newlist.append(base) + self.form.baseList.takeItem(self.form.baseList.row(item)) + self.obj.Base = newlist + #self.obj.Proxy.execute(self.obj) + #FreeCAD.ActiveDocument.recompute() + + def updateBase(self): + newlist = [] + for i in range(self.form.baseList.count()): + item = self.form.baseList.item(i) + obj = item.data(self.DataObject) + sub = item.data(self.DataObjectSub) + newlist.append((obj, sub)) + self.obj.Base = newlist + + #self.obj.Proxy.execute(self.obj) + #FreeCAD.ActiveDocument.recompute() + + def registerSignalHandlers(self, obj): + self.form.baseList.itemSelectionChanged.connect(self.itemActivated) + self.form.addBase.clicked.connect(self.addBase) + self.form.deleteBase.clicked.connect(self.deleteBase) + self.form.updateBase.clicked.connect(self.updateBase) + class TaskPanelHeightsPage(TaskPanelPage): def getForm(self): return FreeCADGui.PySideUic.loadUi(":/panels/PageHeightsEdit.ui") @@ -172,6 +309,11 @@ class TaskPanel(object): self.deleteOnReject = deleteOnReject self.featurePages = [] + if PathAreaOp.FeatureBaseGeometry & obj.Proxy.opFeatures(obj): + basePage = TaskPanelBaseGeometryPage(obj) + basePage.supports = obj.Proxy.opFeatures(obj) & PathAreaOp.FeatureBaseGeometry + self.featurePages.append(basePage) + if PathAreaOp.FeatureDepths & obj.Proxy.opFeatures(obj): if PathAreaOp.FeatureFinishDepth & obj.Proxy.opFeatures(obj): depthPage = TaskPanelDepthsPage(obj) diff --git a/src/Mod/Path/PathScripts/PathContourGui.py b/src/Mod/Path/PathScripts/PathContourGui.py index 4bc53378a2..f4311f7fb8 100644 --- a/src/Mod/Path/PathScripts/PathContourGui.py +++ b/src/Mod/Path/PathScripts/PathContourGui.py @@ -38,9 +38,6 @@ def translate(context, text, disambig=None): class TaskPanelOpPage(PathAreaOpGui.TaskPanelPage): - def opSelectionFactory(self): - return PathSelection.contourselect - def getForm(self): return FreeCADGui.PySideUic.loadUi(":/panels/PageOpContourEdit.ui") @@ -49,6 +46,8 @@ class TaskPanelOpPage(PathAreaOpGui.TaskPanelPage): self.obj.OffsetExtra = FreeCAD.Units.Quantity(self.form.extraOffset.text()).Value self.obj.UseComp = self.form.useCompensation.isChecked() self.obj.Direction = str(self.form.direction.currentText()) + self.obj.UseStartPoint = self.form.useStartPoint.isChecked() + tc = PathUtils.findToolController(self.obj, self.form.toolController.currentText()) self.obj.ToolController = tc @@ -56,33 +55,10 @@ class TaskPanelOpPage(PathAreaOpGui.TaskPanelPage): PathLog.track() self.form.extraOffset.setText(FreeCAD.Units.Quantity(self.obj.OffsetExtra.Value, FreeCAD.Units.Length).UserString) self.form.useCompensation.setChecked(self.obj.UseComp) - # self.form.useStartPoint.setChecked(self.obj.UseStartPoint) + self.form.useStartPoint.setChecked(self.obj.UseStartPoint) - index = self.form.direction.findText( - self.obj.Direction, QtCore.Qt.MatchFixedString) - if index >= 0: - self.form.direction.blockSignals(True) - self.form.direction.setCurrentIndex(index) - self.form.direction.blockSignals(False) - - controllers = PathUtils.getToolControllers(self.obj) - labels = [c.Label for c in controllers] - self.form.toolController.blockSignals(True) - self.form.toolController.addItems(labels) - self.form.toolController.blockSignals(False) - - if self.obj.ToolController is None: - self.obj.ToolController = PathUtils.findToolController(self.obj) - - if self.obj.ToolController is not None: - index = self.form.toolController.findText( - self.obj.ToolController.Label, QtCore.Qt.MatchFixedString) - if index >= 0: - self.form.toolController.blockSignals(True) - self.form.toolController.setCurrentIndex(index) - self.form.toolController.blockSignals(False) - else: - self.obj.ToolController = PathUtils.findToolController(self.obj) + self.selectInComboBox(self.obj.Direction, self.form.direction) + self.setupToolController(self.obj, self.form.toolController) def getSignalsForUpdate(self, obj): PathLog.track() @@ -94,7 +70,7 @@ class TaskPanelOpPage(PathAreaOpGui.TaskPanelPage): signals.append(self.form.extraOffset.editingFinished) return signals -class _ViewProviderContour(PathAreaOpGui.ViewProvider): +class ViewProviderContour(PathAreaOpGui.ViewProvider): def getTaskPanelOpPage(self, obj): return TaskPanelOpPage(obj) @@ -108,12 +84,13 @@ class _ViewProviderContour(PathAreaOpGui.ViewProvider): def Create(name): FreeCAD.ActiveDocument.openTransaction(translate("Path", "Create a Contour")) obj = PathContour.Create(name) - vobj = _ViewProviderContour(obj.ViewObject) + vobj = ViewProviderContour(obj.ViewObject) obj.ViewObject.Proxy.deleteOnReject = True FreeCAD.ActiveDocument.commitTransaction() obj.ViewObject.startEditing() + return obj class CommandPathContour: def GetResources(self): diff --git a/src/Mod/Path/PathScripts/PathPocket.py b/src/Mod/Path/PathScripts/PathPocket.py index 0ec40b1eaf..71ab3dd1b5 100644 --- a/src/Mod/Path/PathScripts/PathPocket.py +++ b/src/Mod/Path/PathScripts/PathPocket.py @@ -29,7 +29,7 @@ import PathScripts.PathAreaOp as PathAreaOp import PathScripts.PathLog as PathLog from PathScripts import PathUtils -from PySide import QtCore, QtGui +from PySide import QtCore """Path Pocket object and FreeCAD command""" @@ -39,8 +39,6 @@ if False: else: PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) -import FreeCADGui - # Qt tanslation handling def translate(context, text, disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) @@ -63,8 +61,8 @@ class ObjectPocket(PathAreaOp.ObjectOp): obj.OffsetPattern = ['ZigZag', 'Offset', 'Spiral', 'ZigZagOffset', 'Line', 'Grid', 'Triangle'] obj.addProperty("App::PropertyBool", "MinTravel", "Pocket", QtCore.QT_TRANSLATE_NOOP("App::Property", "Use 3D Sorting of Path")) - if FreeCAD.GuiUp: - ViewProviderPocket(obj.ViewObject) + def opFeatures(self, obj): + return PathAreaOp.FeatureTool | PathAreaOp.FeatureDepths | PathAreaOp.FeatureHeights | PathAreaOp.FeatureStartPoint | PathAreaOp.FeatureBaseFaces | PathAreaOp.FeatureFinishDepth def opShapeForDepths(self, obj): job = PathUtils.findParentJob(obj) @@ -175,322 +173,3 @@ def Create(name): obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) proxy = ObjectPocket(obj) return obj - -class _CommandSetPocketStartPoint: - def GetResources(self): - return {'Pixmap': 'Path-StartPoint', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("PathPocket", "Pick Start Point"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathPocket", "Pick Start Point")} - - def IsActive(self): - return FreeCAD.ActiveDocument is not None - - def setpoint(self, point, o): - obj = FreeCADGui.Selection.getSelection()[0] - obj.StartPoint.x = point.x - obj.StartPoint.y = point.y - - def Activated(self): - FreeCADGui.Snapper.getPoint(callback=self.setpoint) - - -class ViewProviderPocket: - - def __init__(self, vobj): - vobj.Proxy = self - - def attach(self, vobj): - self.Object = vobj.Object - return - - def deleteObjectsOnReject(self): - return hasattr(self, 'deleteOnReject') and self.deleteOnReject - - def setEdit(self, vobj, mode=0): - FreeCADGui.Control.closeDialog() - taskd = TaskPanel(vobj.Object, self.deleteObjectsOnReject()) - taskd.obj = vobj.Object - FreeCADGui.Control.showDialog(taskd) - taskd.setupUi() - self.deleteOnReject = False - return True - - def getIcon(self): - return ":/icons/Path-Pocket.svg" - - def __getstate__(self): - return None - - def __setstate__(self, state): - return None - - -class CommandPathPocket: - - def GetResources(self): - return {'Pixmap': 'Path-Pocket', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("PathPocket", "Pocket"), - 'Accel': "P, O", - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathPocket", "Creates a Path Pocket object from a face or faces")} - - def IsActive(self): - if FreeCAD.ActiveDocument is not None: - for o in FreeCAD.ActiveDocument.Objects: - if o.Name[:3] == "Job": - return True - return False - - def Activated(self): - PathLog.track() - - FreeCAD.ActiveDocument.openTransaction(translate("PathPocket", "Create Pocket")) - obj = Create("Pocket") - FreeCAD.ActiveDocument.commitTransaction() - - # FreeCAD.ActiveDocument.recompute() - obj.ViewObject.startEditing() - return obj - - -class TaskPanel: - def __init__(self, obj, deleteOnReject): - FreeCAD.ActiveDocument.openTransaction(translate("Path_Pocket", "Pocket Operation")) - # self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/PocketEdit.ui") - self.form = FreeCADGui.PySideUic.loadUi(":/panels/PocketEdit.ui") - self.deleteOnReject = deleteOnReject - self.isDirty = True - - def accept(self): - FreeCADGui.Control.closeDialog() - FreeCADGui.ActiveDocument.resetEdit() - FreeCAD.ActiveDocument.commitTransaction() - FreeCADGui.Selection.removeObserver(self.s) - if self.isDirty: - FreeCAD.ActiveDocument.recompute() - - def reject(self): - FreeCADGui.Control.closeDialog() - FreeCADGui.ActiveDocument.resetEdit() - FreeCAD.ActiveDocument.abortTransaction() - FreeCADGui.Selection.removeObserver(self.s) - if self.deleteOnReject: - FreeCAD.ActiveDocument.openTransaction(translate("Path_Pocket", "Uncreate Pocket Operation")) - FreeCAD.ActiveDocument.removeObject(self.obj.Name) - FreeCAD.ActiveDocument.commitTransaction() - FreeCAD.ActiveDocument.recompute() - - def clicked(self, button): - if button == QtGui.QDialogButtonBox.Apply: - self.getFields() - self.obj.Proxy.execute(self.obj) - self.isDirty = False - - def getFields(self): - if self.obj: - if hasattr(self.obj, "StartDepth"): - self.obj.StartDepth = FreeCAD.Units.Quantity(self.form.startDepth.text()).Value - if hasattr(self.obj, "FinalDepth"): - self.obj.FinalDepth = FreeCAD.Units.Quantity(self.form.finalDepth.text()).Value - if hasattr(self.obj, "FinishDepth"): - self.obj.FinishDepth = FreeCAD.Units.Quantity(self.form.finishDepth.text()).Value - if hasattr(self.obj, "StepDown"): - self.obj.StepDown = FreeCAD.Units.Quantity(self.form.stepDown.text()).Value - if hasattr(self.obj, "SafeHeight"): - self.obj.SafeHeight = FreeCAD.Units.Quantity(self.form.safeHeight.text()).Value - if hasattr(self.obj, "ClearanceHeight"): - self.obj.ClearanceHeight = FreeCAD.Units.Quantity(self.form.clearanceHeight.text()).Value - if hasattr(self.obj, "MaterialAllowance"): - self.obj.MaterialAllowance = FreeCAD.Units.Quantity(self.form.extraOffset.text()).Value - if hasattr(self.obj, "UseStartPoint"): - self.obj.UseStartPoint = self.form.useStartPoint.isChecked() - if hasattr(self.obj, "CutMode"): - self.obj.CutMode = str(self.form.cutMode.currentText()) - if hasattr(self.obj, "OffsetPattern"): - self.obj.OffsetPattern = str(self.form.offsetpattern.currentText()) - if hasattr(self.obj, "ZigZagAngle"): - self.obj.ZigZagAngle = FreeCAD.Units.Quantity(self.form.zigZagAngle.text()).Value - if hasattr(self.obj, "StepOver"): - self.obj.StepOver = self.form.stepOverPercent.value() - if hasattr(self.obj, "ToolController"): - PathLog.debug("name: {}".format(self.form.uiToolController.currentText())) - tc = PathUtils.findToolController(self.obj, self.form.uiToolController.currentText()) - self.obj.ToolController = tc - self.isDirty = True - - def setFields(self): - self.form.startDepth.setText(FreeCAD.Units.Quantity(self.obj.StartDepth.Value, FreeCAD.Units.Length).UserString) - self.form.finalDepth.setText(FreeCAD.Units.Quantity(self.obj.FinalDepth.Value, FreeCAD.Units.Length).UserString) - self.form.finishDepth.setText(FreeCAD.Units.Quantity(self.obj.FinishDepth.Value, FreeCAD.Units.Length).UserString) - self.form.stepDown.setText(FreeCAD.Units.Quantity(self.obj.StepDown.Value, FreeCAD.Units.Length).UserString) - self.form.safeHeight.setText(FreeCAD.Units.Quantity(self.obj.SafeHeight.Value, FreeCAD.Units.Length).UserString) - self.form.clearanceHeight.setText(FreeCAD.Units.Quantity(self.obj.ClearanceHeight.Value, FreeCAD.Units.Length).UserString) - self.form.extraOffset.setText(FreeCAD.Units.Quantity(self.obj.MaterialAllowance.Value, FreeCAD.Units.Length).UserString) - self.form.useStartPoint.setChecked(self.obj.UseStartPoint) - self.form.zigZagAngle.setText(FreeCAD.Units.Quantity(self.obj.ZigZagAngle, FreeCAD.Units.Angle).UserString) - self.form.stepOverPercent.setValue(self.obj.StepOver) - - index = self.form.offsetpattern.findText( - self.obj.OffsetPattern, QtCore.Qt.MatchFixedString) - if index >= 0: - self.form.offsetpattern.blockSignals(True) - self.form.offsetpattern.setCurrentIndex(index) - self.form.offsetpattern.blockSignals(False) - - index = self.form.cutMode.findText( - self.obj.CutMode, QtCore.Qt.MatchFixedString) - if index >= 0: - self.form.cutMode.blockSignals(True) - self.form.cutMode.setCurrentIndex(index) - self.form.cutMode.blockSignals(False) - - self.form.baseList.blockSignals(True) - for i in self.obj.Base: - for sub in i[1]: - self.form.baseList.addItem(i[0].Name + "." + sub) - self.form.baseList.blockSignals(False) - - controllers = PathUtils.getToolControllers(self.obj) - labels = [c.Label for c in controllers] - self.form.uiToolController.blockSignals(True) - self.form.uiToolController.addItems(labels) - self.form.uiToolController.blockSignals(False) - if self.obj.ToolController is not None: - index = self.form.uiToolController.findText( - self.obj.ToolController.Label, QtCore.Qt.MatchFixedString) - PathLog.debug("searching for TC label {}. Found Index: {}".format(self.obj.ToolController.Label, index)) - if index >= 0: - self.form.uiToolController.blockSignals(True) - self.form.uiToolController.setCurrentIndex(index) - self.form.uiToolController.blockSignals(False) - else: - self.obj.ToolController = PathUtils.findToolController(self.obj) - - def open(self): - self.s = SelObserver() - # install the function mode resident - FreeCADGui.Selection.addObserver(self.s) - - def addBase(self): - # check that the selection contains exactly what we want - selection = FreeCADGui.Selection.getSelectionEx() - - if len(selection) != 1: - FreeCAD.Console.PrintError(translate("PathProject", "Please select only faces from one solid\n")) - return - sel = selection[0] - if not sel.HasSubObjects: - FreeCAD.Console.PrintError(translate("PathProject", "Please select faces from one solid\n")) - return - if not selection[0].SubObjects[0].ShapeType == "Face": - FreeCAD.Console.PrintError(translate("PathProject", "Please select faces from one solid\n")) - return - for i in sel.SubElementNames: - self.obj.Proxy.addpocketbase(self.obj, sel.Object, i) - - self.setFields() # defaults may have changed. Reload. - self.form.baseList.clear() - - for i in self.obj.Base: - for sub in i[1]: - self.form.baseList.addItem(i[0].Name + "." + sub) - - def deleteBase(self): - dlist = self.form.baseList.selectedItems() - newlist = [] - for d in dlist: - for i in self.obj.Base: - if i[0].Name != d.text().partition(".")[0] or i[1] != d.text().partition(".")[2]: - newlist.append(i) - self.form.baseList.takeItem(self.form.baseList.row(d)) - self.obj.Base = newlist - self.obj.Proxy.execute(self.obj) - FreeCAD.ActiveDocument.recompute() - - def itemActivated(self): - FreeCADGui.Selection.clearSelection() - slist = self.form.baseList.selectedItems() - for i in slist: - objstring = i.text().partition(".") - obj = FreeCAD.ActiveDocument.getObject(objstring[0]) - if objstring[2] != "": - FreeCADGui.Selection.addSelection(obj, objstring[2]) - else: - FreeCADGui.Selection.addSelection(obj) - - FreeCADGui.updateGui() - - def reorderBase(self): - newlist = [] - for i in range(self.form.baseList.count()): - s = self.form.baseList.item(i).text() - objstring = s.partition(".") - - obj = FreeCAD.ActiveDocument.getObject(objstring[0]) - item = (obj, str(objstring[2])) - newlist.append(item) - self.obj.Base = newlist - - self.obj.Proxy.execute(self.obj) - FreeCAD.ActiveDocument.recompute() - - def getStandardButtons(self): - return int(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel) - - def setupUi(self): - - # Connect Signals and Slots - # Base Controls - self.form.baseList.itemSelectionChanged.connect(self.itemActivated) - self.form.addBase.clicked.connect(self.addBase) - self.form.deleteBase.clicked.connect(self.deleteBase) - self.form.reorderBase.clicked.connect(self.reorderBase) - self.form.uiToolController.currentIndexChanged.connect(self.getFields) - - # Depths - self.form.startDepth.editingFinished.connect(self.getFields) - self.form.finalDepth.editingFinished.connect(self.getFields) - self.form.finishDepth.editingFinished.connect(self.getFields) - self.form.stepDown.editingFinished.connect(self.getFields) - - # Heights - self.form.safeHeight.editingFinished.connect(self.getFields) - self.form.clearanceHeight.editingFinished.connect(self.getFields) - - # operation - self.form.cutMode.currentIndexChanged.connect(self.getFields) - self.form.useStartPoint.clicked.connect(self.getFields) - - # Pattern - self.form.offsetpattern.currentIndexChanged.connect(self.getFields) - self.form.stepOverPercent.editingFinished.connect(self.getFields) - self.form.zigZagAngle.editingFinished.connect(self.getFields) - self.form.extraOffset.editingFinished.connect(self.getFields) - self.form.uiToolController.currentIndexChanged.connect(self.getFields) - - self.setFields() - - sel = FreeCADGui.Selection.getSelectionEx() - if len(sel) != 0 and sel[0].HasSubObjects: - self.addBase() - - -class SelObserver: - def __init__(self): - import PathScripts.PathSelection as PST - PST.pocketselect() - - def __del__(self): - import PathScripts.PathSelection as PST - PST.clear() - - def addSelection(self, doc, obj, sub, pnt): - FreeCADGui.doCommand('Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')') - FreeCADGui.updateGui() - -if FreeCAD.GuiUp: - # register the FreeCAD command - FreeCADGui.addCommand('Path_Pocket', CommandPathPocket()) - FreeCADGui.addCommand('Set_PocketStartPoint', _CommandSetPocketStartPoint()) - - -FreeCAD.Console.PrintLog("Loading PathPocket... done\n") diff --git a/src/Mod/Path/PathScripts/PathPocketGui.py b/src/Mod/Path/PathScripts/PathPocketGui.py new file mode 100644 index 0000000000..aeb7ccbbbb --- /dev/null +++ b/src/Mod/Path/PathScripts/PathPocketGui.py @@ -0,0 +1,120 @@ +# -*- 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 FreeCAD +import FreeCADGui +import Path +import PathScripts.PathAreaOpGui as PathAreaOpGui +import PathScripts.PathLog as PathLog +import PathScripts.PathPocket as PathPocket +import PathScripts.PathSelection as PathSelection + +from PathScripts import PathUtils +from PySide import QtCore, QtGui + +def translate(context, text, disambig=None): + return QtCore.QCoreApplication.translate(context, text, disambig) + +class TaskPanelOpPage(PathAreaOpGui.TaskPanelPage): + + def getForm(self): + return FreeCADGui.PySideUic.loadUi(":/panels/PageOpPocketEdit.ui") + + def getFields(self, obj): + self.obj.MaterialAllowance = FreeCAD.Units.Quantity(self.form.extraOffset.text()).Value + self.obj.CutMode = str(self.form.cutMode.currentText()) + self.obj.OffsetPattern = str(self.form.offsetPattern.currentText()) + self.obj.ZigZagAngle = FreeCAD.Units.Quantity(self.form.zigZagAngle.text()).Value + self.obj.StepOver = self.form.stepOverPercent.value() + self.obj.UseStartPoint = self.form.useStartPoint.isChecked() + + tc = PathUtils.findToolController(self.obj, self.form.toolController.currentText()) + self.obj.ToolController = tc + + def setFields(self, obj): + self.form.extraOffset.setText(FreeCAD.Units.Quantity(self.obj.MaterialAllowance.Value, FreeCAD.Units.Length).UserString) + self.form.useStartPoint.setChecked(self.obj.UseStartPoint) + self.form.zigZagAngle.setText(FreeCAD.Units.Quantity(self.obj.ZigZagAngle, FreeCAD.Units.Angle).UserString) + self.form.stepOverPercent.setValue(self.obj.StepOver) + + self.selectInComboBox(self.obj.OffsetPattern, self.form.offsetPattern) + self.selectInComboBox(self.obj.CutMode, self.form.cutMode) + self.setupToolController(self.obj, self.form.toolController) + + def getSignalsForUpdate(self, obj): + signals = [] + # operation + signals.append(self.form.cutMode.currentIndexChanged) + signals.append(self.form.useStartPoint.clicked) + + # Pattern + signals.append(self.form.offsetPattern.currentIndexChanged) + signals.append(self.form.stepOverPercent.editingFinished) + signals.append(self.form.zigZagAngle.editingFinished) + signals.append(self.form.extraOffset.editingFinished) + signals.append(self.form.toolController.currentIndexChanged) + return signals + +class ViewProviderPocket(PathAreaOpGui.ViewProvider): + + def getTaskPanelOpPage(self, obj): + return TaskPanelOpPage(obj) + + def getIcon(self): + return ":/icons/Path-Pocket.svg" + + def getSelectionFactory(self): + return PathSelection.pocketselect + +def Create(name): + FreeCAD.ActiveDocument.openTransaction(translate("PathPocket", "Create Pocket")) + obj = PathPocket.Create(name) + vobj = ViewProviderPocket(obj.ViewObject) + + obj.ViewObject.Proxy.deleteOnReject = True + + FreeCAD.ActiveDocument.commitTransaction() + obj.ViewObject.startEditing() + return obj + +class CommandPathPocket: + + def GetResources(self): + return {'Pixmap': 'Path-Pocket', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("PathPocket", "Pocket"), + 'Accel': "P, O", + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathPocket", "Creates a Path Pocket object from a face or faces")} + + def IsActive(self): + if FreeCAD.ActiveDocument is not None: + for o in FreeCAD.ActiveDocument.Objects: + if o.Name[:3] == "Job": + return True + return False + + def Activated(self): + return Create("Pocket") + +FreeCADGui.addCommand('Path_Pocket', CommandPathPocket()) +FreeCAD.Console.PrintLog("Loading PathPocketGui... done\n")