diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt
index c4cf6bd04..225732aa1 100644
--- a/src/Mod/Path/CMakeLists.txt
+++ b/src/Mod/Path/CMakeLists.txt
@@ -38,6 +38,7 @@ SET(PathScripts_SRCS
PathScripts/PathDrilling.py
PathScripts/PathDressup.py
PathScripts/DragknifeDressup.py
+ PathScripts/PathDressupHoldingTabs.py
PathScripts/PathHop.py
PathScripts/PathUtils.py
PathScripts/PathSelection.py
diff --git a/src/Mod/Path/Gui/Resources/Path.qrc b/src/Mod/Path/Gui/Resources/Path.qrc
index 27353e675..7ad296a00 100644
--- a/src/Mod/Path/Gui/Resources/Path.qrc
+++ b/src/Mod/Path/Gui/Resources/Path.qrc
@@ -90,5 +90,6 @@
panels/DogboneEdit.ui
panels/DlgSelectPostProcessor.ui
preferences/PathJob.ui
+ panels/HoldingTabsEdit.ui
diff --git a/src/Mod/Path/Gui/Resources/panels/HoldingTabsEdit.ui b/src/Mod/Path/Gui/Resources/panels/HoldingTabsEdit.ui
new file mode 100644
index 000000000..35c18c9d4
--- /dev/null
+++ b/src/Mod/Path/Gui/Resources/panels/HoldingTabsEdit.ui
@@ -0,0 +1,121 @@
+
+
+ TaskPanel
+
+
+
+ 0
+ 0
+ 352
+ 387
+
+
+
+ Holding Tabs
+
+
+ -
+
+
+ QFrame::NoFrame
+
+
+ 0
+
+
+
+
+ 0
+ 0
+ 334
+ 340
+
+
+
+ Holding Tabs
+
+
+
-
+
+
+ Count
+
+
+
+ -
+
+
+ Width
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ <html><head/><body><p>List of holding tabs calculated by the paremeters entered above. You can un-check tabs you don't want to be inserted.</p></body></html>
+
+
+
+ -
+
+
+ <html><head/><body><p>Enter the number of tabs you wish to have.</p><p><br/></p><p>Note that sometimes it's necessary to enter a larger than desired count number and disable the ones tabs you don't want in order to get the holding tab layout you want.</p></body></html>
+
+
+
+ -
+
+
+ <html><head/><body><p>Width of each tab.</p></body></html>
+
+
+
+ -
+
+
+ Height
+
+
+
+ -
+
+
+ <html><head/><body><p>The height of the holding tab measured from the bottom of the path. By default this is set to the (estimated) height of the path.</p></body></html>
+
+
+
+ -
+
+
+ true
+
+
+ Angle
+
+
+
+ -
+
+
+ true
+
+
+ <html><head/><body><p>Angle of tab walls.</p></body></html>
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Mod/Path/InitGui.py b/src/Mod/Path/InitGui.py
index 468f07fa9..68bc0bdc7 100644
--- a/src/Mod/Path/InitGui.py
+++ b/src/Mod/Path/InitGui.py
@@ -75,6 +75,7 @@ class PathWorkbench (Workbench):
from PathScripts import PathProfileEdges
from PathScripts import DogboneDressup
from PathScripts import PathMillFace
+ from PathScripts import PathDressupHoldingTabs
import PathCommands
# build commands list
@@ -84,7 +85,7 @@ class PathWorkbench (Workbench):
twodopcmdlist = ["Path_Contour", "Path_Profile", "Path_Profile_Edges", "Path_Pocket", "Path_Drilling", "Path_Engrave", "Path_MillFace"]
threedopcmdlist = ["Path_Surfacing"]
modcmdlist = ["Path_Copy", "Path_CompoundExtended", "Path_Array", "Path_SimpleCopy" ]
- dressupcmdlist = ["Dogbone_Dressup", "DragKnife_Dressup"]
+ dressupcmdlist = ["Dogbone_Dressup", "DragKnife_Dressup", "PathDressup_HoldingTabs"]
extracmdlist = ["Path_SelectLoop"]
#modcmdmore = ["Path_Hop",]
#remotecmdlist = ["Path_Remote"]
@@ -119,6 +120,11 @@ class PathWorkbench (Workbench):
# "Path", "Remote Operations")], remotecmdlist)
self.appendMenu([translate("Path", "&Path")], extracmdlist)
+ # Add preferences pages
+ import os
+ FreeCADGui.addPreferencePage(FreeCAD.getHomePath(
+ ) + os.sep + "Mod" + os.sep + "Path" + os.sep + "PathScripts" + os.sep + "DlgSettingsPath.ui", "Path")
+
Log('Loading Path workbench... done\n')
def GetClassName(self):
@@ -136,7 +142,7 @@ class PathWorkbench (Workbench):
if len(FreeCADGui.Selection.getSelection()) == 1:
if FreeCADGui.Selection.getSelection()[0].isDerivedFrom("Path::Feature"):
self.appendContextMenu("", ["Path_Inspect"])
- if "Profile" or "Contour" in FreeCADGui.Selection.getSelection()[0].Name:
+ if "Profile" in FreeCADGui.Selection.getSelection()[0].Name:
self.appendContextMenu("", ["Add_Tag"])
self.appendContextMenu("", ["Set_StartPoint"])
self.appendContextMenu("", ["Set_EndPoint"])
diff --git a/src/Mod/Path/PathScripts/PathDressupHoldingTabs.py b/src/Mod/Path/PathScripts/PathDressupHoldingTabs.py
new file mode 100644
index 000000000..2f12b0956
--- /dev/null
+++ b/src/Mod/Path/PathScripts/PathDressupHoldingTabs.py
@@ -0,0 +1,514 @@
+# -*- coding: utf-8 -*-
+
+# ***************************************************************************
+# * *
+# * Copyright (c) 2014 Yorik van Havre *
+# * *
+# * 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
+from PathScripts import PathUtils
+from PySide import QtCore, QtGui
+import math
+import Part
+import DraftGeomUtils
+
+"""Holding Tabs Dressup object and FreeCAD command"""
+
+# Qt tanslation handling
+try:
+ _encoding = QtGui.QApplication.UnicodeUTF8
+
+ def translate(context, text, disambig=None):
+ return QtGui.QApplication.translate(context, text, disambig, _encoding)
+
+except AttributeError:
+
+ def translate(context, text, disambig=None):
+ return QtGui.QApplication.translate(context, text, disambig)
+
+debugDressup = True
+
+def debugMarker(vector, label, color = None, radius = 0.5):
+ if debugDressup:
+ obj = FreeCAD.ActiveDocument.addObject("Part::Sphere", label)
+ obj.Label = label
+ obj.Radius = radius
+ obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0,0,1), 0))
+ if color:
+ obj.ViewObject.ShapeColor = color
+
+movecommands = ['G0', 'G00', 'G1', 'G01', 'G2', 'G02', 'G3', 'G03']
+movestraight = ['G1', 'G01']
+movecw = ['G2', 'G02']
+moveccw = ['G3', 'G03']
+movearc = movecw + moveccw
+
+def getAngle(v):
+ a = v.getAngle(FreeCAD.Vector(1,0,0))
+ if v.x < 0 and v.y < 0:
+ return a - math.pi/2
+ if v.y < 0:
+ return -a
+ return a
+
+class PathData:
+ def __init__(self, obj):
+ self.obj = obj
+ self.edges = []
+ lastPt = FreeCAD.Vector(0, 0, 0)
+ for cmd in obj.Base.Path.Commands:
+ if cmd.Name in movecommands:
+ pt = self.point(cmd, lastPt)
+ if cmd.Name in movestraight:
+ self.edges.append(Part.Edge(Part.Line(lastPt, pt)))
+ elif cmd.Name in movearc:
+ center = lastPt + self.point(cmd, FreeCAD.Vector(0,0,0), 'I', 'J', 'K')
+ A = lastPt - center
+ B = pt - center
+ a = getAngle(A)
+ b = getAngle(B)
+ if cmd.Name in movecw and a < 0 and math.fabs(math.pi - b) < 0.0000001:
+ angle = (a - b) / 2
+ elif cmd.Name in moveccw and math.fabs(math.pi - a) < 0.0000001 and b < 0:
+ angle = (b - a) / 2
+ else:
+ angle = (a + b) / 2.
+ d = -B.x * A.y + B.y * A.x
+
+ R = (lastPt - center).Length
+ ptm = center + FreeCAD.Vector(math.cos(angle), math.sin(angle), 0) * R
+ #if pt.z == 2.: # and pt.x == 10. and math.fabs(pt.y) == 12.5:
+ # #print("%s (%.2f %.2f) -> (%.2f, %.2f): center=(%.2f, %.2f)" % (cmd, lastPt.x, lastPt.y, pt.x, pt.y, center.x, center.y))
+ # print(" a = %+.2f b = %+.2f) %+.2f -> angle = %+.2f r = %.2f" % (a/math.pi, b/math.pi, d, angle/math.pi, R))
+ # debugMarker(lastPt, 'arc', (1.0, 1.0, 0.0), 0.3)
+ # debugMarker(ptm, 'arc', (1.0, 1.0, 0.0), 0.3)
+ # debugMarker(pt, 'arc', (1.0, 1.0, 0.0), 0.3)
+ self.edges.append(Part.Edge(Part.Arc(lastPt, ptm, pt)))
+ lastPt = pt
+ self.base = self.findBottomWire(self.edges)
+ # determine overall length
+ self.length = self.base.Length
+
+ def point(self, cmd, pt, X='X', Y='Y', Z='Z'):
+ x = cmd.Parameters.get(X, pt.x)
+ y = cmd.Parameters.get(Y, pt.y)
+ z = cmd.Parameters.get(Z, pt.z)
+ return FreeCAD.Vector(x, y, z)
+
+ def findBottomWire(self, edges):
+ (minZ, maxZ) = self.findZLimits(edges)
+ self.minZ = minZ
+ self.maxZ = maxZ
+ bottom = [e for e in edges if e.Vertexes[0].Point.z == minZ and e.Vertexes[1].Point.z == minZ]
+ wire = Part.Wire(bottom)
+ if wire.isClosed():
+ return wire
+ # if we get here there are already holding tabs, or we're not looking at a profile
+ # let's try and insert the missing pieces - another day
+ raise ValueError("Selected path doesn't seem to be a Profile operation.")
+
+
+ def findZLimits(self, edges):
+ # not considering arcs and spheres in Z direction, find the highes and lowest Z values
+ minZ = edges[0].Vertexes[0].Point.z
+ maxZ = minZ
+ for e in edges:
+ for v in e.Vertexes:
+ if v.Point.z < minZ:
+ minZ = v.Point.z
+ if v.Point.z > maxZ:
+ maxZ = v.Point.z
+ return (minZ, maxZ)
+
+class ObjectDressup:
+
+ def __init__(self, obj):
+ self.obj = obj
+ obj.addProperty("App::PropertyLink", "Base","Base", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTabs", "The base path to modify"))
+ obj.addProperty("App::PropertyInteger", "Count", "Tab", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTabs", "The number of holding tabs to be generated"))
+ obj.addProperty("App::PropertyFloat", "Height", "Tab", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTabs", "Height of holding tabs measured from bottom of path"))
+ obj.addProperty("App::PropertyFloat", "Width", "Tab", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTabs", "Width of each tab at its base"))
+ obj.addProperty("App::PropertyFloat", "Angle", "Tab", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTabs", "Angle of plunge used for tabs"))
+ obj.addProperty("App::PropertyIntegerList", "Blacklist", "Tab", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTabs", "IDs of disabled paths"))
+ obj.setEditorMode("Blacklist", 2)
+ obj.Proxy = self
+
+ def __getstate__(self):
+ return None
+
+ def __setstate__(self, state):
+ return None
+
+ def getFingerprint(self, obj):
+ if hasattr(self, 'pathData'):
+ return "%d-%.2f-%.2f-%.2f-%s" % (obj.Count, obj.Height, obj.Width, obj.Angle, str(obj.Blacklist))
+ return ''
+
+ def execute(self, obj):
+ if not obj.Base:
+ return
+ if not obj.Base.isDerivedFrom("Path::Feature"):
+ return
+ if not obj.Base.Path:
+ return
+ if not obj.Base.Path.Commands:
+ return
+
+ pathData = self.setup(obj)
+ if not pathData:
+ return
+
+ if hasattr(self, 'fingerprint') and self.fingerprint and self.fingerprint == self.getFingerprint(obj):
+ return
+
+ self.fingerprint = self.getFingerprint(obj)
+
+ #for e in pathData.base.Edges:
+ # debugMarker(e.Vertexes[0].Point, 'base', (0.0, 1.0, 1.0), 0.2)
+
+ if obj.Count == 0:
+ obj.Path = obj.Base.Path
+ return
+
+ tabDistance = pathData.base.Length / obj.Count
+
+ # start assigning tabs on the longest segment
+ maxLen = sorted(pathData.base.Edges, key=lambda e: -e.Length)[0].Length
+ startIndex = 0
+ for i in range(0, len(pathData.base.Edges)):
+ edge = pathData.base.Edges[i]
+ if edge.Length == maxLen:
+ startIndex = i
+ break
+
+ startEdge = pathData.base.Edges[startIndex]
+ startCount = int(startEdge.Length / tabDistance) + 1
+
+ lastTabLength = (startEdge.Length + (startCount - 1) * tabDistance) / 2
+ if lastTabLength < 0 or lastTabLength > startEdge.Length:
+ lastTabLength = startEdge.Length / 2
+ currentLength = startEdge.Length
+ minLength = 2 * obj.Width
+
+ print("start index=%-2d -> count=%d (length=%.2f, distance=%.2f)" % (startIndex, startCount, startEdge.Length, tabDistance))
+ print(" -> lastTabLength=%.2f)" % lastTabLength)
+ print(" -> currentLength=%.2f)" % currentLength)
+
+ tabs = { startIndex: startCount }
+
+ for i in range(startIndex + 1, len(pathData.base.Edges)):
+ edge = pathData.base.Edges[i]
+ (currentLength, lastTabLength) = self.executeTabLength(i, edge, currentLength, lastTabLength, tabDistance, minLength, tabs)
+ for i in range(0, startIndex):
+ edge = pathData.base.Edges[i]
+ (currentLength, lastTabLength) = self.executeTabLength(i, edge, currentLength, lastTabLength, tabDistance, minLength, tabs)
+
+ self.tabs = tabs
+ locs = {}
+
+ tabID = 0
+ for (i, count) in tabs.iteritems():
+ edge = pathData.base.Edges[i]
+ #debugMarker(edge.Vertexes[0].Point, 'base', (1.0, 0.0, 0.0), 0.2)
+ #debugMarker(edge.Vertexes[1].Point, 'base', (0.0, 1.0, 0.0), 0.2)
+ distance = (edge.LastParameter - edge.FirstParameter) / count
+ for j in range(0, count):
+ tab = edge.Curve.value((j+0.5) * distance)
+ tabID += 1
+ locs[(tab.x, tab.y)] = tabID
+ if not tabID in obj.Blacklist:
+ debugMarker(tab, "tab-%02d" % tabID , (1.0, 0.0, 1.0), 0.5)
+
+ self.tabLocations = locs
+ #debugMarker(pathData.base.CenterOfMass, 'cog', (0., 0., 0.), 0.5)
+
+ obj.Path = obj.Base.Path
+
+ def executeTabLength(self, index, edge, currentLength, lastTabLength, tabDistance, minLength, tabs):
+ tabCount = 0
+ currentLength += edge.Length
+ if edge.Length > minLength:
+ while lastTabLength + tabDistance < currentLength:
+ tabCount += 1
+ lastTabLength += tabDistance
+ if tabCount > 0:
+ #print(" index=%d -> count=%d" % (index, tabCount))
+ tabs[index] = tabCount
+ else:
+ print(" skipping=%-2d (%.2f)" % (index, edge.Length))
+ return (currentLength, lastTabLength)
+
+ def holdingTabsLocations(self, obj):
+ if hasattr(self, "tabLocations") and self.tabLocations:
+ return self.tabLocations
+ return {}
+
+ def setup(self, obj):
+ if not hasattr(self, "pathData") or not self.pathData:
+ try:
+ pathData = PathData(obj)
+ except ValueError:
+ FreeCAD.Console.PrintError(translate("PathDressup_HoldingTabs", "Cannot insert holding tabs for this path - please select a Profile path\n"))
+ return None
+
+ # setup the object's properties, in case they're not set yet
+ obj.Count = self.tabCount(obj)
+ obj.Angle = self.tabAngle(obj)
+ obj.Blacklist = self.tabBlacklist(obj)
+
+ # if the heigt isn't set, use the height of the path
+ if not hasattr(obj, "Height") or not obj.Height:
+ obj.Height = pathData.maxZ - pathData.minZ
+ # try and take an educated guess at the width
+ if not hasattr(obj, "Width") or not obj.Width:
+ width = sorted(pathData.base.Edges, key=lambda e: -e.Length)[0].Length / 10
+ while obj.Count > len([e for e in pathData.base.Edges if e.Length > 3*width]):
+ width = widht / 2
+ obj.Width = width
+
+ # and the tool radius, not sure yet if it's needed
+ self.toolRadius = 5
+ toolLoad = PathUtils.getLastToolLoad(obj)
+ if toolLoad is None or toolLoad.ToolNumber == 0:
+ self.toolRadius = 5
+ else:
+ tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
+ if not tool or tool.Diameter == 0:
+ self.toolRadius = 5
+ else:
+ self.toolRadius = tool.Diameter / 2
+ self.pathData = pathData
+ return self.pathData
+
+ def tabCount(self, obj):
+ if hasattr(obj, "Count") and obj.Count:
+ return obj.Count
+ return 4
+
+ def tabHeight(self, obj):
+ if hasattr(obj, "Height") and obj.Height:
+ return obj.Height
+ return 1
+
+ def tabWidth(self, obj):
+ if hasattr(obj, "Width") and obj.Width:
+ return obj.Width
+ return 3
+
+ def tabAngle(self, obj):
+ if hasattr(obj, "Angle") and obj.Angle:
+ return obj.Angle
+ return 90
+
+ def tabBlacklist(self, obj):
+ if hasattr(obj, "Blacklist") and obj.Blacklist:
+ return obj.Blacklist
+ return []
+
+class TaskPanel:
+ DataId = QtCore.Qt.ItemDataRole.UserRole
+
+ def __init__(self, obj):
+ self.obj = obj
+ self.form = FreeCADGui.PySideUic.loadUi(":/panels/HoldingTabsEdit.ui")
+ FreeCAD.ActiveDocument.openTransaction(translate("PathDressup_HoldingTabs", "Edit HoldingTabs Dress-up"))
+
+ def reject(self):
+ FreeCAD.ActiveDocument.abortTransaction()
+ FreeCADGui.Control.closeDialog()
+ FreeCAD.ActiveDocument.recompute()
+ FreeCADGui.Selection.removeObserver(self.s)
+
+ def accept(self):
+ FreeCAD.ActiveDocument.commitTransaction()
+ FreeCADGui.ActiveDocument.resetEdit()
+ FreeCADGui.Control.closeDialog()
+ FreeCAD.ActiveDocument.recompute()
+ FreeCADGui.Selection.removeObserver(self.s)
+ FreeCAD.ActiveDocument.recompute()
+
+ def open(self):
+ self.s = SelObserver()
+ # install the function mode resident
+ FreeCADGui.Selection.addObserver(self.s)
+
+ def updateTabList(self):
+ blacklist = self.obj.Proxy.tabBlacklist(self.obj)
+ itemList = []
+ for (x,y), id in self.obj.Proxy.holdingTabsLocations(self.obj).iteritems():
+ label = "%d: (x=%.2f, y=%.2f)" % (id, x, y)
+ item = QtGui.QListWidgetItem(label)
+ if id in blacklist:
+ item.setCheckState(QtCore.Qt.CheckState.Unchecked)
+ else:
+ item.setCheckState(QtCore.Qt.CheckState.Checked)
+ item.setFlags(QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsUserCheckable)
+ item.setData(self.DataId, id)
+ itemList.append(item)
+ self.form.lwHoldingTabs.clear()
+ for item in sorted(itemList, key=lambda item: item.data(self.DataId)):
+ self.form.lwHoldingTabs.addItem(item)
+
+ def getFields(self):
+ self.obj.Count = self.form.sbCount.value()
+ self.obj.Height = self.form.dsbHeight.value()
+ self.obj.Width = self.form.dsbWidth.value()
+ self.obj.Angle = self.form.dsbAngle.value()
+ blacklist = []
+ for i in range(0, self.form.lwHoldingTabs.count()):
+ item = self.form.lwHoldingTabs.item(i)
+ if item.checkState() == QtCore.Qt.CheckState.Unchecked:
+ blacklist.append(item.data(self.DataId))
+ self.obj.Blacklist = sorted(blacklist)
+ self.obj.Proxy.execute(self.obj)
+
+ def update(self):
+ if True or debugDressup:
+ for obj in FreeCAD.ActiveDocument.Objects:
+ if obj.Name.startswith('tab'):
+ FreeCAD.ActiveDocument.removeObject(obj.Name)
+ self.getFields()
+ self.updateTabList()
+ FreeCAD.ActiveDocument.recompute()
+
+ def setupSpinBox(self, widget, val, decimals = 2):
+ widget.setMinimum(0)
+ if decimals:
+ widget.setDecimals(decimals)
+ widget.setValue(val)
+
+
+ def setFields(self):
+ self.setupSpinBox(self.form.sbCount, self.obj.Proxy.tabCount(self.obj), None)
+ self.setupSpinBox(self.form.dsbHeight, self.obj.Proxy.tabHeight(self.obj))
+ self.setupSpinBox(self.form.dsbWidth, self.obj.Proxy.tabWidth(self.obj))
+ self.setupSpinBox(self.form.dsbAngle, self.obj.Proxy.tabAngle(self.obj))
+ self.updateTabList()
+
+ def setupUi(self):
+ self.setFields()
+ self.form.sbCount.valueChanged.connect(self.update)
+ self.form.dsbHeight.valueChanged.connect(self.update)
+ self.form.dsbWidth.valueChanged.connect(self.update)
+ self.form.dsbAngle.valueChanged.connect(self.update)
+ self.form.lwHoldingTabs.itemChanged.connect(self.update)
+
+class SelObserver:
+ def __init__(self):
+ import PathScripts.PathSelection as PST
+ PST.eselect()
+
+ def __del__(self):
+ import PathScripts.PathSelection as PST
+ PST.clear()
+
+ def addSelection(self, doc, obj, sub, pnt):
+ FreeCADGui.doCommand('Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')')
+ FreeCADGui.updateGui()
+
+class ViewProviderDressup:
+
+ def __init__(self, vobj):
+ vobj.Proxy = self
+
+ def attach(self, vobj):
+ self.Object = vobj.Object
+ return
+
+ def claimChildren(self):
+ for i in self.Object.Base.InList:
+ if hasattr(i, "Group"):
+ group = i.Group
+ for g in group:
+ if g.Name == self.Object.Base.Name:
+ group.remove(g)
+ i.Group = group
+ print i.Group
+ #FreeCADGui.ActiveDocument.getObject(obj.Base.Name).Visibility = False
+ return [self.Object.Base]
+
+ def setEdit(self, vobj, mode=0):
+ FreeCADGui.Control.closeDialog()
+ panel = TaskPanel(vobj.Object)
+ FreeCADGui.Control.showDialog(panel)
+ panel.setupUi()
+ return True
+
+ def __getstate__(self):
+ return None
+
+ def __setstate__(self, state):
+ return None
+
+ def onDelete(self, arg1=None, arg2=None):
+ '''this makes sure that the base operation is added back to the project and visible'''
+ FreeCADGui.ActiveDocument.getObject(arg1.Object.Base.Name).Visibility = True
+ PathUtils.addToJob(arg1.Object.Base)
+ return True
+
+class CommandPathDressupHoldingTabs:
+
+ def GetResources(self):
+ return {'Pixmap': 'Path-Dressup',
+ 'MenuText': QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTabs", "HoldingTabs Dress-up"),
+ 'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTabs", "Creates a HoldingTabs Dress-up object from a selected path")}
+
+ def IsActive(self):
+ if FreeCAD.ActiveDocument is not None:
+ for o in FreeCAD.ActiveDocument.Objects:
+ if o.Name[:3] == "Job":
+ return True
+ return False
+
+ def Activated(self):
+
+ # check that the selection contains exactly what we want
+ selection = FreeCADGui.Selection.getSelection()
+ if len(selection) != 1:
+ FreeCAD.Console.PrintError(translate("PathDressup_HoldingTabs", "Please select one path object\n"))
+ return
+ baseObject = selection[0]
+ if not baseObject.isDerivedFrom("Path::Feature"):
+ FreeCAD.Console.PrintError(translate("PathDressup_HoldingTabs", "The selected object is not a path\n"))
+ return
+ if baseObject.isDerivedFrom("Path::FeatureCompoundPython"):
+ FreeCAD.Console.PrintError(translate("PathDressup_HoldingTabs", "Please select a Profile object"))
+ return
+
+ # everything ok!
+ FreeCAD.ActiveDocument.openTransaction(translate("PathDressup_HoldingTabs", "Create HoldingTabs Dress-up"))
+ FreeCADGui.addModule("PathScripts.PathDressupHoldingTabs")
+ FreeCADGui.addModule("PathScripts.PathUtils")
+ FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "HoldingTabsDressup")')
+ FreeCADGui.doCommand('dbo = PathScripts.PathDressupHoldingTabs.ObjectDressup(obj)')
+ FreeCADGui.doCommand('obj.Base = FreeCAD.ActiveDocument.' + selection[0].Name)
+ FreeCADGui.doCommand('PathScripts.PathDressupHoldingTabs.ViewProviderDressup(obj.ViewObject)')
+ FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
+ FreeCADGui.doCommand('Gui.ActiveDocument.getObject(obj.Base.Name).Visibility = False')
+ FreeCADGui.doCommand('dbo.setup(obj)')
+ FreeCAD.ActiveDocument.commitTransaction()
+ FreeCAD.ActiveDocument.recompute()
+
+if FreeCAD.GuiUp:
+ # register the FreeCAD command
+ FreeCADGui.addCommand('PathDressup_HoldingTabs', CommandPathDressupHoldingTabs())
+
+FreeCAD.Console.PrintLog("Loading PathDressupHoldingTabs... done\n")