From c0cfbc291161d5bb0b4194da1efdcdd8aebd0e7a Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Mon, 4 Jun 2018 23:00:18 -0700 Subject: [PATCH] Consolidated path tool editor and added customized support for endmill, drill and v-bit. --- src/Mod/Path/App/Tooltable.cpp | 4 +- src/Mod/Path/App/TooltablePyImp.cpp | 2 +- src/Mod/Path/CMakeLists.txt | 16 + src/Mod/Path/Gui/Resources/Path.qrc | 3 +- .../Resources/panels/DlgToolControllerEdit.ui | 416 ++---------- .../Path/Gui/Resources/panels/DlgToolEdit.ui | 85 +++ src/Mod/Path/Gui/Resources/panels/ToolEdit.ui | 277 -------- .../Path/Gui/Resources/panels/ToolEditor.ui | 317 ++++++++++ src/Mod/Path/Images/Tools/drill.svg | 280 ++++++++ src/Mod/Path/Images/Tools/endmill.svg | 529 ++++++++++++++++ src/Mod/Path/Images/Tools/v-bit.svg | 596 ++++++++++++++++++ .../Path/PathScripts/PathToolController.py | 64 +- src/Mod/Path/PathScripts/PathToolEdit.py | 288 +++++++++ .../PathScripts/PathToolLibraryManager.py | 80 +-- 14 files changed, 2186 insertions(+), 771 deletions(-) create mode 100644 src/Mod/Path/Gui/Resources/panels/DlgToolEdit.ui delete mode 100644 src/Mod/Path/Gui/Resources/panels/ToolEdit.ui create mode 100644 src/Mod/Path/Gui/Resources/panels/ToolEditor.ui create mode 100644 src/Mod/Path/Images/Tools/drill.svg create mode 100644 src/Mod/Path/Images/Tools/endmill.svg create mode 100644 src/Mod/Path/Images/Tools/v-bit.svg create mode 100644 src/Mod/Path/PathScripts/PathToolEdit.py diff --git a/src/Mod/Path/App/Tooltable.cpp b/src/Mod/Path/App/Tooltable.cpp index b7774d0609..53a72d5d53 100644 --- a/src/Mod/Path/App/Tooltable.cpp +++ b/src/Mod/Path/App/Tooltable.cpp @@ -65,7 +65,7 @@ Tool::Tool() LengthOffset = 0; FlatRadius = 0; CornerRadius = 0; - CuttingEdgeAngle = 0; + CuttingEdgeAngle = 180; CuttingEdgeHeight = 0; } @@ -103,7 +103,7 @@ void Tool::Restore(XMLReader &reader) LengthOffset = reader.hasAttribute("length") ? (double) reader.getAttributeAsFloat("length") : 0.0; FlatRadius = reader.hasAttribute("flat") ? (double) reader.getAttributeAsFloat("flat") : 0.0; CornerRadius = reader.hasAttribute("corner") ? (double) reader.getAttributeAsFloat("corner") : 0.0; - CuttingEdgeAngle = reader.hasAttribute("angle") ? (double) reader.getAttributeAsFloat("angle") : 0.0; + CuttingEdgeAngle = reader.hasAttribute("angle") ? (double) reader.getAttributeAsFloat("angle") : 180.0; CuttingEdgeHeight = reader.hasAttribute("height") ? (double) reader.getAttributeAsFloat("height") : 0.0; std::string type = reader.hasAttribute("type") ? reader.getAttribute("type") : ""; std::string mat = reader.hasAttribute("mat") ? reader.getAttribute("mat") : ""; diff --git a/src/Mod/Path/App/TooltablePyImp.cpp b/src/Mod/Path/App/TooltablePyImp.cpp index 17cb3fe59e..756ef0a23a 100644 --- a/src/Mod/Path/App/TooltablePyImp.cpp +++ b/src/Mod/Path/App/TooltablePyImp.cpp @@ -104,7 +104,7 @@ int ToolPy::PyInit(PyObject* args, PyObject* kwd) getToolPtr()->LengthOffset = len ? PyFloat_AsDouble(len) : 0.0; getToolPtr()->FlatRadius = fla ? PyFloat_AsDouble(fla) : 0.0; getToolPtr()->CornerRadius = cor ? PyFloat_AsDouble(cor) : 0.0; - getToolPtr()->CuttingEdgeAngle = ang ? PyFloat_AsDouble(ang) : 0.0; + getToolPtr()->CuttingEdgeAngle = ang ? PyFloat_AsDouble(ang) : 180.0; getToolPtr()->CuttingEdgeHeight = hei ? PyFloat_AsDouble(hei) : 0.0; return 0; diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index 3f17f149df..6c8890b9c6 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -85,6 +85,7 @@ SET(PathScripts_SRCS PathScripts/PathSurface.py PathScripts/PathSurfaceGui.py PathScripts/PathToolController.py + PathScripts/PathToolEdit.py PathScripts/PathToolLibraryManager.py PathScripts/PathUtil.py PathScripts/PathUtils.py @@ -131,9 +132,16 @@ SET(PathTests_SRCS PathTests/TestPathUtil.py ) +SET(Path_Images + Images/Tools/drill.svg + Images/Tools/endmill.svg + Images/Tools/v-bit.svg +) + SET(all_files ${PathScripts_SRCS} ${PathScripts_post_SRCS} + ${Path_Images} ) ADD_CUSTOM_TARGET(PathScripts ALL @@ -172,3 +180,11 @@ INSTALL( DESTINATION Mod/Path/PathScripts/post ) + +INSTALL( + FILES + ${Path_Images} + DESTINATION + Mod/Path/Images +) + diff --git a/src/Mod/Path/Gui/Resources/Path.qrc b/src/Mod/Path/Gui/Resources/Path.qrc index 59af5b9efe..0c16b73f9e 100644 --- a/src/Mod/Path/Gui/Resources/Path.qrc +++ b/src/Mod/Path/Gui/Resources/Path.qrc @@ -66,6 +66,7 @@ panels/DlgSelectPostProcessor.ui panels/DlgToolControllerEdit.ui panels/DlgToolCopy.ui + panels/DlgToolEdit.ui panels/DlgTCChooser.ui panels/DogboneEdit.ui panels/HoldingTagsEdit.ui @@ -83,7 +84,7 @@ panels/PageOpSurfaceEdit.ui panels/PathEdit.ui panels/PointEdit.ui - panels/ToolEdit.ui + panels/ToolEditor.ui panels/ToolLibraryEditor.ui panels/TaskPathSimulator.ui preferences/PathDressupHoldingTags.ui diff --git a/src/Mod/Path/Gui/Resources/panels/DlgToolControllerEdit.ui b/src/Mod/Path/Gui/Resources/panels/DlgToolControllerEdit.ui index f0b836c3af..232354fec8 100644 --- a/src/Mod/Path/Gui/Resources/panels/DlgToolControllerEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/DlgToolControllerEdit.ui @@ -6,8 +6,8 @@ 0 0 - 386 - 554 + 561 + 739 @@ -21,8 +21,8 @@ 0 0 - 368 - 445 + 543 + 593 @@ -75,15 +75,15 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - mm/s - 0.000000000000000 9999999.000000000000000 + + mm/s + @@ -104,15 +104,15 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - mm/s - 0.000000000000000 9999999.000000000000000 + + mm/s + @@ -133,15 +133,15 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - mm/s - 0.000000000000000 9999999.000000000000000 + + mm/s + @@ -162,15 +162,15 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - mm/s - 0.000000000000000 9999999.000000000000000 + + mm/s + @@ -232,8 +232,8 @@ 0 0 - 368 - 445 + 543 + 593 @@ -241,355 +241,36 @@ - - - Tool Properties + + + + 0 + 0 + - - - QFormLayout::AllNonFixedFieldsGrow + + + 0 + + + 0 - - - - Name - - - - - - - - 0 - 0 - - - - 50 - - - Display Name - - - - - - - Type - - - - - - - 6 - - - - Drill - - - - - CenterDrill - - - - - CounterSink - - - - - CounterBore - - - - - Reamer - - - - - Tap - - - - - EndMill - - - - - SlotCutter - - - - - BallEndMill - - - - - ChamferMill - - - - - CornerRound - - - - - Engraver - - - - - - - - Material - - - - - - - - HighSpeedSteel - - - - - HighCarbonSteel - - - - - CastAlloy - - - - - Carbide - - - - - Ceramics - - - - - Diamond - - - - - Sialon - - - - - - - - Diameter - - - - - - - Length Offset - - - - - - - Flat Radius - - - - - - - Corner Radius - - - - - - - Point/Tip Angle - - - - - - - Cutting Edge Height - - - - - - - - 0 - 0 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0 mm - - - mm - - - 0.000000000000000 - - - 100.000000000000000 - - - 0.125000000000000 - - - - - - - - 0 - 0 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0 mm - - - mm - - - 0.000000000000000 - - - 100.000000000000000 - - - - - - - - 0 - 0 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0 mm - - - mm - - - 0.000000000000000 - - - 100.000000000000000 - - - - - - - - 0 - 0 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0 mm - - - mm - - - 0.000000000000000 - - - 100.000000000000000 - - - - - - - - 0 - 0 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0 mm - - - mm - - - 0.000000000000000 - - - 100.000000000000000 - - - - - - - - 0 - 0 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - ° - - - 180 ° - - - 0.000000000000000 - - - 180.000000000000000 - - - + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -625,7 +306,7 @@ Gui::QuantitySpinBox - QWidget + QDoubleSpinBox
Gui/QuantitySpinBox.h
@@ -639,15 +320,6 @@ spindleSpeed spindleDirection buttonBox - toolName - toolType - toolMaterial - toolDiameter - toolLengthOffset - toolFlatRadius - toolCornerRadius - toolCuttingEdgeAngle - toolCuttingEdgeHeight diff --git a/src/Mod/Path/Gui/Resources/panels/DlgToolEdit.ui b/src/Mod/Path/Gui/Resources/panels/DlgToolEdit.ui new file mode 100644 index 0000000000..ac0eae95c2 --- /dev/null +++ b/src/Mod/Path/Gui/Resources/panels/DlgToolEdit.ui @@ -0,0 +1,85 @@ + + + Dialog + + + + 0 + 0 + 600 + 584 + + + + Tool Editor + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + buttonBox + + + + + buttonBox + accepted() + Dialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Dialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/Mod/Path/Gui/Resources/panels/ToolEdit.ui b/src/Mod/Path/Gui/Resources/panels/ToolEdit.ui deleted file mode 100644 index b5ffde3a92..0000000000 --- a/src/Mod/Path/Gui/Resources/panels/ToolEdit.ui +++ /dev/null @@ -1,277 +0,0 @@ - - - Dialog - - - - 0 - 0 - 422 - 498 - - - - Dialog - - - - - - Tool Properties - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - Name - - - - - - - 50 - - - Display Name - - - - - - - Type - - - - - - - 0 - - - - - - - Material - - - - - - - - - - Diameter - - - - - - - Length Offset - - - - - - - Flat Radius - - - - - - - Corner Radius - - - - - - - Point/Tip Angle - - - - - - - Cutting Edge Height - - - - - - - 0 mm - - - 0.125000000000000 - - - 100.000000000000000 - - - 0.000000000000000 - - - mm - - - - - - - 0 mm - - - 100.000000000000000 - - - 0.000000000000000 - - - mm - - - - - - - 0 mm - - - 100.000000000000000 - - - 0.000000000000000 - - - mm - - - - - - - 0 mm - - - 100.000000000000000 - - - 0.000000000000000 - - - mm - - - - - - - 0 mm - - - 100.000000000000000 - - - 0.000000000000000 - - - mm - - - - - - - 180 ° - - - 180.000000000000000 - - - 0.000000000000000 - - - ° - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - Gui::InputField - QLineEdit -
Gui/InputField.h
-
-
- - NameField - TypeField - MaterialField - DiameterField - LengthOffsetField - FlatRadiusField - CornerRadiusField - CuttingEdgeAngleField - CuttingEdgeHeightField - buttonBox - - - - - buttonBox - accepted() - Dialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Dialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - -
diff --git a/src/Mod/Path/Gui/Resources/panels/ToolEditor.ui b/src/Mod/Path/Gui/Resources/panels/ToolEditor.ui new file mode 100644 index 0000000000..3b73c884c7 --- /dev/null +++ b/src/Mod/Path/Gui/Resources/panels/ToolEditor.ui @@ -0,0 +1,317 @@ + + + Form + + + + 0 + 0 + 560 + 766 + + + + Form + + + + + + Tool + + + + + + Name + + + + + + + 50 + + + Display Name + + + + + + + Type + + + + + + + -1 + + + + + + + Material + + + + + + + + + + Length Offset + + + + + + + 0.00 + + + mm + + + + + + + + + + Tool Parameter + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Diameter + + + + + + + Flat Radius + + + + + + + Corner Radius + + + + + + + Point/Tip Angle + + + + + + + Cutting Edge Height + + + + + + + 0.00 + + + mm + + + + + + + 0.00 + + + mm + + + + + + + 0.00 + + + mm + + + + + + + 180° + + + ° + + + + + + + 0.00 + + + mm + + + + + + + + + + Tool Parameter + + + + + + + + + D = + + + + + + + d = + + + + + + + H = + + + + + + + α = + + + + + + + false + + + S = + + + + + + + 0.00 + + + mm + + + + + + + 0.00 + + + mm + + + + + + + 0.00 + + + mm + + + + + + + 180° + + + ° + + + + + + + false + + + 0.00 + + + mm + + + + + + + + + + + 0 + 0 + + + + Image + + + true + + + Qt::AlignCenter + + + + + + + + + + + Gui::InputField + QLineEdit +
Gui/InputField.h
+
+
+ + +
diff --git a/src/Mod/Path/Images/Tools/drill.svg b/src/Mod/Path/Images/Tools/drill.svg new file mode 100644 index 0000000000..1eb08e786e --- /dev/null +++ b/src/Mod/Path/Images/Tools/drill.svg @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + H + D + α + + + diff --git a/src/Mod/Path/Images/Tools/endmill.svg b/src/Mod/Path/Images/Tools/endmill.svg new file mode 100644 index 0000000000..dbf3e746fc --- /dev/null +++ b/src/Mod/Path/Images/Tools/endmill.svg @@ -0,0 +1,529 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + S + D + H + + + + + + + diff --git a/src/Mod/Path/Images/Tools/v-bit.svg b/src/Mod/Path/Images/Tools/v-bit.svg new file mode 100644 index 0000000000..f3ef915529 --- /dev/null +++ b/src/Mod/Path/Images/Tools/v-bit.svg @@ -0,0 +1,596 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + S + D + + α + d + + + + + + + + + H + + diff --git a/src/Mod/Path/PathScripts/PathToolController.py b/src/Mod/Path/PathScripts/PathToolController.py index 3e4f4fd3b8..ccb54ca243 100644 --- a/src/Mod/Path/PathScripts/PathToolController.py +++ b/src/Mod/Path/PathScripts/PathToolController.py @@ -28,6 +28,7 @@ import Part import Path import PathScripts import PathScripts.PathLog as PathLog +import PathScripts.PathToolEdit as PathToolEdit import PathScripts.PathUtil as PathUtil from FreeCAD import Units @@ -280,37 +281,7 @@ class ToolControllerEditor: self.vertRapid = PathGui.QuantitySpinBox(self.form.vertRapid, obj, 'VertRapid') self.horizRapid = PathGui.QuantitySpinBox(self.form.horizRapid, obj, 'HorizRapid') - self.toolDiameter = PathGui.QuantitySpinBox(self.form.toolDiameter, obj, 'Tool.Diameter') - self.toolLengthOffset = PathGui.QuantitySpinBox(self.form.toolLengthOffset, obj, 'Tool.LengthOffset') - self.toolFlatRadius = PathGui.QuantitySpinBox(self.form.toolFlatRadius, obj, 'Tool.FlatRadius') - self.toolCornerRadius = PathGui.QuantitySpinBox(self.form.toolCornerRadius, obj, 'Tool.CornerRadius') - self.toolCuttingEdgeAngle = PathGui.QuantitySpinBox(self.form.toolCuttingEdgeAngle, obj, 'Tool.CuttingEdgeAngle') - self.toolCuttingEdgeHeight = PathGui.QuantitySpinBox(self.form.toolCuttingEdgeHeight, obj, 'Tool.CuttingEdgeHeight') - - def getType(self, tooltype): - "gets a combobox index number for a given type or viceversa" - toolslist = ["Drill", "CenterDrill", "CounterSink", "CounterBore", - "Reamer", "Tap", "EndMill", "SlotCutter", "BallEndMill", - "ChamferMill", "CornerRound", "Engraver"] - if isinstance(tooltype, str): - if tooltype in toolslist: - return toolslist.index(tooltype) - else: - return 0 - else: - return toolslist[tooltype] - - def getMaterial(self, material): - "gets a combobox index number for a given material or viceversa" - matslist = ["HighSpeedSteel", "HighCarbonToolSteel", "CastAlloy", - "Carbide", "Ceramics", "Diamond", "Sialon"] - if isinstance(material, str): - if material in matslist: - return matslist.index(material) - else: - return 0 - else: - return matslist[material] + self.editor = PathToolEdit.ToolEditor(obj.Tool, self.form.toolEditor) def updateUi(self): tc = self.obj @@ -325,15 +296,7 @@ class ToolControllerEditor: if index >= 0: self.form.spindleDirection.setCurrentIndex(index) - self.form.toolName.setText(tc.Tool.Name) - self.form.toolType.setCurrentIndex(self.getType(tc.Tool.ToolType)) - self.form.toolMaterial.setCurrentIndex(self.getMaterial(tc.Tool.Material)) - self.toolDiameter.updateSpinBox() - self.toolLengthOffset.updateSpinBox() - self.toolFlatRadius.updateSpinBox() - self.toolCornerRadius.updateSpinBox() - self.toolCuttingEdgeAngle.updateSpinBox() - self.toolCuttingEdgeHeight.updateSpinBox() + self.editor.updateUI() def updateToolController(self): tc = self.obj @@ -347,15 +310,9 @@ class ToolControllerEditor: tc.SpindleSpeed = self.form.spindleSpeed.value() tc.SpindleDir = self.form.spindleDirection.currentText() - tc.Tool.Name = str(self.form.toolName.text()) - tc.Tool.ToolType = self.getType(self.form.toolType.currentIndex()) - tc.Tool.Material = self.getMaterial(self.form.toolMaterial.currentIndex()) - self.toolDiameter.updateProperty() - self.toolLengthOffset.updateProperty() - self.toolFlatRadius.updateProperty() - self.toolCornerRadius.updateProperty() - self.toolCuttingEdgeAngle.updateProperty() - self.toolCuttingEdgeHeight.updateProperty() + self.editor.updateTool() + tc.Tool = self.editor.tool + except Exception as e: PathLog.error(translate("PathToolController", "Error updating TC: %s") % e) @@ -367,19 +324,14 @@ class ToolControllerEditor: self.form.blockSignals(False) def setupUi(self): + 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.toolName.editingFinished.connect(self.refresh) - self.form.toolDiameter.editingFinished.connect(self.refresh) - self.form.toolLengthOffset.editingFinished.connect(self.refresh) - self.form.toolFlatRadius.editingFinished.connect(self.refresh) - self.form.toolCornerRadius.editingFinished.connect(self.refresh) - self.form.toolCuttingEdgeAngle.editingFinished.connect(self.refresh) - self.form.toolCuttingEdgeHeight.editingFinished.connect(self.refresh) class TaskPanel: diff --git a/src/Mod/Path/PathScripts/PathToolEdit.py b/src/Mod/Path/PathScripts/PathToolEdit.py new file mode 100644 index 0000000000..6ca60bd907 --- /dev/null +++ b/src/Mod/Path/PathScripts/PathToolEdit.py @@ -0,0 +1,288 @@ +# -*- coding: utf-8 -*- + +# *************************************************************************** +# * * +# * Copyright (c) 2018 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.PathGui as PathGui +import PathScripts.PathLog as PathLog +import math + +from PySide import QtCore, QtGui + +PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) +#PathLog.trackModule(PathLog.thisModule()) + +class ToolEditorDefault: + '''Generic Tool parameter editor for all Tools that don't have a customized edit function. + Let's the user enter the raw internal data. Not the best approach but this is the starting point.''' + def __init__(self, editor): + self.editor = editor + self.form = editor.form + + def setupUI(self): + self.form.paramImage.hide() + self.form.paramGeneric.show() + + def updateUI(self): + self.form.toolDiameter.setText(FreeCAD.Units.Quantity(self.editor.tool.Diameter, FreeCAD.Units.Length).UserString) + self.form.toolFlatRadius.setText(FreeCAD.Units.Quantity(self.editor.tool.FlatRadius, FreeCAD.Units.Length).UserString) + self.form.toolCornerRadius.setText(FreeCAD.Units.Quantity(self.editor.tool.CornerRadius, FreeCAD.Units.Length).UserString) + self.form.toolCuttingEdgeHeight.setText(FreeCAD.Units.Quantity(self.editor.tool.CuttingEdgeHeight, FreeCAD.Units.Length).UserString) + self.form.toolCuttingEdgeAngle.setText(FreeCAD.Units.Quantity(self.editor.tool.CuttingEdgeAngle, FreeCAD.Units.Angle).UserString) + + def updateTool(self): + self.editor.tool.Diameter = FreeCAD.Units.parseQuantity(self.form.toolDiameter.text()) + self.editor.tool.FlatRadius = FreeCAD.Units.parseQuantity(self.form.toolFlatRadius.text()) + self.editor.tool.CornerRadius = FreeCAD.Units.parseQuantity(self.form.toolCornerRadius.text()) + self.editor.tool.CuttingEdgeAngle = FreeCAD.Units.Quantity(self.form.toolCuttingEdgeAngle.text()) + self.editor.tool.CuttingEdgeHeight = FreeCAD.Units.parseQuantity(self.form.toolCuttingEdgeHeight.text()) + +class ToolEditorImage(object): + '''Base implementation for all customized Tool parameter editors. + While not required it is simplest to subclass specific editors.''' + def __init__(self, editor, imageFile, hide='', disable=''): + self.editor = editor + self.form = editor.form + self.imagePath = "{}Mod/Path/Images/Tools/{}".format(FreeCAD.getHomePath(), imageFile) + self.image = QtGui.QPixmap(self.imagePath) + self.hide = hide + self.disable = disable + + form = editor.form + self.widgets = { + 'D' : (form.label_D, form.value_D), + 'd' : (form.label_d, form.value_d), + 'H' : (form.label_H, form.value_H), + 'a' : (form.label_a, form.value_a), + 'S' : (form.label_S, form.value_S) + } + + def setupUI(self): + PathLog.track() + self.form.paramGeneric.hide() + self.form.paramImage.show() + + for key, widgets in self.widgets.items(): + hide = key in self.hide + disable = key in self.disable + for w in widgets: + w.setHidden(hide) + w.setDisabled(disable) + if not hide and not disable: + widgets[1].editingFinished.connect(self.editor.refresh) + + self.form.image.setPixmap(self.image) + + def updateUI(self): + PathLog.track() + self.form.value_D.setText(self.quantityDiameter(True).UserString) + self.form.value_d.setText(self.quantityFlatRadius(True).UserString) + self.form.value_a.setText(self.quantityCuttingEdgeAngle(True).UserString) + self.form.value_H.setText(self.quantityCuttingEdgeHeight(True).UserString) + + def updateTool(self): + PathLog.track() + toolDefault = Path.Tool() + if 'D' in self.hide: + self.editor.tool.Diameter = toolDefault.Diameter + else: + self.editor.tool.Diameter = self.quantityDiameter(False) + + if 'd' in self.hide: + self.editor.tool.FlatRadius = toolDefault.FlatRadius + else: + self.editor.tool.FlatRadius = self.quantityFlatRadius(False) + + if 'a' in self.hide: + self.editor.tool.CuttingEdgeAngle = toolDefault.CuttingEdgeAngle + else: + self.editor.tool.CuttingEdgeAngle = self.quantityCuttingEdgeAngle(False) + + if 'H' in self.hide: + self.editor.tool.CuttingEdgeHeight = toolDefault.CuttingEdgeHeight + else: + self.editor.tool.CuttingEdgeHeight = self.quantityCuttingEdgeHeight(False) + + self.editor.tool.CornerRadius = toolDefault.CornerRadius + + def quantityDiameter(self, propertyToDisplay): + if propertyToDisplay: + return FreeCAD.Units.Quantity(self.editor.tool.Diameter, FreeCAD.Units.Length) + return FreeCAD.Units.parseQuantity(self.form.value_D.text()) + + def quantityFlatRadius(self, propertyToDisplay): + if propertyToDisplay: + return FreeCAD.Units.Quantity(self.editor.tool.FlatRadius, FreeCAD.Units.Length) * 2 + return FreeCAD.Units.parseQuantity(self.form.value_d.text()) / 2 + + def quantityCuttingEdgeAngle(self, propertyToDisplay): + if propertyToDisplay: + return FreeCAD.Units.Quantity(self.editor.tool.CuttingEdgeAngle, FreeCAD.Units.Angle) / 2 + return FreeCAD.Units.parseQuantity(self.form.value_a.text()) * 2 + + def quantityCuttingEdgeHeight(self, propertyToDisplay): + if propertyToDisplay: + return FreeCAD.Units.Quantity(self.editor.tool.CuttingEdgeHeight, FreeCAD.Units.Length) + return FreeCAD.Units.parseQuantity(self.form.value_H.text()) + +class ToolEditorEndmill(ToolEditorImage): + '''Tool parameter editor for endmills.''' + def __init__(self, editor): + super(self.__class__, self).__init__(editor, 'endmill.svg', 'da', 'S') + +class ToolEditorDrill(ToolEditorImage): + '''Tool parameter editor for drills.''' + def __init__(self, editor): + super(self.__class__, self).__init__(editor, 'drill.svg', 'dS', '') + + def quantityCuttingEdgeAngle(self, propertyToDisplay): + if propertyToDisplay: + return FreeCAD.Units.Quantity(self.editor.tool.CuttingEdgeAngle, FreeCAD.Units.Angle) + return FreeCAD.Units.parseQuantity(self.form.value_a.text()) + +class ToolEditorEngrave(ToolEditorImage): + '''Tool parameter editor for v-bits.''' + def __init__(self, editor): + super(self.__class__, self).__init__(editor, 'v-bit.svg', '', 'HS') + + def quantityCuttingEdgeHeight(self, propertyToDisplay): + PathLog.track() + dr = (self.quantityDiameter(False) - self.quantityFlatRadius(False)) / 2 + da = self.quantityCuttingEdgeAngle(False).Value + return dr / math.tan(math.radians(da) / 2) + +class ToolEditor: + '''UI and controller for editing a Tool. + The controller embeds the UI to the parentWidget which has to have a layout attached to it. + The editor maintains two Tools, self.tool and self.Tool. The former is the one being edited + and always reflects the current state. self.Tool on the other hand is the "official" Tool + which should be used externally. The state is transferred between the two with accept and + reject. + + The editor uses instances of ToolEditorDefault and ToolEditorImage to deal with the changes + of the actual parameters. For any ToolType not mapped in ToolTypeImage the editor uses + an instance of ToolEditorDefault. + ''' + + ToolTypeImage = { + 'EndMill': ToolEditorEndmill, + 'Drill': ToolEditorDrill, + 'Engraver': ToolEditorEngrave } + + def __init__(self, tool, parentWidget, parent=None): + self.Parent = parent + self.Tool = tool + self.tool = tool.copy() + self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolEditor.ui") + + self.form.setParent(parentWidget) + parentWidget.layout().addWidget(self.form) + + for tooltype in Path.Tool.getToolTypes(tool): + self.form.toolType.addItem(tooltype) + for material in Path.Tool.getToolMaterials(tool): + self.form.toolMaterial.addItem(material) + + self.setupToolType(self.tool.ToolType) + + def accept(self): + self.Tool = self.tool + + def reject(self): + self.tool = self.Tool + + def getType(self, tooltype): + "gets a combobox index number for a given type or viceversa" + toolslist = Path.Tool.getToolTypes(Path.Tool()) + if isinstance(tooltype, str): + if tooltype in toolslist: + return toolslist.index(tooltype) + else: + return 0 + return toolslist[tooltype] + + def getMaterial(self, material): + "gets a combobox index number for a given material or viceversa" + matslist = Path.Tool.getToolMaterials(Path.Tool()) + if isinstance(material, str): + if material in matslist: + return matslist.index(material) + else: + return 0 + return matslist[material] + + def updateUI(self): + PathLog.track() + self.form.toolName.setText(self.tool.Name) + self.form.toolType.setCurrentIndex(self.getType(self.tool.ToolType)) + self.form.toolMaterial.setCurrentIndex(self.getMaterial(self.tool.Material)) + self.form.toolLengthOffset.setText(FreeCAD.Units.Quantity(self.tool.LengthOffset, FreeCAD.Units.Length).UserString) + + self.editor.updateUI() + + def updateToolName(self): + self.tool.Name = str(self.form.toolName.text()) + + def updateToolType(self): + PathLog.track() + self.form.blockSignals(True) + self.tool.ToolType = self.getType(self.form.toolType.currentIndex()) + self.setupToolType(self.tool.ToolType) + self.updateUI() + self.form.blockSignals(False) + + def setupToolType(self, tt): + PathLog.track() + if 'Undefined' == tt: + tt = Path.Tool.getToolTypes(Path.Tool())[0] + if tt in self.ToolTypeImage: + self.editor = self.ToolTypeImage[tt](self) + else: + PathLog.debug("weak supported ToolType = %s" % (tt)) + self.editor = ToolEditorDefault(self) + self.editor.setupUI() + + def updateTool(self): + PathLog.track() + self.tool.Material = self.getMaterial(self.form.toolMaterial.currentIndex()) + self.tool.LengthOffset = FreeCAD.Units.parseQuantity(self.form.toolLengthOffset.text()) + self.editor.updateTool() + + def refresh(self): + PathLog.track() + self.form.blockSignals(True) + self.updateTool() + self.updateUI() + self.form.blockSignals(False) + + def setupUI(self): + PathLog.track() + self.updateUI() + + self.form.toolName.editingFinished.connect(self.updateToolName) + self.form.toolType.currentIndexChanged.connect(self.updateToolType) + self.form.toolMaterial.currentIndexChanged.connect(self.refresh) + self.form.toolLengthOffset.valueChanged.connect(self.refresh) + diff --git a/src/Mod/Path/PathScripts/PathToolLibraryManager.py b/src/Mod/Path/PathScripts/PathToolLibraryManager.py index 59ca60d198..f48cf23fba 100644 --- a/src/Mod/Path/PathScripts/PathToolLibraryManager.py +++ b/src/Mod/Path/PathScripts/PathToolLibraryManager.py @@ -29,6 +29,7 @@ import FreeCADGui import Path import PathScripts import PathScripts.PathLog as PathLog +import PathScripts.PathToolEdit as PathToolEdit import PathScripts.PathUtil as PathUtil import PathScripts.PathUtils as PathUtils import json @@ -37,10 +38,8 @@ import xml.sax from PySide import QtCore, QtGui - -LOG_MODULE = 'PathToolLibraryManager' -PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE) -#PathLog.trackModule('PathToolLibraryManager') +PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule()) +#PathLog.trackModule(PathLog.thisModule()) def translate(context, text, disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) @@ -392,10 +391,7 @@ class ToolLibraryManager(): class EditorPanel(): def __init__(self, job, cb): - #self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/ToolLibraryEditor.ui") self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolLibraryEditor.ui") - #self.editform = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/ToolEdit.ui") - self.editform = FreeCADGui.PySideUic.loadUi(":/panels/ToolEdit.ui") self.TLM = ToolLibraryManager() self.loadTable() @@ -403,6 +399,12 @@ class EditorPanel(): self.job = job self.cb = cb + def toolEditor(self, tool): + dialog = FreeCADGui.PySideUic.loadUi(":/panels/DlgToolEdit.ui") + editor = PathToolEdit.ToolEditor(tool, dialog.toolEditor, dialog) + editor.setupUI() + return editor + def accept(self): pass @@ -436,32 +438,14 @@ class EditorPanel(): return matslist[material] def addTool(self): - t = Path.Tool() - editform = FreeCADGui.PySideUic.loadUi(":/panels/ToolEdit.ui") - editform.TypeField.clear() - for tooltype in Path.Tool.getToolTypes(t): - editform.TypeField.addItem(tooltype) + tool = Path.Tool() + editor = self.toolEditor(tool) - editform.MaterialField.clear() - for material in Path.Tool.getToolMaterials(t): - editform.MaterialField.addItem(material) - - r = editform.exec_() + r = editor.Parent.exec_() if r: - if editform.NameField.text(): - t.Name = str(editform.NameField.text()) #FIXME: not unicode safe! - t.ToolType = self.getType(editform.TypeField.currentIndex()) - t.Material = self.getMaterial(editform.MaterialField.currentIndex()) - t.Diameter = FreeCAD.Units.parseQuantity(editform.DiameterField.text()) - t.LengthOffset = FreeCAD.Units.parseQuantity(editform.LengthOffsetField.text()) - t.FlatRadius = FreeCAD.Units.parseQuantity(editform.FlatRadiusField.text()) - t.CornerRadius = FreeCAD.Units.parseQuantity(editform.CornerRadiusField.text()) - t.CuttingEdgeAngle = FreeCAD.Units.Quantity(editform.CuttingEdgeAngleField.text()) - t.CuttingEdgeHeight = FreeCAD.Units.parseQuantity(editform.CuttingEdgeHeightField.text()) - + editor.accept() listname = "
" - - if self.TLM.addnew(listname, t) is True: + if self.TLM.addnew(listname, editor.Tool) is True: self.loadTable() def setFields(self): @@ -515,40 +499,12 @@ class EditorPanel(): listname = "
" toolnum = int(value) tool = self.TLM.getTool(listname, toolnum) - editform = FreeCADGui.PySideUic.loadUi(":/panels/ToolEdit.ui") + editor = self.toolEditor(tool) - editform.TypeField.clear() - for tooltype in Path.Tool.getToolTypes(tool): - editform.TypeField.addItem(tooltype) - - editform.MaterialField.clear() - for material in Path.Tool.getToolMaterials(tool): - editform.MaterialField.addItem(material) - - editform.NameField.setText(tool.Name) - editform.TypeField.setCurrentIndex(self.getType(tool.ToolType)) - editform.MaterialField.setCurrentIndex(self.getMaterial(tool.Material)) - editform.DiameterField.setText(FreeCAD.Units.Quantity(tool.Diameter, FreeCAD.Units.Length).UserString) - editform.LengthOffsetField.setText(FreeCAD.Units.Quantity(tool.LengthOffset, FreeCAD.Units.Length).UserString) - editform.FlatRadiusField.setText(FreeCAD.Units.Quantity(tool.FlatRadius, FreeCAD.Units.Length).UserString) - editform.CornerRadiusField.setText(FreeCAD.Units.Quantity(tool.CornerRadius, FreeCAD.Units.Length).UserString) - editform.CuttingEdgeAngleField.setText(FreeCAD.Units.Quantity(tool.CuttingEdgeAngle, FreeCAD.Units.Angle).UserString) - editform.CuttingEdgeHeightField.setText(FreeCAD.Units.Quantity(tool.CuttingEdgeHeight, FreeCAD.Units.Length).UserString) - - r = editform.exec_() + r = editor.Parent.exec_() if r: - if editform.NameField.text(): - tool.Name = str(editform.NameField.text()) #FIXME: not unicode safe! - tool.ToolType = self.getType(editform.TypeField.currentIndex()) - tool.Material = self.getMaterial(editform.MaterialField.currentIndex()) - tool.Diameter = FreeCAD.Units.parseQuantity(editform.DiameterField.text()) - tool.LengthOffset = FreeCAD.Units.parseQuantity(editform.LengthOffsetField.text()) - tool.FlatRadius = FreeCAD.Units.parseQuantity(editform.FlatRadiusField.text()) - tool.CornerRadius = FreeCAD.Units.parseQuantity(editform.CornerRadiusField.text()) - tool.CuttingEdgeAngle = FreeCAD.Units.Quantity(editform.CuttingEdgeAngleField.text()) - tool.CuttingEdgeHeight = FreeCAD.Units.parseQuantity(editform.CuttingEdgeHeightField.text()) - - if self.TLM.updateTool(listname, toolnum, tool) is True: + editor.accept() + if self.TLM.updateTool(listname, toolnum, editor.Tool) is True: self.loadTable() def importFile(self):