284 lines
12 KiB
Python
284 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# ***************************************************************************
|
|
# * *
|
|
# * Copyright (c) 2018 sliptonic <shopinthewoods@gmail.com> *
|
|
# * *
|
|
# * 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.PathLog as PathLog
|
|
import math
|
|
|
|
from PySide import 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)
|
|
return FreeCAD.Units.parseQuantity(self.form.value_a.text())
|
|
|
|
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(ToolEditorEndmill, self).__init__(editor, 'endmill.svg', 'da', 'S')
|
|
|
|
class ToolEditorDrill(ToolEditorImage):
|
|
'''Tool parameter editor for drills.'''
|
|
def __init__(self, editor):
|
|
super(ToolEditorDrill, 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(ToolEditorEngrave, self).__init__(editor, 'v-bit.svg', '', 'dS')
|
|
|
|
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.refresh()
|
|
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 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.Name = str(self.form.toolName.text())
|
|
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.refresh)
|
|
self.form.toolType.currentIndexChanged.connect(self.updateToolType)
|