From 159f5ae93123bedfa1219802a350f3777edba00a Mon Sep 17 00:00:00 2001 From: markus Date: Thu, 20 Sep 2018 17:10:15 -0700 Subject: [PATCH] Basic UI to add extension features. --- .../Resources/panels/PageOpPocketExtEdit.ui | 12 +++- src/Mod/Path/PathScripts/PathPocketShape.py | 65 ++++++++++++++++--- .../Path/PathScripts/PathPocketShapeGui.py | 65 +++++++++++++++++-- 3 files changed, 125 insertions(+), 17 deletions(-) diff --git a/src/Mod/Path/Gui/Resources/panels/PageOpPocketExtEdit.ui b/src/Mod/Path/Gui/Resources/panels/PageOpPocketExtEdit.ui index 7cd06c936c..8af3de3fdf 100644 --- a/src/Mod/Path/Gui/Resources/panels/PageOpPocketExtEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/PageOpPocketExtEdit.ui @@ -50,7 +50,7 @@ - + -999999999.000000000000000 @@ -67,6 +67,9 @@ + + false + Feature @@ -116,6 +119,13 @@ + + + Gui::QuantitySpinBox + QDoubleSpinBox +
gui_quantityspinbox.h
+
+
diff --git a/src/Mod/Path/PathScripts/PathPocketShape.py b/src/Mod/Path/PathScripts/PathPocketShape.py index 44f3d30173..457d4903d0 100644 --- a/src/Mod/Path/PathScripts/PathPocketShape.py +++ b/src/Mod/Path/PathScripts/PathPocketShape.py @@ -28,6 +28,7 @@ import PathScripts.PathGeom as PathGeom import PathScripts.PathLog as PathLog import PathScripts.PathOp as PathOp import PathScripts.PathPocketBase as PathPocketBase +import PathScripts.PathUtil as PathUtil import PathScripts.PathUtils as PathUtils import TechDraw import sys @@ -39,7 +40,7 @@ __author__ = "sliptonic (Brad Collette)" __url__ = "http://www.freecadweb.org" __doc__ = "Class and implementation of shape based Pocket operation." -if False: +if True: PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) PathLog.trackModule(PathLog.thisModule()) else: @@ -49,6 +50,17 @@ else: def translate(context, text, disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) +class Extension(object): + DirectionNormal = 0 + DirectionX = 1 + DirectionY = 2 + + def __init__(self, obj, sub, length, direction): + self.obj = obj + self.sub = sub + self.length = length + self.direction = direction + class ObjectPocket(PathPocketBase.ObjectPocket): '''Proxy object for Pocket operation.''' @@ -58,13 +70,25 @@ class ObjectPocket(PathPocketBase.ObjectPocket): def initPocketOp(self, obj): '''initPocketOp(obj) ... setup receiver''' - obj.addProperty("App::PropertyBool", "UseOutline", "Pocket", QtCore.QT_TRANSLATE_NOOP("App::Property", "Uses the outline of the base geometry.")) - obj.UseOutline = False + if not hasattr(obj, 'UseOutline'): + obj.addProperty('App::PropertyBool', 'UseOutline', 'Pocket', QtCore.QT_TRANSLATE_NOOP('PathPocketShape', 'Uses the outline of the base geometry.')) + obj.UseOutline = False + if not hasattr(obj, 'ExtensionLengthDefault'): + obj.addProperty('App::PropertyDistance', 'ExtensionLengthDefault', 'Extension', QtCore.QT_TRANSLATE_NOOP('PathPocketShape', 'Default length of extensions.')) + if not hasattr(obj, 'ExtensionFeatures'): + obj.addProperty('App::PropertyLinkSubListGlobal', 'ExtensionFeature', 'Extension', QtCore.QT_TRANSLATE_NOOP('PathPocketShape', 'List of features to extend.')) + if not hasattr(obj, 'ExtensionLength'): + obj.addProperty('App::PropertyFloatList', 'ExtensionLength', 'Extension', QtCore.QT_TRANSLATE_NOOP('PathPocketShape', 'List of extension lenght of corresponding feature.')) + if not hasattr(obj, 'ExtensionDirection'): + obj.addProperty('App::PropertyIntegerList', 'ExtensionDirection', 'Extension', QtCore.QT_TRANSLATE_NOOP('PathPocketShape', 'List of extension direction of corresponding feature.')) + + obj.setEditorMode('ExtensionFeature', 2) + obj.setEditorMode('ExtensionLength', 2) + obj.setEditorMode('ExtensionDirection', 2) def opOnDocumentRestored(self, obj): '''opOnDocumentRestored(obj) ... adds the UseOutline property if it doesn't exist.''' - if not hasattr(obj, 'UseOutline'): - self.initPocketOp(obj) + self.initPocketOp(obj) def pocketInvertExtraOffset(self): return False @@ -74,15 +98,15 @@ class ObjectPocket(PathPocketBase.ObjectPocket): PathLog.track() if obj.Base: - PathLog.debug("base items exist. Processing...") + PathLog.debug('base items exist. Processing...') self.removalshapes = [] self.horiz = [] vertical = [] for o in obj.Base: - PathLog.debug("Base item: {}".format(o)) + PathLog.debug('Base item: {}'.format(o)) base = o[0] for sub in o[1]: - if "Face" in sub: + if 'Face' in sub: face = base.Shape.getElement(sub) if type(face.Surface) == Part.Plane and PathGeom.isVertical(face.Surface.Axis): # it's a flat horizontal face @@ -100,7 +124,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): elif type(face.Surface) == Part.Plane and PathGeom.isHorizontal(face.Surface.Axis): vertical.append(face) else: - PathLog.error(translate('PathPocket', "Pocket does not support shape %s.%s") % (base.Label, sub)) + PathLog.error(translate('PathPocket', 'Pocket does not support shape %s.%s') % (base.Label, sub)) self.vertical = PathGeom.combineConnectedShapes(vertical) self.vWires = [TechDraw.findShapeOutline(shape, 1, FreeCAD.Vector(0, 0, 1)) for shape in self.vertical] @@ -162,6 +186,27 @@ class ObjectPocket(PathPocketBase.ObjectPocket): bb = job.Stock.Shape.BoundBox obj.OpFinalDepth = bb.ZMin obj.OpStartDepth = bb.ZMax + obj.ExtensionLengthDefault = obj.OpToolDiameter / 2 + + def getExtensions(self, obj): + extensions = [] + i = 0 + for extObj,features in obj.ExtensionFeature: + for extSub in features: + ext = Extension(extObj, extSub, obj.ExtensionLengthDefault, Extension.DirectionNormal) + extensions.append(ext) + i = i + 1 + return extensions + + def setExtensions(self, obj, extensions): + features = {} + for ext in extensions: + subs = features.get(ext.obj, []) + subs.append(ext.sub) + features[ext.obj] = subs + PathLog.track('setExtension', obj.Label) + #obj.ExtensionFeature = [(obj, sub) for obj, sub in PathUtil.keyValueIter(features)] + obj.ExtensionFeature = [(ext.obj, ext.sub) for ext in extensions] def SetupProperties(): return PathPocketBase.SetupProperties() + [ 'UseOutline' ] @@ -169,6 +214,6 @@ def SetupProperties(): def Create(name, obj = None): '''Create(name) ... Creates and returns a Pocket operation.''' if obj is None: - obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) + obj = FreeCAD.ActiveDocument.addObject('Path::FeaturePython', name) proxy = ObjectPocket(obj, name) return obj diff --git a/src/Mod/Path/PathScripts/PathPocketShapeGui.py b/src/Mod/Path/PathScripts/PathPocketShapeGui.py index 661942eb0f..e547ea1228 100644 --- a/src/Mod/Path/PathScripts/PathPocketShapeGui.py +++ b/src/Mod/Path/PathScripts/PathPocketShapeGui.py @@ -24,6 +24,7 @@ import FreeCAD import FreeCADGui +import PathScripts.PathGui as PathGui import PathScripts.PathLog as PathLog import PathScripts.PathOp as PathOp import PathScripts.PathOpGui as PathOpGui @@ -38,6 +39,8 @@ __author__ = "sliptonic (Brad Collette)" __url__ = "http://www.freecadweb.org" __doc__ = "Pocket Shape operation page controller and command implementation." +def translate(context, text, disambig=None): + return QtCore.QCoreApplication.translate(context, text, disambig) if True: PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) @@ -47,14 +50,23 @@ else: class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): + DataObject = QtCore.Qt.ItemDataRole.UserRole + Direction = { + PathPocketShape.Extension.DirectionNormal: translate('PathPocket', 'Normal'), + PathPocketShape.Extension.DirectionX: translate('PathPocket', 'X'), + PathPocketShape.Extension.DirectionY: translate('PathPocket', 'Y') + } def initPage(self, obj): self.setTitle("Pocket Extensions") - self.enabled = True - self.enable(False) - tc = PathUtil.toolControllerForOp(self.obj) - if tc: - self.form.defaultLength.setValue(tc.Tool.Diameter/2) + self.enabled = not obj.UseOutline + self.enable(not self.enabled) + self.extensions = obj.Proxy.getExtensions(obj) + + self.defaultLength = PathGui.QuantitySpinBox(self.form.defaultLength, obj, 'ExtensionLengthDefault') + + self.form.extensions.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) + self.form.extensions.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) def enable(self, ena): if ena != self.enabled: @@ -69,6 +81,40 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): def getForm(self): return FreeCADGui.PySideUic.loadUi(":/panels/PageOpPocketExtEdit.ui") + def getFields(self, obj): + self.defaultLength.updateProperty() + exts = [] + for row in range(self.form.extensions.rowCount()): + item = self.form.extensions.item(row, 0) + exts.append(item.data(self.DataObject)) + obj.Proxy.setExtensions(obj, exts) + + def setFields(self, obj): + self.defaultLength.updateSpinBox() + + self.form.extensions.blockSignals(True) + self.form.extensions.clearContents() + self.form.extensions.setRowCount(0) + for row, ext in enumerate(self.extensions): + PathLog.info("{}.{}".format(ext.obj.Label, ext.sub)) + + self.form.extensions.insertRow(row) + + item = QtGui.QTableWidgetItem("{}.{}".format(ext.obj.Label, ext.sub)) + item.setData(self.DataObject, ext) + self.form.extensions.setItem(row, 0, item) + + item = QtGui.QTableWidgetItem("{}".format(ext.length)) + item.setData(self.DataObject, ext) + self.form.extensions.setItem(row, 1, item) + + item = QtGui.QTableWidgetItem("{}".format(self.Direction[ext.direction])) + item.setData(self.DataObject, ext) + self.form.extensions.setItem(row, 2, item) + + self.form.extensions.resizeColumnsToContents() + self.form.extensions.blockSignals(False) + def updateSelection(self, obj, sel): PathLog.track(sel) if sel and sel[0].SubElementNames: @@ -88,10 +134,17 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): self.form.buttonRemove.setEnabled(False) def extensionsAdd(self): - pass + for sel in FreeCADGui.Selection.getSelectionEx(): + for subname in sel.SubElementNames: + row = self.form.extensions.rowCount() + ext = PathPocketShape.Extension(sel.Object, subname, 0.0, 0) + self.extensions.append(ext) + self.setFields(self.obj) + self.setDirty() def extensionsClear(self): self.form.extensions.clearContents() + self.form.extensions.setRowCount(0) def extensionsRemove(self): pass