diff --git a/src/Mod/Path/Gui/Resources/panels/DogboneEdit.ui b/src/Mod/Path/Gui/Resources/panels/DogboneEdit.ui
index 336ace17e..11fec2817 100644
--- a/src/Mod/Path/Gui/Resources/panels/DogboneEdit.ui
+++ b/src/Mod/Path/Gui/Resources/panels/DogboneEdit.ui
@@ -10,18 +10,15 @@
486
-
-
- 0
- 400
-
-
Dogbones
- -
+
-
+
+ QFrame::NoFrame
+
0
@@ -31,7 +28,7 @@
0
0
334
- 410
+ 439
@@ -137,23 +134,15 @@
-
-
-
-
-
- 0
- 0
- 334
- 410
-
-
-
- Selection
-
-
- -
-
+
-
+
+
+
+ 0
+ 0
+
+
+
diff --git a/src/Mod/Path/PathScripts/DogboneDressup.py b/src/Mod/Path/PathScripts/DogboneDressup.py
index ff42bfadd..faf005774 100644
--- a/src/Mod/Path/PathScripts/DogboneDressup.py
+++ b/src/Mod/Path/PathScripts/DogboneDressup.py
@@ -152,6 +152,7 @@ class ObjectDressup:
obj.Shape = ObjectDressup.LabelDogbone
obj.addProperty("App::PropertyIntegerList", "BoneBlacklist", "", "Bones that aren't dressed up")
obj.setEditorMode('BoneBlacklist', 2) # hide this one
+ obj.BoneBlacklist = []
obj.Proxy = self
def __getstate__(self):
@@ -238,19 +239,37 @@ class ObjectDressup:
inChordIsShorter = inChord.getLength() < outChord.getLength()
return self.tboneEdgeCommands(obj, inChord, outChord, inChordIsShorter)
+ def isBoneBlacklisted(self, obj, boneId, loc):
+ blacklisted = False
+ if boneId in obj.BoneBlacklist:
+ blacklisted = True
+ elif loc in self.locationBlacklist:
+ obj.BoneBlacklist.append(boneId)
+ blacklisted = True
+ if blacklisted:
+ self.locationBlacklist.add(loc)
+ return blacklisted
+
# Generate commands necessary to execute the dogbone
- def dogboneCommands(self, obj, inChord, outChord):
- if obj.Shape == ObjectDressup.LabelDogbone:
- return self.dogbone(obj, inChord, outChord)
- if obj.Shape == ObjectDressup.LabelTbone_H:
- return self.tboneHorizontal(obj, inChord, outChord)
- if obj.Shape == ObjectDressup.LabelTbone_V:
- return self.tboneVertical(obj, inChord, outChord)
- if obj.Shape == ObjectDressup.LabelTbone_L:
- return self.tboneLongEdge(obj, inChord, outChord)
- if obj.Shape == ObjectDressup.LabelTbone_S:
- return self.tboneShortEdge(obj, inChord, outChord)
- return self.debugCircleBone(obj, inChord, outChord)
+ def boneCommands(self, obj, boneId, inChord, outChord):
+ loc = (inChord.End.x, inChord.End.y)
+ enabled = not self.isBoneBlacklisted(obj, boneId, loc)
+ self.bones.append((boneId, loc, enabled))
+
+ if enabled:
+ if obj.Shape == ObjectDressup.LabelDogbone:
+ return self.dogbone(obj, inChord, outChord)
+ if obj.Shape == ObjectDressup.LabelTbone_H:
+ return self.tboneHorizontal(obj, inChord, outChord)
+ if obj.Shape == ObjectDressup.LabelTbone_V:
+ return self.tboneVertical(obj, inChord, outChord)
+ if obj.Shape == ObjectDressup.LabelTbone_L:
+ return self.tboneLongEdge(obj, inChord, outChord)
+ if obj.Shape == ObjectDressup.LabelTbone_S:
+ return self.tboneShortEdge(obj, inChord, outChord)
+ return self.debugCircleBone(obj, inChord, outChord)
+ else:
+ return []
def execute(self, obj):
if not obj.Base:
@@ -269,19 +288,24 @@ class ObjectDressup:
lastCommand = None # the command that generated the last chord
oddsAndEnds = [] # track chords that are connected to plunges - in case they form a loop
+ boneId = 1
+ self.bones = []
+ self.locationBlacklist = set()
+
for thisCmd in obj.Base.Path.Commands:
if thisCmd.Name in movecommands:
thisChord = lastChord.moveToParameters(thisCmd.Parameters)
thisIsACandidate = self.canAttachDogbone(thisCmd, thisChord)
if thisIsACandidate and lastCommand and self.shouldInsertDogbone(obj, lastChord, thisChord):
- dogbone = self.dogboneCommands(obj, lastChord, thisChord)
- commands.extend(dogbone)
+ commands.extend(self.boneCommands(obj, boneId, lastChord, thisChord))
+ boneId = boneId + 1
if lastCommand and thisChord.isAPlungeMove():
for chord in (chord for chord in oddsAndEnds if lastChord.connectsTo(chord)):
if self.shouldInsertDogbone(obj, lastChord, chord):
- commands.extend(self.dogboneCommands(obj, lastChord, chord))
+ commands.extend(self.boneCommands(obj, boneId,lastChord, chord))
+ boneId = boneId + 1
if lastChord.isAPlungeMove() and thisIsACandidate:
oddsAndEnds.append(thisChord)
@@ -305,6 +329,7 @@ class ObjectDressup:
elif obj.Base.Side == 'Right':
obj.Side = 'Left'
else:
+ # This will cause an error, which is fine for now 'cause I don't know what to do here
obj.Side = 'On'
self.toolRadius = 5
@@ -318,8 +343,18 @@ class ObjectDressup:
else:
self.toolRadius = tool.Diameter / 2
- def boneStateList(self):
- return [ (FreeCAD.Vector(0,0,17), False), (FreeCAD.Vector(1,1,23), True), (FreeCAD.Vector(7,9,0), True) ]
+ def boneStateList(self, obj):
+ state = {}
+ # If the receiver was loaded from file, then it never generated the bone list.
+ if not hasattr(self, 'bones'):
+ self.execute(obj)
+ for (id, loc, enabled) in self.bones:
+ item = state.get(loc)
+ if item:
+ item[1].append(id)
+ else:
+ state[loc] = (enabled, [id])
+ return state
class ViewProviderDressup:
@@ -404,6 +439,9 @@ class CommandDogboneDressup:
FreeCAD.ActiveDocument.recompute()
class TaskPanel:
+ DataIds = QtCore.Qt.ItemDataRole.UserRole
+ DataKey = QtCore.Qt.ItemDataRole.UserRole + 1
+
def __init__(self, obj):
self.obj = obj
self.form = FreeCADGui.PySideUic.loadUi(":/panels/DogboneEdit.ui")
@@ -415,6 +453,7 @@ class TaskPanel:
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.Selection.removeObserver(self.s)
+ FreeCAD.ActiveDocument.recompute()
def reject(self):
FreeCADGui.Control.closeDialog()
@@ -424,11 +463,16 @@ class TaskPanel:
def getFields(self):
self.obj.Shape = str(self.form.shape.currentText())
self.obj.Side = str(self.form.side.currentText())
+ blacklist = []
+ for i in range(0, self.form.bones.count()):
+ item = self.form.bones.item(i)
+ if item.checkState() == QtCore.Qt.CheckState.Unchecked:
+ blacklist.extend(item.data(self.DataIds))
+ self.obj.BoneBlacklist = sorted(blacklist)
self.obj.Proxy.execute(self.obj)
def updateModel(self):
self.getFields()
- self.obj.Proxy.execute(self.obj)
FreeCAD.ActiveDocument.recompute()
def comboSelectText(self, combo, text):
@@ -437,17 +481,23 @@ class TaskPanel:
combo.setCurrentIndex(index)
def setFields(self):
+ # If the dressup was loaded from disk the Proxy might not be seupt properly
self.comboSelectText(self.form.shape, self.obj.Shape)
self.comboSelectText(self.form.side, self.obj.Side)
self.form.bones.clear()
- for (pos, enabled) in self.obj.Proxy.boneStateList():
- lbl = '(%.2f, %2f, *)' % (pos.x, pos.y)
- item = QtGui.QListWidgetItem(lbl, self.form.bones)
+ itemList = []
+ for loc, state in self.obj.Proxy.boneStateList(self.obj).iteritems():
+ lbl = '(%.2f, %.2f): %s' % (loc[0], loc[1], ','.join(str(id) for id in state[1]))
+ item = QtGui.QListWidgetItem(lbl)
item.setFlags(QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsUserCheckable)
- if enabled:
+ if state[0]:
item.setCheckState(QtCore.Qt.CheckState.Checked)
else:
item.setCheckState(QtCore.Qt.CheckState.Unchecked)
+ item.setData(self.DataIds, state[1])
+ item.setData(self.DataKey, state[1][0])
+ itemList.append(item)
+ for item in sorted(itemList, key=lambda item: item.data(self.DataKey)):
self.form.bones.addItem(item)
def open(self):
@@ -459,10 +509,11 @@ class TaskPanel:
return int(QtGui.QDialogButtonBox.Ok)
def setupUi(self):
+ self.setFields()
+ # now that the form is filled, setup the signal handlers
self.form.shape.currentIndexChanged.connect(self.updateModel)
self.form.side.currentIndexChanged.connect(self.updateModel)
- self.form.bones.itemActivated.connect(self.updateModel)
- self.setFields()
+ self.form.bones.itemChanged.connect(self.updateModel)
class SelObserver:
def __init__(self):