diff --git a/src/Mod/Path/Gui/Resources/panels/PathEdit.ui b/src/Mod/Path/Gui/Resources/panels/PathEdit.ui index efc27ed7d3..26d98cd62d 100644 --- a/src/Mod/Path/Gui/Resources/panels/PathEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/PathEdit.ui @@ -7,14 +7,14 @@ 0 0 400 - 924 + 673 Job Edit - 4 + 3 @@ -393,81 +393,207 @@ + + + Defaults + + + + + + Tool Rapid Feed + + + false + + + + + + <html><head/><body><p>Rapid horizontal feed rate assigned to new Tool Controllers.</p></body></html> + + + + + + + Hori + + + + + + + Vert + + + + + + + <html><head/><body><p>Rapid vertical feed rate assigned to new Tool Controllers.</p></body></html> + + + + + + + Horizontal + + + + + + + Vertical + + + + + + + + + + Operation Heights + + + false + + + + + + Safe Extra + + + + + + + Clearance Extra + + + + + + + <html><head/><body><p>Extra height for Safe Heights, measured from the operations Start Depth.</p></body></html> + + + + + + + <html><head/><body><p>Extra height for Clearance Heights, measured from the operations Start Depth.</p></body></html> + + + + + + + + + + Qt::Vertical + + + + 20 + 415 + + + + + + Tools - - - false - - - - Name - - - - - Nr. - - - - - Feed - - - - - - - - - - Feed - - - - - - - - - - Spindle - - - - - - - + + + QFrame::StyledPanel + + + QFrame::Raised + + - - + + false - - - Edit - + + + + Name + + + + + Nr. + + + + + Feed + + + + + + + + + + Feed + + + + + + + + + + Spindle + + - - - Add - - - - - - - false - - - Remove - + + + + + + false + + + Edit + + + + + + + Add + + + + + + + false + + + Remove + + + + @@ -640,7 +766,6 @@ moveToOrigin centerInStock centerInStockXY - toolControllerList toolControllerEdit toolControllerAdd toolControllerDelete diff --git a/src/Mod/Path/PathScripts/PathDrillingGui.py b/src/Mod/Path/PathScripts/PathDrillingGui.py index 751e3b8434..19bfdf4aff 100644 --- a/src/Mod/Path/PathScripts/PathDrillingGui.py +++ b/src/Mod/Path/PathScripts/PathDrillingGui.py @@ -26,6 +26,7 @@ import FreeCAD import FreeCADGui import PathScripts.PathCircularHoleBaseGui as PathCircularHoleBaseGui import PathScripts.PathDrilling as PathDrilling +import PathScripts.PathGui as PathGui import PathScripts.PathLog as PathLog import PathScripts.PathOpGui as PathOpGui @@ -53,9 +54,9 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): def getFields(self, obj): '''setFields(obj) ... update obj's properties with values from the UI''' PathLog.track() - self.updateInputField(obj, 'PeckDepth', self.form.peckDepth) - self.updateInputField(obj, 'RetractHeight', self.form.retractHeight) - self.updateInputField(obj, 'DwellTime', self.form.dwellTime) + PathGui.updateInputField(obj, 'PeckDepth', self.form.peckDepth) + PathGui.updateInputField(obj, 'RetractHeight', self.form.retractHeight) + PathGui.updateInputField(obj, 'DwellTime', self.form.dwellTime) if obj.DwellEnabled != self.form.dwellEnabled.isChecked(): obj.DwellEnabled = self.form.dwellEnabled.isChecked() diff --git a/src/Mod/Path/PathScripts/PathGui.py b/src/Mod/Path/PathScripts/PathGui.py new file mode 100644 index 0000000000..aee18a7ffc --- /dev/null +++ b/src/Mod/Path/PathScripts/PathGui.py @@ -0,0 +1,56 @@ +# -*- 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 PathScripts.PathGeom as PathGeom +import PathScripts.PathGetPoint as PathGetPoint +import PathScripts.PathLog as PathLog +import PathScripts.PathSelection as PathSelection +import PathScripts.PathOp as PathOp +import PathScripts.PathUtils as PathUtils +import importlib + +from PathScripts.PathGeom import PathGeom +from PySide import QtCore, QtGui + +__title__ = "Path UI helper and utility functions" +__author__ = "sliptonic (Brad Collette)" +__url__ = "http://www.freecadweb.org" +__doc__ = "A collection of helper and utility functions for the Path GUI." + + +def updateInputField(obj, prop, widget, onBeforeChange = None): + '''updateInputField(obj, prop, widget) ... helper function to update obj's property named prop with the value from widget, if it has changed.''' + value = FreeCAD.Units.Quantity(widget.text()).Value + attr = getattr(obj, prop) + attrValue = attr.Value if hasattr(attr, 'Value') else attr + if not PathGeom.isRoughly(attrValue, value): + PathLog.debug("updateInputField(%s, %s): %.2f -> %.2f" % (obj.Label, prop, getattr(obj, prop), value)) + if onBeforeChange: + onBeforeChange(obj) + setattr(obj, prop, value) + return True + return False + diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/PathScripts/PathJob.py index 95c0fc8900..e2b09c2a15 100644 --- a/src/Mod/Path/PathScripts/PathJob.py +++ b/src/Mod/Path/PathScripts/PathJob.py @@ -59,6 +59,10 @@ class JobTemplate: ToolController = 'ToolController' Stock = 'Stock' Version = 'Version' + DefaultVertRapid = 'DefaultVertRapid' + DefaultHorizRapid = 'DefaultHorizRapid' + DefaultSafeHeight = 'DefaultSafeHeight' + DefaultClearanceHeight = 'DefaultClearanceHeight' def isArchPanelSheet(obj): return hasattr(obj, 'Proxy') and isinstance(obj.Proxy, ArchPanel.PanelSheet) @@ -132,6 +136,20 @@ class ObjectJob: if obj.Stock.ViewObject: obj.Stock.ViewObject.Visibility = False + self.initDefaultValues(obj) + + def initDefaultValues(self, obj): + if not hasattr(obj, 'DefaultHorizRapid'): + obj.addProperty('App::PropertySpeed', 'DefaultHorizRapid', 'Defaults', QtCore.QT_TRANSLATE_NOOP('PathJob', 'Horizontal rapid feed rate for new tool controllers')) + if not hasattr(obj, 'DefaultVertRapid'): + obj.addProperty('App::PropertySpeed', 'DefaultVertRapid', 'Defaults', QtCore.QT_TRANSLATE_NOOP('PathJob', 'Vertical rapid feed rate for new tool controllers')) + if not hasattr(obj, 'DefaultSafeHeight'): + obj.addProperty('App::PropertyLength', 'DefaultSafeHeight', 'Defaults', QtCore.QT_TRANSLATE_NOOP('PathJob', 'Extra distance on top of StartDepth to set SafeHeight')) + obj.DefaultSafeHeight = 3.0 + if not hasattr(obj, 'DefaultClearanceHeight'): + obj.addProperty('App::PropertyLength', 'DefaultClearanceHeight', 'Defaults', QtCore.QT_TRANSLATE_NOOP('PathJob', 'Extra distance on top of StartDepth to set ClearanceHeight')) + obj.DefaultClearanceHeight = 5.0 + def onDelete(self, obj, arg2=None): '''Called by the view provider, there doesn't seem to be a callback on the obj itself.''' PathLog.track(obj.Label, arg2) @@ -170,6 +188,7 @@ class ObjectJob: def onDocumentRestored(self, obj): self.fixupResourceClone(obj, 'Base', 'BaseGeometry') + self.initDefaultValues(obj) def onChanged(self, obj, prop): if prop == "PostProcessor" and obj.PostProcessor: @@ -211,6 +230,15 @@ class ObjectJob: tcs.append(PathToolController.FromTemplate(tc)) if attrs.get(JobTemplate.Stock): obj.Stock = PathStock.CreateFromTemplate(obj, attrs.get(JobTemplate.Stock)) + + if attrs.get(JobTemplate.DefaultVertRapid): + obj.DefaultVertRapid = attrs[JobTemplate.DefaultVertRapid] + if attrs.get(JobTemplate.DefaultHorizRapid): + obj.DefaultHorizRapid = attrs[JobTemplate.DefaultHorizRapid] + if attrs.get(JobTemplate.DefaultSafeHeight): + obj.DefaultSafeHeight = attrs[JobTemplate.DefaultSafeHeight] + if attrs.get(JobTemplate.DefaultClearanceHeight): + obj.DefaultClearanceHeight = attrs[JobTemplate.DefaultClearanceHeight] else: PathLog.error(translate('PathJob', "Unsupported PathJob template version %s") % attrs.get(JobTemplate.Version)) tcs.append(PathToolController.Create()) @@ -231,6 +259,10 @@ class ObjectJob: attrs[JobTemplate.GeometryTolerance] = str(obj.GeometryTolerance.Value) if obj.Description: attrs[JobTemplate.Description] = obj.Description + attrs[JobTemplate.DefaultVertRapid] = obj.DefaultVertRapid.UserString + attrs[JobTemplate.DefaultHorizRapid] = obj.DefaultHorizRapid.UserString + attrs[JobTemplate.DefaultSafeHeight] = obj.DefaultSafeHeight.UserString + attrs[JobTemplate.DefaultClearanceHeight] = obj.DefaultClearanceHeight.UserString return attrs def __getstate__(self): @@ -256,6 +288,8 @@ class ObjectJob: group = self.obj.ToolController PathLog.info("addToolController(%s): %s" % (tc.Label, [t.Label for t in group])) if tc.Name not in [str(t.Name) for t in group]: + tc.VertRapid = self.obj.DefaultVertRapid + tc.HorizRapid = self.obj.DefaultHorizRapid group.append(tc) self.obj.ToolController = group diff --git a/src/Mod/Path/PathScripts/PathJobGui.py b/src/Mod/Path/PathScripts/PathJobGui.py index 8260641511..42e3bbe844 100644 --- a/src/Mod/Path/PathScripts/PathJobGui.py +++ b/src/Mod/Path/PathScripts/PathJobGui.py @@ -27,6 +27,7 @@ import DraftVecUtils import FreeCAD import FreeCADGui import PathScripts.PathJob as PathJob +import PathScripts.PathGui as PathGui import PathScripts.PathLog as PathLog import PathScripts.PathStock as PathStock import PathScripts.PathToolController as PathToolController @@ -476,6 +477,13 @@ class TaskPanel: self.postProcessorDefaultTooltip = self.form.postProcessor.toolTip() self.postProcessorArgsDefaultTooltip = self.form.postProcessorArguments.toolTip() + hicon = QtGui.QIcon.fromTheme('object-flip-horizontal') + vicon = QtGui.QIcon.fromTheme('object-flip-vertical') + iconSize = QtCore.QSize() + + self.form.defaultRapidHorizontalIcon.setPixmap(hicon.pixmap(iconSize)) + self.form.defaultRapidVerticalIcon.setPixmap(vicon.pixmap(iconSize)) + self.vproxy.setupEditVisibility(self.obj) self.stockFromBase = None @@ -549,6 +557,12 @@ class TaskPanel: self.updateTooltips() self.stockEdit.getFields(self.obj) + + PathGui.updateInputField(self.obj, 'DefaultSafeHeight', self.form.defaultHeightSafe) + PathGui.updateInputField(self.obj, 'DefaultClearanceHeight', self.form.defaultHeightClearance) + PathGui.updateInputField(self.obj, 'DefaultVertRapid', self.form.defaultRapidVertical) + PathGui.updateInputField(self.obj, 'DefaultHorizRapid', self.form.defaultRapidHorizontal) + self.obj.Proxy.execute(self.obj) def selectComboBoxText(self, widget, text): @@ -647,6 +661,11 @@ class TaskPanel: self.updateToolController() self.stockEdit.setFields(self.obj) + self.form.defaultRapidVertical.setText(self.obj.DefaultVertRapid.UserString) + self.form.defaultRapidHorizontal.setText(self.obj.DefaultHorizRapid.UserString) + self.form.defaultHeightSafe.setText(self.obj.DefaultSafeHeight.UserString) + self.form.defaultHeightClearance.setText(self.obj.DefaultClearanceHeight.UserString) + def setPostProcessorOutputFile(self): filename = QtGui.QFileDialog.getSaveFileName(self.form, translate("Path_Job", "Select Output File"), None, translate("Path_Job", "All Files (*.*)")) @@ -987,6 +1006,12 @@ class TaskPanel: self.form.moveToOrigin.clicked.connect(self.alignMoveToOrigin) self.updateSelection() + # Defaults + self.form.defaultRapidVertical.editingFinished.connect(self.getFields) + self.form.defaultRapidHorizontal.editingFinished.connect(self.getFields) + self.form.defaultHeightSafe.editingFinished.connect(self.getFields) + self.form.defaultHeightClearance.editingFinished.connect(self.getFields) + # set active page if activate in ['General', 'Base']: self.form.setCurrentIndex(0) diff --git a/src/Mod/Path/PathScripts/PathOp.py b/src/Mod/Path/PathScripts/PathOp.py index bafbff7f5f..0570e04cd9 100644 --- a/src/Mod/Path/PathScripts/PathOp.py +++ b/src/Mod/Path/PathScripts/PathOp.py @@ -330,8 +330,8 @@ class ObjectOp(object): if obj.StartDepth.Value < zmax: safeDepths = False - clearance = obj.StartDepth.Value + 5.0 - safe = obj.StartDepth.Value + 3 + clearance = obj.StartDepth.Value + self.job.DefaultClearanceHeight.Value + safe = obj.StartDepth.Value + self.job.DefaultSafeHeight.Value if hasattr(obj, 'ClearanceHeight') and not PathGeom.isRoughly(clearance, obj.ClearanceHeight.Value): obj.ClearanceHeight = clearance if hasattr(obj, 'SafeHeight') and not PathGeom.isRoughly(safe, obj.SafeHeight.Value): diff --git a/src/Mod/Path/PathScripts/PathOpGui.py b/src/Mod/Path/PathScripts/PathOpGui.py index 1c7034fa4f..295140fb1e 100644 --- a/src/Mod/Path/PathScripts/PathOpGui.py +++ b/src/Mod/Path/PathScripts/PathOpGui.py @@ -26,6 +26,7 @@ import FreeCAD import FreeCADGui import PathScripts.PathGeom as PathGeom import PathScripts.PathGetPoint as PathGetPoint +import PathScripts.PathGui as PathGui import PathScripts.PathLog as PathLog import PathScripts.PathSelection as PathSelection import PathScripts.PathOp as PathOp @@ -299,19 +300,6 @@ class TaskPanelPage(object): if obj.ToolController != tc: obj.ToolController = tc - def updateInputField(self, obj, prop, widget, onBeforeChange = None): - '''updateInputField(obj, prop, widget) ... helper function to update obj's property named prop with the value from widget, if it has changed.''' - value = FreeCAD.Units.Quantity(widget.text()).Value - attr = getattr(obj, prop) - attrValue = attr.Value if hasattr(attr, 'Value') else attr - if not PathGeom.isRoughly(attrValue, value): - PathLog.debug("updateInputField(%s, %s): %.2f -> %.2f" % (obj.Label, prop, getattr(obj, prop), value)) - if onBeforeChange: - onBeforeChange(obj) - setattr(obj, prop, value) - return True - return False - class TaskPanelBaseGeometryPage(TaskPanelPage): '''Page controller for the base geometry.''' DataObject = QtCore.Qt.ItemDataRole.UserRole @@ -548,8 +536,8 @@ class TaskPanelHeightsPage(TaskPanelPage): def getTitle(self, obj): return translate("Path", "Heights") def getFields(self, obj): - self.updateInputField(obj, 'SafeHeight', self.form.safeHeight) - self.updateInputField(obj, 'ClearanceHeight', self.form.clearanceHeight) + PathGui.updateInputField(obj, 'SafeHeight', self.form.safeHeight) + PathGui.updateInputField(obj, 'ClearanceHeight', self.form.clearanceHeight) def setFields(self, obj): self.form.safeHeight.setText(FreeCAD.Units.Quantity(obj.SafeHeight.Value, FreeCAD.Units.Length).UserString) self.form.clearanceHeight.setText(FreeCAD.Units.Quantity(obj.ClearanceHeight.Value, FreeCAD.Units.Length).UserString) @@ -600,13 +588,13 @@ class TaskPanelDepthsPage(TaskPanelPage): if obj.FinalDepthLock != self.form.finalDepthLock.isChecked(): obj.FinalDepthLock = self.form.finalDepthLock.isChecked() - self.updateInputField(obj, 'StartDepth', self.form.startDepth, self.lockStartDepth) + PathGui.updateInputField(obj, 'StartDepth', self.form.startDepth, self.lockStartDepth) if not PathOp.FeatureNoFinalDepth & self.features: - self.updateInputField(obj, 'FinalDepth', self.form.finalDepth, self.lockFinalDepth) + PathGui.updateInputField(obj, 'FinalDepth', self.form.finalDepth, self.lockFinalDepth) if PathOp.FeatureStepDown & self.features: - self.updateInputField(obj, 'StepDown', self.form.stepDown) + PathGui.updateInputField(obj, 'StepDown', self.form.stepDown) if PathOp.FeatureFinishDepth & self.features: - self.updateInputField(obj, 'FinishDepth', self.form.finishDepth) + PathGui.updateInputField(obj, 'FinishDepth', self.form.finishDepth) def setFields(self, obj): self.form.startDepth.setText(FreeCAD.Units.Quantity(obj.StartDepth.Value, FreeCAD.Units.Length).UserString) diff --git a/src/Mod/Path/PathScripts/PathPocketBaseGui.py b/src/Mod/Path/PathScripts/PathPocketBaseGui.py index 6e22443737..5b8dd42a5f 100644 --- a/src/Mod/Path/PathScripts/PathPocketBaseGui.py +++ b/src/Mod/Path/PathScripts/PathPocketBaseGui.py @@ -25,6 +25,7 @@ import FreeCAD import FreeCADGui import PathScripts.PathLog as PathLog +import PathScripts.PathGui as PathGui import PathScripts.PathOpGui as PathOpGui import PathScripts.PathPocket as PathPocket import PathScripts.PathSelection as PathSelection @@ -91,7 +92,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): self.form.zigZagAngle.setEnabled(True) if setModel: - self.updateInputField(obj, 'ZigZagAngle', self.form.zigZagAngle) + PathGui.updateInputField(obj, 'ZigZagAngle', self.form.zigZagAngle) def getFields(self, obj): '''getFields(obj) ... transfers values from UI to obj's proprties''' @@ -102,7 +103,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): if obj.OffsetPattern != str(self.form.offsetPattern.currentText()): obj.OffsetPattern = str(self.form.offsetPattern.currentText()) - self.updateInputField(obj, 'ExtraOffset', self.form.extraOffset) + PathGui.updateInputField(obj, 'ExtraOffset', self.form.extraOffset) self.updateToolController(obj, self.form.toolController) self.updateZigZagAngle(obj) diff --git a/src/Mod/Path/PathScripts/PathProfileBaseGui.py b/src/Mod/Path/PathScripts/PathProfileBaseGui.py index 92a01cbfa3..91801d68fe 100644 --- a/src/Mod/Path/PathScripts/PathProfileBaseGui.py +++ b/src/Mod/Path/PathScripts/PathProfileBaseGui.py @@ -25,6 +25,7 @@ import FreeCAD import FreeCADGui import PathScripts.PathLog as PathLog +import PathScripts.PathGui as PathGui import PathScripts.PathOpGui as PathOpGui import PathScripts.PathProfileFaces as PathProfileFaces import PathScripts.PathSelection as PathSelection @@ -73,7 +74,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): def getFields(self, obj): '''getFields(obj) ... transfers values from UI to obj's proprties''' - self.updateInputField(obj, 'OffsetExtra', self.form.extraOffset) + PathGui.updateInputField(obj, 'OffsetExtra', self.form.extraOffset) if obj.UseComp != self.form.useCompensation.isChecked(): obj.UseComp = self.form.useCompensation.isChecked() if obj.UseStartPoint != self.form.useStartPoint.isChecked():