diff --git a/src/Mod/CAM/Gui/Resources/Path.qrc b/src/Mod/CAM/Gui/Resources/Path.qrc index 287d7a2a61..071ae97d00 100644 --- a/src/Mod/CAM/Gui/Resources/Path.qrc +++ b/src/Mod/CAM/Gui/Resources/Path.qrc @@ -124,6 +124,7 @@ panels/SetupOp.ui panels/ToolBitEditor.ui panels/ToolBitLibraryEdit.ui + panels/ToolControllerEdit.ui panels/TaskPathCamoticsSim.ui panels/TaskPathSimulator.ui panels/TaskCAMSimulator.ui diff --git a/src/Mod/CAM/Gui/Resources/panels/DlgToolControllerEdit.ui b/src/Mod/CAM/Gui/Resources/panels/DlgToolControllerEdit.ui index 511aafc20e..ce26f9dc62 100644 --- a/src/Mod/CAM/Gui/Resources/panels/DlgToolControllerEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/DlgToolControllerEdit.ui @@ -15,293 +15,8 @@ - - - - - 0 - 0 - 543 - 638 - - - - Controller - - - - - - Controller Name / Tool Number - - - - - - false - - - - - - - 99999 - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - Horizontal feed - - - - - - - - 0 - 0 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0.000000000000000 - - - 9999999.000000000000000 - - - mm/s - - - - - - - Vertical feed - - - - - - - - 0 - 0 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0.000000000000000 - - - 9999999.000000000000000 - - - mm/s - - - - - - - Horizontal rapid - - - - - - - - 0 - 0 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0.000000000000000 - - - 9999999.000000000000000 - - - mm/s - - - - - - - Vertical rapid - - - - - - - - 0 - 0 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0.000000000000000 - - - 9999999.000000000000000 - - - mm/s - - - - - - - - - - Spindle - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - - Forward - - - - - Reverse - - - - - - - - 0.000000000000000 - - - 100000.000000000000000 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - 0 - 0 - 543 - 638 - - - - Tool - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - QFrame::WinPanel - - - Any modifications only affect this ToolController! - - - Qt::AlignCenter - - - true - - - - - + + @@ -316,22 +31,7 @@ - - - Gui::QuantitySpinBox - QDoubleSpinBox -
Gui/QuantitySpinBox.h
-
-
- tcName - tcNumber - horizFeed - vertFeed - horizRapid - vertRapid - spindleSpeed - spindleDirection buttonBox diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpAdaptiveEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpAdaptiveEdit.ui index 31d6ff4b93..667bc2755a 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpAdaptiveEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpAdaptiveEdit.ui @@ -25,7 +25,7 @@ - + @@ -37,6 +37,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpCustomEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpCustomEdit.ui index e7f084e0fc..ab8d05a783 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpCustomEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpCustomEdit.ui @@ -53,6 +53,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpDeburrEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpDeburrEdit.ui index 8b0ae3bdb8..0fe4be6b3d 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpDeburrEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpDeburrEdit.ui @@ -29,7 +29,7 @@ QFrame::Raised - + @@ -54,14 +54,14 @@ - + The tool and its settings to be used for this operation - + @@ -86,13 +86,20 @@ - + The tool and its settings to be used for this operation + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpDrillingEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpDrillingEdit.ui index d8920da0f7..d6a0330d5f 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpDrillingEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpDrillingEdit.ui @@ -56,8 +56,8 @@ The tool and its settings to be used for this operation - - + + Do not retract after every hole @@ -67,6 +67,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpEngraveEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpEngraveEdit.ui index 3296627d78..e2e5579a33 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpEngraveEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpEngraveEdit.ui @@ -51,6 +51,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpHelixEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpHelixEdit.ui index 02d656535a..574d8371b2 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpHelixEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpHelixEdit.ui @@ -51,6 +51,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpPocketFullEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpPocketFullEdit.ui index ecff4f3a4c..e08bdac8d1 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpPocketFullEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpPocketFullEdit.ui @@ -51,6 +51,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpProbeEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpProbeEdit.ui index d3dc72f8e9..9306803c0b 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpProbeEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpProbeEdit.ui @@ -43,6 +43,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpProfileFullEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpProfileFullEdit.ui index 6b215e43c1..f907d6397a 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpProfileFullEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpProfileFullEdit.ui @@ -51,6 +51,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpSlotEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpSlotEdit.ui index 85f7cd7aa8..b1ece310ef 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpSlotEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpSlotEdit.ui @@ -25,7 +25,7 @@ QFrame::Raised - + 3 @@ -53,6 +53,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpSurfaceEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpSurfaceEdit.ui index 9aea7bc7b4..4fe64dbbaf 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpSurfaceEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpSurfaceEdit.ui @@ -22,7 +22,7 @@ QFrame::Raised - + @@ -51,6 +51,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpTappingEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpTappingEdit.ui index 242221bf33..133ed66cd6 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpTappingEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpTappingEdit.ui @@ -111,6 +111,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpThreadMillingEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpThreadMillingEdit.ui index 71f59ac8c0..7368d2c161 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpThreadMillingEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpThreadMillingEdit.ui @@ -15,13 +15,34 @@ - - - Tool Controller + + + QFrame::StyledPanel - - - + + QFrame::Raised + + + + + + Tool Controller + + + + + + + The tool and its settings to be used for this operation. + + + + + + + Edit Tool Controller + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpVcarveEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpVcarveEdit.ui index 3115241023..e403fa39bc 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpVcarveEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpVcarveEdit.ui @@ -51,6 +51,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpWaterlineEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpWaterlineEdit.ui index 1e7b8c6cf4..173f0d78b4 100644 --- a/src/Mod/CAM/Gui/Resources/panels/PageOpWaterlineEdit.ui +++ b/src/Mod/CAM/Gui/Resources/panels/PageOpWaterlineEdit.ui @@ -22,7 +22,7 @@ QFrame::Raised - + @@ -47,6 +47,13 @@ + + + + Edit Tool Controller + + + diff --git a/src/Mod/CAM/Gui/Resources/panels/SurfaceEdit.ui b/src/Mod/CAM/Gui/Resources/panels/SurfaceEdit.ui deleted file mode 100644 index 7bb41cbd01..0000000000 --- a/src/Mod/CAM/Gui/Resources/panels/SurfaceEdit.ui +++ /dev/null @@ -1,351 +0,0 @@ - - - TaskPanel - - - - 0 - 0 - 363 - 523 - - - - - 0 - 400 - - - - Surface - - - - - - 3 - - - - true - - - - 0 - 0 - 347 - 391 - - - - - :/icons/CAM_BaseGeometry.svg:/icons/CAM_BaseGeometry.svg - - - Base geometry - - - - - - Drag to reorder, then update - - - QAbstractItemView::DragDrop - - - Qt::MoveAction - - - false - - - - - - - Add item selected in window - - - Add - - - - - - - Remove item selected in list, then update - - - Remove - - - - - - - Update the path with the removed and reordered items - - - Update - - - - - - - All objects will be profiled using the same depth and speed settings - - - Qt::AutoText - - - true - - - - - - - - - 0 - 0 - 347 - 391 - - - - - :/icons/CAM_Depths.svg:/icons/CAM_Depths.svg - - - Depths - - - - - - mm - - - - - - - Start depth - - - - - - - mm - - - - - - - Final depth - - - - - - - mm - - - - - - - Step down - - - - - - - mm - - - - - - - Finish step down - - - - - - - - - 0 - 0 - 347 - 391 - - - - - :/icons/CAM_Heights.svg:/icons/CAM_Heights.svg - - - Heights - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - mm - - - - - - - Safe height - - - - - - - mm - - - - - - - Clearance height - - - - - - - - - 0 - 0 - 347 - 391 - - - - - :/icons/CAM_OperationB.svg:/icons/CAM_OperationB.svg - - - Operation - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - Tool controller - - - - - - - - - - Coolant mode - - - - - - - The tool and its settings to be used for this operation. - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - Algorithm - - - - - - - - OCL dropcutter - - - - - OCL waterline - - - - - - - - - - - Qt::Vertical - - - - 20 - 274 - - - - - - - - - - - - - Gui::InputField - QLineEdit -
Gui/InputField.h
-
-
- - - - - -
diff --git a/src/Mod/CAM/Gui/Resources/panels/ToolControllerEdit.ui b/src/Mod/CAM/Gui/Resources/panels/ToolControllerEdit.ui new file mode 100644 index 0000000000..bbb94b24b2 --- /dev/null +++ b/src/Mod/CAM/Gui/Resources/panels/ToolControllerEdit.ui @@ -0,0 +1,240 @@ + + + Frame + + + + 0 + 0 + 561 + 739 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + + Controller Name / Tool Number + + + + + + false + + + + + + + Qt::StrongFocus + + + QAbstractSpinBox::NoButtons + + + 99999 + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Horizontal feed + + + + + + + + 0 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0.000000000000000 + + + 9999999.000000000000000 + + + mm/s + + + + + + + Vertical feed + + + + + + + + 0 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0.000000000000000 + + + 9999999.000000000000000 + + + mm/s + + + + + + + Horizontal rapid + + + + + + + + 0 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0.000000000000000 + + + 9999999.000000000000000 + + + mm/s + + + + + + + Vertical rapid + + + + + + + + 0 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0.000000000000000 + + + 9999999.000000000000000 + + + mm/s + + + + + + + + + + Spindle + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Qt::StrongFocus + + + + Forward + + + + + Reverse + + + + + + + + 0.000000000000000 + + + 100000.000000000000000 + + + + + + + + + + + Gui::QuantitySpinBox + QDoubleSpinBox +
Gui/QuantitySpinBox.h
+
+
+ + tcName + tcNumber + horizFeed + vertFeed + horizRapid + vertRapid + spindleSpeed + spindleDirection + + + +
diff --git a/src/Mod/CAM/Path/Main/Gui/Camotics.py b/src/Mod/CAM/Path/Main/Gui/Camotics.py index 2be847ed63..3c28187ef0 100644 --- a/src/Mod/CAM/Path/Main/Gui/Camotics.py +++ b/src/Mod/CAM/Path/Main/Gui/Camotics.py @@ -28,6 +28,7 @@ import FreeCADGui import Mesh import Path import PathScripts +import PathScripts.PathUtils as PathUtils import Path.Post.Command as PathPost import camotics import io @@ -191,7 +192,7 @@ class CamoticsSimulation(QtCore.QObject): self.SIM.set_tool( t.ToolNumber, metric=True, - shape=self.SHAPEMAP.get(t.Tool.ShapeName, "Cylindrical"), + shape=self.SHAPEMAP.get(PathUtils.getToolShapeName(t.Tool), "Cylindrical"), length=t.Tool.Length.Value, diameter=t.Tool.Diameter.Value, ) @@ -283,7 +284,9 @@ class CamoticsSimulation(QtCore.QObject): if hasattr(t.Tool, "Camotics"): toolitem["shape"] = t.Tool.Camotics else: - toolitem["shape"] = self.SHAPEMAP.get(t.Tool.ShapeName, "Cylindrical") + toolitem["shape"] = self.SHAPEMAP.get( + PathUtils.getToolShapeName(t.Tool), "Cylindrical" + ) toolitem["length"] = t.Tool.Length.Value toolitem["diameter"] = t.Tool.Diameter.Value diff --git a/src/Mod/CAM/Path/Op/Gui/Adaptive.py b/src/Mod/CAM/Path/Op/Gui/Adaptive.py index d16b6ace33..58abd359ba 100644 --- a/src/Mod/CAM/Path/Op/Gui/Adaptive.py +++ b/src/Mod/CAM/Path/Op/Gui/Adaptive.py @@ -57,7 +57,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): signals = [] signals.append(self.form.Side.currentIndexChanged) signals.append(self.form.OperationType.currentIndexChanged) - signals.append(self.form.ToolController.currentIndexChanged) + signals.append(self.form.toolController.currentIndexChanged) signals.append(self.form.stepOverPercent.valueChanged) signals.append(self.form.Tolerance.valueChanged) signals.append(self.form.HelixAngle.valueChanged) @@ -113,7 +113,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): self.form.FinishingProfile.setChecked(obj.FinishingProfile) self.form.useOutline.setChecked(obj.UseOutline) self.form.orderCutsByRegion.setChecked(obj.OrderCutsByRegion) - self.setupToolController(obj, self.form.ToolController) + self.setupToolController(obj, self.form.toolController) self.setupCoolant(obj, self.form.coolantController) self.form.StopButton.setChecked(obj.Stopped) obj.setEditorMode("AdaptiveInputState", 2) # hide this property @@ -155,7 +155,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): self.form.StopButton.setChecked(False) # reset the button obj.StopProcessing = True - self.updateToolController(obj, self.form.ToolController) + self.updateToolController(obj, self.form.toolController) self.updateCoolant(obj, self.form.coolantController) obj.setEditorMode("AdaptiveInputState", 2) # hide this property obj.setEditorMode("AdaptiveOutputState", 2) # hide this property diff --git a/src/Mod/CAM/Path/Op/Gui/Base.py b/src/Mod/CAM/Path/Op/Gui/Base.py index 141b79bc75..2cda1f989e 100644 --- a/src/Mod/CAM/Path/Op/Gui/Base.py +++ b/src/Mod/CAM/Path/Op/Gui/Base.py @@ -30,12 +30,14 @@ import Path.Base.Util as PathUtil import Path.Main.Job as PathJob import Path.Op.Base as PathOp import Path.Op.Gui.Selection as PathSelection +import Path.Tool.Controller as PathToolController +from Path.Tool.library.ui.dock import ToolBitLibraryDock import PathGui import PathScripts.PathUtils as PathUtils import importlib from PySide.QtCore import QT_TRANSLATE_NOOP -from PySide import QtCore, QtGui +from PySide import QtCore, QtGui, QtWidgets __title__ = "CAM Operation UI base classes" __author__ = "sliptonic (Brad Collette)" @@ -212,9 +214,12 @@ class TaskPanelPage(object): self.isdirty = False self.parent = None self.panelTitle = "Operation" + self.tcEditor = None + self.combo = None if self._installTCUpdate(): PathJob.Notification.updateTC.connect(self.resetToolController) + self.form.toolController.currentIndexChanged.connect(self.tcComboChanged) def show_error_message(self, title, message): msg_box = QtGui.QMessageBox() @@ -389,27 +394,141 @@ class TaskPanelPage(object): """populateCombobox(form, enumTups, comboBoxesPropertyMap) ... proxy for PathGuiUtil.populateCombobox()""" PathGuiUtil.populateCombobox(form, enumTups, comboBoxesPropertyMap) + def tcComboChanged(self, newIndex): + if self.obj is not None and self.tcEditor: + if newIndex == self.combo.count() - 1: + # Special entry: new tool controller. Show the tool dock and reset combo + dock = ToolBitLibraryDock(self.job, True) + dock.open() + self.resetTCCombo() + elif newIndex == self.combo.count() - 2: + # Special entry: copy tool controller + self.copyToolController() # this function also rebuilds the combo + self.resetTCCombo() + else: + tc = PathUtils.findToolController( + self.obj, self.obj.Proxy, self.form.toolController.currentText() + ) + self.obj.ToolController = tc + self.setupToolController() + + def updateToolControllerEditorVisibility(self): + if self.form.editToolController.isChecked(): + self.tcEditor.controller.show() + else: + self.tcEditor.controller.hide() + def resetToolController(self, job, tc): if self.obj is not None: self.obj.ToolController = tc - combo = self.form.toolController - self.setupToolController(self.obj, combo) + self.setupToolController() - def setupToolController(self, obj, combo): + def copyToolController(self): + oldTc = self.tcEditor.obj + self.tcEditor.updateToolController() + tc = PathToolController.Create( + name=oldTc.Label, tool=oldTc.Tool, toolNumber=oldTc.ToolNumber + ) + job = self.obj.Proxy.getJob(self.obj) + job.Proxy.addToolController(tc) + + tc.HorizFeed = oldTc.HorizFeed + tc.VertFeed = oldTc.VertFeed + tc.HorizRapid = oldTc.HorizRapid + tc.VertRapid = oldTc.VertRapid + tc.SpindleSpeed = oldTc.SpindleSpeed + tc.SpindleDir = oldTc.SpindleDir + for attr, expr in oldTc.ExpressionEngine: + tc.setExpression(attr, expr) + + self.obj.ToolController = tc + self.setupToolController() + + def tcEditorChanged(self): + self.setDirty() + self.resetTCCombo() + + def resetTCCombo(self): + controllers = PathUtils.getToolControllers(self.obj) + + if self.obj.ToolController is None: + self.obj.ToolController = PathUtils.findToolController(self.obj, self.obj.Proxy) + if len(controllers) > 0 and not self.obj.Proxy.isToolSupported( + self.obj, self.obj.ToolController.Tool + ): + self.obj.ToolController = controllers[0] + + tcName = self.obj.ToolController.Label if self.obj.ToolController else "" + labels = [c.Label for c in controllers] + labels.append(FreeCAD.Qt.translate("CAM_Operation", "Copy {0}…").format(tcName)) + labels.append(FreeCAD.Qt.translate("CAM_Operation", "New tool controller…")) + self.combo.blockSignals(True) + self.combo.clear() + self.combo.addItems(labels) + self.combo.insertSeparator(len(controllers)) + self.combo.blockSignals(False) + + if self.obj.ToolController is not None: + self.selectInComboBox(self.obj.ToolController.Label, self.combo) + + def setupToolController(self, obj=None, combo=None): """setupToolController(obj, combo) ... helper function to setup obj's ToolController in the given combo box.""" - controllers = PathUtils.getToolControllers(self.obj) - labels = [c.Label for c in controllers] - combo.blockSignals(True) - combo.clear() - combo.addItems(labels) - combo.blockSignals(False) + obj = obj or self.obj + combo = combo or self.combo + self.obj, self.combo = obj, combo - if obj.ToolController is None: - obj.ToolController = PathUtils.findToolController(obj, obj.Proxy) - if obj.ToolController is not None: - self.selectInComboBox(obj.ToolController.Label, combo) + self.resetTCCombo() + + if hasattr(self.form, "editToolController"): + layout = self.form.editToolController.parent().layout() + oldEditor = self.tcEditor + + # Count the number of times the tool controller is used in other operations + # If it is used in other operations, we will offer the "copy tool controller" button + tcCount = 0 + for job in PathUtils.GetJobs(): + for op in job.Operations.Group: + if op == self.obj: + continue + elif hasattr(op, "ToolController") and op.ToolController == obj.ToolController: + tcCount += 1 + + self.tcEditor = Path.Tool.Gui.Controller.ToolControllerEditor( + obj.ToolController, + False, + self.tcEditorChanged, + True, + True, + ) + self.tcEditor.setupUi() + + labelStr = FreeCAD.Qt.translate( + "CAM_Operation", "This tool controller is used by {0} other operations." + ).format(tcCount) + self.tcEditor.controller.tcOperationCountLabel.setText(labelStr) + + # add to layout -- requires a grid layout + if isinstance(layout, QtWidgets.QGridLayout): + layout.addWidget( + self.tcEditor.controller, layout.rowCount(), 0, 1, layout.columnCount() + ) + else: + Path.Log.error( + "Panel uses a layout incompatible with editing tool controllers. Report a bug: it should be a QGridLayout" + ) + + self.updateToolControllerEditorVisibility() + self.tcEditor.updateUi() + self.form.editToolController.checkStateChanged.connect( + self.updateToolControllerEditorVisibility + ) + + if oldEditor: + oldEditor.updateToolController() + oldEditor.controller.hide() + layout.removeWidget(oldEditor.controller) def updateToolController(self, obj, combo): """updateToolController(obj, combo) ... @@ -418,6 +537,8 @@ class TaskPanelPage(object): tc = PathUtils.findToolController(obj, obj.Proxy, combo.currentText()) if obj.ToolController != tc: obj.ToolController = tc + if self.tcEditor: + self.tcEditor.updateToolController() def setupCoolant(self, obj, combo): """setupCoolant(obj, combo) ... diff --git a/src/Mod/CAM/Path/Op/Probe.py b/src/Mod/CAM/Path/Op/Probe.py index d1523f4473..b8ae6edcea 100644 --- a/src/Mod/CAM/Path/Op/Probe.py +++ b/src/Mod/CAM/Path/Op/Probe.py @@ -134,7 +134,7 @@ class ObjectProbing(PathOp.ObjectOp): def isToolSupported(self, obj, tool): """Probe operation requires a probe tool""" - support = hasattr(tool, "ShapeName") and (tool.ShapeName == "probe") + support = PathUtils.getToolShapeName(tool) == "probe" Path.Log.track(tool.Label, support) return support diff --git a/src/Mod/CAM/Path/Tool/Gui/Controller.py b/src/Mod/CAM/Path/Tool/Gui/Controller.py index bc40b82154..f5712e1c71 100644 --- a/src/Mod/CAM/Path/Tool/Gui/Controller.py +++ b/src/Mod/CAM/Path/Tool/Gui/Controller.py @@ -188,80 +188,104 @@ class CommandPathToolController(object): FreeCAD.ActiveDocument.recompute() +class BlockScrollWheel(QtCore.QObject): + def eventFilter(self, obj, event): + if event.type() == QtCore.QEvent.Type.Wheel: + if not obj.hasFocus(): + return True + return super().eventFilter(obj, event) + + class ToolControllerEditor(object): - def __init__(self, obj, asDialog): + + def __init__( + self, obj, asDialog, notifyChanged=None, showCountLabel=False, disableToolNumber=False + ): + self.notifyChanged = notifyChanged self.form = FreeCADGui.PySideUic.loadUi(":/panels/DlgToolControllerEdit.ui") + self.controller = FreeCADGui.PySideUic.loadUi(":/panels/ToolControllerEdit.ui") + self.form.tc_layout.addWidget(self.controller) if not asDialog: self.form.buttonBox.hide() + if not showCountLabel: + self.controller.tcOperationCountLabel.hide() self.obj = obj comboToPropertyMap = [("spindleDirection", "SpindleDir")] enumTups = PathToolController.ToolController.propertyEnumerations(dataType="raw") - PathGuiUtil.populateCombobox(self.form, enumTups, comboToPropertyMap) - self.vertFeed = PathGuiUtil.QuantitySpinBox(self.form.vertFeed, obj, "VertFeed") - self.horizFeed = PathGuiUtil.QuantitySpinBox(self.form.horizFeed, obj, "HorizFeed") - self.vertRapid = PathGuiUtil.QuantitySpinBox(self.form.vertRapid, obj, "VertRapid") - self.horizRapid = PathGuiUtil.QuantitySpinBox(self.form.horizRapid, obj, "HorizRapid") + PathGuiUtil.populateCombobox(self.controller, enumTups, comboToPropertyMap) + self.vertFeed = PathGuiUtil.QuantitySpinBox(self.controller.vertFeed, obj, "VertFeed") + self.horizFeed = PathGuiUtil.QuantitySpinBox(self.controller.horizFeed, obj, "HorizFeed") + self.vertRapid = PathGuiUtil.QuantitySpinBox(self.controller.vertRapid, obj, "VertRapid") + self.horizRapid = PathGuiUtil.QuantitySpinBox(self.controller.horizRapid, obj, "HorizRapid") + + self.blockScrollWheel = BlockScrollWheel() + self.controller.tcNumber.installEventFilter(self.blockScrollWheel) + self.controller.spindleDirection.installEventFilter(self.blockScrollWheel) + self.controller.tcNumber.setReadOnly(disableToolNumber) self.editor = None - self.form.toolBox.widget(1).hide() - self.form.toolBox.removeItem(1) def selectInComboBox(self, name, combo): """selectInComboBox(name, combo) ... helper function to select a specific value in a combo box.""" - blocker = QtCore.QSignalBlocker(combo) - index = combo.currentIndex() # Save initial index + with QtCore.QSignalBlocker(combo): + index = combo.currentIndex() # Save initial index - # Search using currentData and return if found - newindex = combo.findData(name) - if newindex >= 0: - combo.setCurrentIndex(newindex) - return + # Search using currentData and return if found + newindex = combo.findData(name) + if newindex >= 0: + combo.setCurrentIndex(newindex) + return - # if not found, search using current text - newindex = combo.findText(name, QtCore.Qt.MatchFixedString) - if newindex >= 0: - combo.setCurrentIndex(newindex) - return + # if not found, search using current text + newindex = combo.findText(name, QtCore.Qt.MatchFixedString) + if newindex >= 0: + combo.setCurrentIndex(newindex) + return - # not found, return unchanged - combo.setCurrentIndex(index) + # not found, return unchanged + combo.setCurrentIndex(index) return def updateUi(self): tc = self.obj - self.form.tcName.setText(tc.Label) - self.form.tcNumber.setValue(tc.ToolNumber) - self.horizFeed.updateWidget() - self.horizRapid.updateWidget() - self.vertFeed.updateWidget() - self.vertRapid.updateWidget() - self.form.spindleSpeed.setValue(tc.SpindleSpeed) - self.selectInComboBox(tc.SpindleDir, self.form.spindleDirection) + with ( + QtCore.QSignalBlocker(self.controller.tcName), + QtCore.QSignalBlocker(self.controller.tcNumber), + QtCore.QSignalBlocker(self.horizFeed.widget), + QtCore.QSignalBlocker(self.horizRapid.widget), + QtCore.QSignalBlocker(self.vertFeed.widget), + QtCore.QSignalBlocker(self.vertRapid.widget), + QtCore.QSignalBlocker(self.controller.spindleSpeed), + QtCore.QSignalBlocker(self.controller.spindleDirection), + ): + self.controller.tcName.setText(tc.Label) + self.controller.tcNumber.setValue(tc.ToolNumber) + self.horizFeed.updateWidget() + self.horizRapid.updateWidget() + self.vertFeed.updateWidget() + self.vertRapid.updateWidget() + self.controller.spindleSpeed.setValue(tc.SpindleSpeed) - # index = self.form.spindleDirection.findText( - # tc.SpindleDir, QtCore.Qt.MatchFixedString - # ) - # if index >= 0: - # self.form.spindleDirection.setCurrentIndex(index) + self.selectInComboBox(tc.SpindleDir, self.controller.spindleDirection) - if self.editor: - self.editor.updateUI() + if self.editor: + self.editor.updateUI() def updateToolController(self): tc = self.obj try: - tc.Label = self.form.tcName.text() - tc.ToolNumber = self.form.tcNumber.value() + tc.Label = self.controller.tcName.text() + tc.ToolNumber = self.controller.tcNumber.value() self.horizFeed.updateProperty() self.vertFeed.updateProperty() self.horizRapid.updateProperty() self.vertRapid.updateProperty() - tc.SpindleSpeed = self.form.spindleSpeed.value() - tc.SpindleDir = self.form.spindleDirection.currentData() + tc.SpindleSpeed = self.controller.spindleSpeed.value() + tc.SpindleDir = self.controller.spindleDirection.currentData() if self.editor: self.editor.updateTool() @@ -270,23 +294,29 @@ class ToolControllerEditor(object): except Exception as e: Path.Log.error("Error updating TC: {}".format(e)) - def refresh(self): + def changed(self): self.form.blockSignals(True) + self.controller.blockSignals(True) self.updateToolController() self.updateUi() + self.controller.blockSignals(False) self.form.blockSignals(False) + if self.notifyChanged: + self.notifyChanged() + def setupUi(self): if self.editor: self.editor.setupUI() - self.form.tcName.editingFinished.connect(self.refresh) - self.form.horizFeed.editingFinished.connect(self.refresh) - self.form.vertFeed.editingFinished.connect(self.refresh) - self.form.horizRapid.editingFinished.connect(self.refresh) - self.form.vertRapid.editingFinished.connect(self.refresh) - self.form.spindleSpeed.editingFinished.connect(self.refresh) - self.form.spindleDirection.currentIndexChanged.connect(self.refresh) + self.controller.tcName.textChanged.connect(self.changed) + self.controller.tcNumber.editingFinished.connect(self.changed) + self.vertFeed.widget.textChanged.connect(self.changed) + self.horizFeed.widget.textChanged.connect(self.changed) + self.vertRapid.widget.textChanged.connect(self.changed) + self.horizRapid.widget.textChanged.connect(self.changed) + self.controller.spindleSpeed.editingFinished.connect(self.changed) + self.controller.spindleDirection.currentIndexChanged.connect(self.changed) class TaskPanel: @@ -359,6 +389,9 @@ class DlgToolControllerEdit: Path.Log.info("revert") self.obj.Proxy.setFromTemplate(self.obj, restoreTC) rc = True + else: + self.editor.updateToolController() + self.obj.Proxy.execute(self.obj) return rc diff --git a/src/Mod/CAM/Path/Tool/library/ui/cmd.py b/src/Mod/CAM/Path/Tool/library/ui/cmd.py index a1f9f94f99..c1dc9d0798 100644 --- a/src/Mod/CAM/Path/Tool/library/ui/cmd.py +++ b/src/Mod/CAM/Path/Tool/library/ui/cmd.py @@ -48,8 +48,10 @@ class CommandToolBitLibraryDockOpen: def GetResources(self): return { "Pixmap": "CAM_ToolTable", - "MenuText": QT_TRANSLATE_NOOP("CAM_ToolBitDock", "Toolbit Dock"), - "ToolTip": QT_TRANSLATE_NOOP("CAM_ToolBitDock", "Toggles the toolbit dock"), + "MenuText": QT_TRANSLATE_NOOP("CAM_ToolBitSelection", "Add toolbit…"), + "ToolTip": QT_TRANSLATE_NOOP( + "CAM_ToolBitSelection", "Opens the toolbit selection dialog" + ), "Accel": "P, T", "CmdType": "ForEdit", } diff --git a/src/Mod/CAM/Path/Tool/library/ui/dock.py b/src/Mod/CAM/Path/Tool/library/ui/dock.py index 2667af7a64..6606bfeb44 100644 --- a/src/Mod/CAM/Path/Tool/library/ui/dock.py +++ b/src/Mod/CAM/Path/Tool/library/ui/dock.py @@ -28,7 +28,7 @@ import FreeCADGui import Path import Path.Tool.Gui.Controller as PathToolControllerGui import PathScripts.PathUtilsGui as PathUtilsGui -from PySide import QtGui, QtCore +from PySide import QtGui, QtCore, QtWidgets from functools import partial from typing import List, Tuple from ...camassets import cam_assets, ensure_assets_initialized @@ -50,12 +50,20 @@ translate = FreeCAD.Qt.translate class ToolBitLibraryDock(object): """Controller for displaying a library and creating ToolControllers""" - def __init__(self): + def __init__(self, defaultJob=None, autoClose=False): ensure_assets_initialized(cam_assets) # Create the main form widget directly - self.form = QtGui.QDockWidget() + self.defaultJob = defaultJob + self.autoClose = autoClose + self.form = QtWidgets.QDialog() self.form.setObjectName("ToolSelector") self.form.setWindowTitle(translate("CAM_ToolBit", "Tool Selector")) + self.form.setMinimumSize(600, 400) + self.form.resize(800, 600) + self.form.adjustSize() + self.form_layout = QtGui.QVBoxLayout(self.form) + self.form_layout.setContentsMargins(4, 4, 4, 4) + self.form_layout.setSpacing(4) # Create the browser widget self.browser_widget = LibraryBrowserWidget(asset_manager=cam_assets) @@ -69,6 +77,8 @@ class ToolBitLibraryDock(object): # Create a main widget and layout for the dock main_widget = QtGui.QWidget() main_layout = QtGui.QVBoxLayout(main_widget) + main_layout.setContentsMargins(4, 4, 4, 4) + main_layout.setSpacing(4) # Add the browser widget to the layout main_layout.addWidget(self.browser_widget) @@ -88,7 +98,7 @@ class ToolBitLibraryDock(object): main_layout.addLayout(button_layout) # Set the main widget as the dock's widget - self.form.setWidget(main_widget) + self.form.layout().addWidget(main_widget) # Connect signals from the browser widget and buttons self.browser_widget.toolSelected.connect(self._update_state) @@ -152,11 +162,12 @@ class ToolBitLibraryDock(object): translate("CAM_ToolBit", "Please create a Job first."), ) return - elif len(jobs) == 1: - job = jobs[0] + elif self.defaultJob or len(jobs) == 1: + job = self.defaultJob or jobs[0] else: userinput = PathUtilsGui.PathUtilsUserInput() job = userinput.chooseJob(jobs) + self.defaultJob = job if job is None: # user may have canceled return @@ -169,21 +180,9 @@ class ToolBitLibraryDock(object): job.Proxy.addToolController(tc) FreeCAD.ActiveDocument.recompute() + if self.autoClose: + self.form.accept() + def open(self, path=None): """load library stored in path and bring up ui""" - docs = FreeCADGui.getMainWindow().findChildren(QtGui.QDockWidget) - for doc in docs: - if doc.objectName() == "ToolSelector": - if doc.isVisible(): - doc.deleteLater() - return - else: - doc.setVisible(True) - return - - mw = FreeCADGui.getMainWindow() - mw.addDockWidget( - QtCore.Qt.RightDockWidgetArea, - self.form, - QtCore.Qt.Orientation.Vertical, - ) + self.form.exec_() diff --git a/src/Mod/CAM/PathScripts/PathUtils.py b/src/Mod/CAM/PathScripts/PathUtils.py index 10a846456c..367d03c63e 100644 --- a/src/Mod/CAM/PathScripts/PathUtils.py +++ b/src/Mod/CAM/PathScripts/PathUtils.py @@ -357,6 +357,14 @@ def getToolControllers(obj, proxy=None): return [] +def getToolShapeName(tool): + if hasattr(tool, "ShapeName"): + return tool.ShapeName.lower() + if hasattr(tool, "ShapeType"): + return tool.ShapeType.lower() + return "" + + def findToolController(obj, proxy, name=None): """returns a tool controller with a given name. If no name is specified, returns the first controller.