Basic UI for holding tags.

This commit is contained in:
Markus Lampert 2017-01-01 19:23:19 -08:00
parent 807cf80a77
commit 8efbe9e645

View File

@ -32,6 +32,7 @@ import math
import cProfile
import time
from DraftGui import todo
from PathScripts import PathUtils
from PathScripts.PathGeom import *
from PySide import QtCore, QtGui
@ -468,11 +469,11 @@ class PathData:
if width:
W = width
else:
W = self.tagWidth()
W = self.defaultTagWidth()
if height:
H = height
else:
H = self.tagHeight()
H = self.defaultTagHeight()
# start assigning tags on the longest segment
@ -539,20 +540,17 @@ class PathData:
return (currentLength, lastTagLength)
def tagHeight(self):
def defaultTagHeight(self):
if hasattr(self.obj, 'Base') and hasattr(self.obj.Base, 'StartDepth') and hasattr(self.obj.Base, 'FinalDepth'):
return self.obj.Base.StartDepth - self.obj.Base.FinalDepth
return (self.obj.Base.StartDepth - self.obj.Base.FinalDepth).Value
return self.maxZ - self.minZ
def tagWidth(self):
def defaultTagWidth(self):
return self.shortestAndLongestPathEdge()[1].Length / 10
def tagAngle(self):
def defaultTagAngle(self):
return 90
def pathLength(self):
return self.base.Length
def sortedTags(self, tags):
ordered = []
for edge in self.base.Edges:
@ -570,8 +568,11 @@ class ObjectDressup:
def __init__(self, obj):
self.obj = obj
obj.addProperty("App::PropertyLink", "Base","Base", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "The base path to modify"))
obj.addProperty("App::PropertyStringList", "Tags", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_holdingTags", "Inserted tags"))
obj.setEditorMode("Tags", 2)
obj.addProperty("App::PropertyFloat", "Width", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "Width of tags."))
obj.addProperty("App::PropertyFloat", "Height", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "Height of tags."))
obj.addProperty("App::PropertyFloat", "Angle", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "Angle of tag plunge and ascent."))
obj.addProperty("App::PropertyVectorList", "Positions", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "Locations of insterted holding tags"))
obj.addProperty("App::PropertyIntegerList", "Disabled", "Tag", QtCore.QT_TRANSLATE_NOOP("PathDressup_HoldingTags", "Ids of disabled holding tags"))
obj.Proxy = self
def __getstate__(self):
@ -580,8 +581,14 @@ class ObjectDressup:
def __setstate__(self, state):
return None
def generateTags(self, obj, count=None, width=None, height=None, angle=90, spacing=None):
return self.pathData.generateTags(obj, count, width, height, angle, spacing)
def generateTags(self, obj, count):
if hasattr(self, "pathData"):
self.tags = self.pathData.generateTags(obj, count, obj.Width, obj.Height, obj.Angle, None)
obj.Positions = [tag.originAt(0) for tag in self.tags]
obj.Disabled = []
else:
self.setup(obj, count)
self.execute(obj)
def isValidTagStartIntersection(self, edge, i):
if PathGeom.pointsCoincide(i, edge.valueAt(edge.LastParameter)):
@ -675,103 +682,87 @@ class ObjectDressup:
print("execute - no pathData")
return
if hasattr(obj, 'Tags') and obj.Tags:
if False and self.fingerprint == obj.Tags:
print("execute - cache valid")
return
print("execute - tags from property")
tags = [Tag.FromString(tag) for tag in obj.Tags]
else:
print("execute - default tags")
tags = self.generateTags(obj, 4.)
self.tags = []
if hasattr(obj, "Positions"):
for i, pos in enumerate(obj.Positions):
tag = Tag(pos.x, pos.y, obj.Width, obj.Height, obj.Angle, not i in obj.Disabled)
tag.createSolidsAt(pathData.minZ, self.toolRadius)
self.tags.append(tag)
if not tags:
if not self.tags:
print("execute - no tags")
self.tags = []
obj.Path = obj.Base.Path
return
print("execute - %d tags" % (len(tags)))
tags = pathData.sortedTags(tags)
self.setTags(obj, tags, False)
for tag in tags:
tag.createSolidsAt(pathData.minZ, self.toolRadius)
tagID = 0
for tag in tags:
tagID += 1
if tag.enabled:
#print("x=%s, y=%s, z=%s" % (tag.x, tag.y, pathData.minZ))
#debugMarker(FreeCAD.Vector(tag.x, tag.y, pathData.minZ), "tag-%02d" % tagID , (1.0, 0.0, 1.0), 0.5)
if tag.angle != 90:
debugCone(tag.originAt(pathData.minZ), tag.r1, tag.r2, tag.actualHeight, "tag-%02d" % tagID)
else:
debugCylinder(tag.originAt(pathData.minZ), tag.fullWidth()/2, tag.actualHeight, "tag-%02d" % tagID)
if debugDressup:
for tag in self.tags:
tagID += 1
if tag.enabled:
print("x=%s, y=%s, z=%s" % (tag.x, tag.y, pathData.minZ))
debugMarker(FreeCAD.Vector(tag.x, tag.y, pathData.minZ), "tag-%02d" % tagID , (1.0, 0.0, 1.0), 0.5)
if tag.angle != 90:
debugCone(tag.originAt(pathData.minZ), tag.r1, tag.r2, tag.actualHeight, "tag-%02d" % tagID)
else:
debugCylinder(tag.originAt(pathData.minZ), tag.fullWidth()/2, tag.actualHeight, "tag-%02d" % tagID)
self.fingerprint = [tag.toString() for tag in tags]
self.tags = tags
obj.Path = self.createPath(pathData.edges, tags, pathData.rapid)
obj.Path = self.createPath(pathData.edges, self.tags, pathData.rapid)
print("execute - done")
def setTags(self, obj, tags, update = True):
print("setTags(%d, %d)" % (len(tags), update))
#for t in tags:
# print(" .... %s" % t.toString())
obj.Tags = [tag.toString() for tag in tags]
if update:
self.execute(obj)
def getTags(self, obj):
if not hasattr(self, 'tags'):
self.execute(obj)
return self.tags
def setup(self, obj):
if True or not hasattr(self, "pathData") or not self.pathData:
try:
pathData = PathData(obj)
except ValueError:
FreeCAD.Console.PrintError(translate("PathDressup_HoldingTags", "Cannot insert holding tags for this path - please select a Profile path\n"))
return None
def setup(self, obj, generate=None):
print("setup")
self.obj = obj
try:
pathData = PathData(obj)
except ValueError:
FreeCAD.Console.PrintError(translate("PathDressup_HoldingTags", "Cannot insert holding tags for this path - please select a Profile path\n"))
return None
self.toolRadius = 5
toolLoad = PathUtils.getLastToolLoad(obj)
if toolLoad is None or toolLoad.ToolNumber == 0:
self.toolRadius = 5
toolLoad = PathUtils.getLastToolLoad(obj)
if toolLoad is None or toolLoad.ToolNumber == 0:
else:
tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
if not tool or tool.Diameter == 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
self.toolRadius = tool.Diameter / 2
self.pathData = pathData
if generate:
obj.Height = self.pathData.defaultTagHeight()
obj.Width = self.pathData.defaultTagWidth()
obj.Angle = self.pathData.defaultTagAngle()
self.generateTags(obj, generate)
return self.pathData
def getHeight(self, obj):
return self.pathData.tagHeight()
def getWidth(self, obj):
return self.pathData.tagWidth()
def getAngle(self, obj):
return self.pathData.tagAngle()
def getPathLength(self, obj):
return self.pathData.pathLength()
def setXyEnabled(self, triples):
positions = []
disabled = []
for i, (x, y, enabled) in enumerate(triples):
positions.append(FreeCAD.Vector(x, y, 0))
if not enabled:
disabled.append(i)
self.obj.Positions = positions
self.obj.Disabled = disabled
self.execute(self.obj)
class TaskPanel:
DataX = QtCore.Qt.ItemDataRole.UserRole
DataY = QtCore.Qt.ItemDataRole.UserRole + 1
def __init__(self, obj):
def __init__(self, obj, jvoVisibility=None):
self.obj = obj
self.obj.Proxy.obj = obj
self.form = FreeCADGui.PySideUic.loadUi(":/panels/HoldingTagsEdit.ui")
FreeCAD.ActiveDocument.openTransaction(translate("PathDressup_HoldingTags", "Edit HoldingTags Dress-up"))
self.jvo = PathUtils.findParentJob(obj).ViewObject
self.jvoVisible = self.jvo.isVisible()
if self.jvoVisible:
self.jvo.hide()
if jvoVisibility is None:
FreeCAD.ActiveDocument.openTransaction(translate("PathDressup_HoldingTags", "Edit HoldingTags Dress-up"))
self.jvoVisible = self.jvo.isVisible()
if self.jvoVisible:
self.jvo.hide()
else:
self.jvoVisible = jvoVisibility
def reject(self):
print("reject")
@ -782,51 +773,64 @@ class TaskPanel:
print("accept")
self.getFields()
FreeCAD.ActiveDocument.commitTransaction()
FreeCADGui.ActiveDocument.resetEdit()
self.cleanup()
FreeCAD.ActiveDocument.recompute()
def cleanup(self):
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.Selection.removeObserver(self.s)
if self.jvoVisible:
self.jvo.show()
def closeDialog(self):
print("closed")
def open(self):
self.s = SelObserver()
# install the function mode resident
FreeCADGui.Selection.addObserver(self.s)
def getFields(self):
width = self.form.dsbWidth.value()
height = self.form.dsbHeight.value()
angle = self.form.dsbAngle.value()
def getTags(self, includeCurrent):
tags = []
index = self.form.lwTags.currentRow()
for i in range(0, self.form.lwTags.count()):
item = self.form.lwTags.item(i)
enabled = item.checkState() == QtCore.Qt.CheckState.Checked
x = item.data(self.DataX)
y = item.data(self.DataY)
tags.append(Tag(x, y, width, height, angle, enabled))
self.obj.Proxy.setTags(self.obj, tags)
print("(%.2f, %.2f) i=%d/%s" % (x, y, i, index))
if includeCurrent or i != index:
tags.append((x, y, enabled))
return tags
def getTagParameters(self):
self.obj.Width = self.form.dsbWidth.value()
self.obj.Height = self.form.dsbHeight.value()
self.obj.Angle = self.form.dsbAngle.value()
def getFields(self):
self.getTagParameters()
tags = self.getTags(True)
self.obj.Proxy.setXyEnabled(tags)
def updateTagsView(self):
self.tags = self.obj.Proxy.getTags(self.obj)
print("updateTagsView: %d" % (len(self.tags)))
print("updateTagsView")
self.form.lwTags.blockSignals(True)
self.form.lwTags.clear()
for tag in self.tags:
lbl = "(%.2f, %.2f)" % (tag.x, tag.y)
for i, pos in enumerate(self.obj.Positions):
lbl = "%d: (%.2f, %.2f)" % (i, pos.x, pos.y)
item = QtGui.QListWidgetItem(lbl)
item.setData(self.DataX, tag.x)
item.setData(self.DataY, tag.y)
if tag.enabled:
item.setCheckState(QtCore.Qt.CheckState.Checked)
else:
item.setData(self.DataX, pos.x)
item.setData(self.DataY, pos.y)
if i in self.obj.Disabled:
item.setCheckState(QtCore.Qt.CheckState.Unchecked)
else:
item.setCheckState(QtCore.Qt.CheckState.Checked)
flags = QtCore.Qt.ItemFlag.ItemIsSelectable
flags |= QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsUserCheckable
flags |= QtCore.Qt.ItemFlag.ItemIsEnabled
flags |= QtCore.Qt.ItemFlag.ItemIsUserCheckable
item.setFlags(flags)
self.form.lwTags.addItem(item)
self.form.lwTags.blockSignals(False)
@ -843,22 +847,13 @@ class TaskPanel:
self.cleanupUI()
count = self.form.sbCount.value()
width = self.form.dsbWidth.value()
height = self.form.dsbHeight.value()
angle = self.form.dsbAngle.value()
self.obj.Proxy.generateTags(self.obj, count)
tags = self.obj.Proxy.generateTags(self.obj, count, width, height, angle)
self.obj.Proxy.setTags(self.obj, tags)
self.updateTagsView()
#if debugDressup:
# # this causes a big of an echo and a double click on the spin buttons, don't know why though
# FreeCAD.ActiveDocument.recompute()
# def autoApply(self):
# print("autoApply")
# if self.form.cbAutoApply.checkState() == QtCore.Qt.CheckState.Checked:
# self.whenApplyClicked()
def updateModel(self):
self.getFields()
@ -876,19 +871,23 @@ class TaskPanel:
self.form.pbDelete.setEnabled(not item is None)
def deleteSelectedTag(self):
item = self.form.lwTags.currentItem()
if item:
x = item.data(self.DataX)
y = item.data(self.DataY)
tags = filter(lambda t: t.x != x or t.y != y, self.tags)
self.obj.Proxy.setTags(self.obj, tags)
self.updateTagsView()
self.obj.Proxy.setXyEnabled(self.getTags(False))
self.updateTagsView()
def addNewTagAt(self, point, what):
print("%s '%s'" %( point, what.Name))
if what == self.obj:
print("%s '%s'" %( point, what.Name))
tags = self.tags
tags.append((point.x, point.y, True))
self.obj.Proxy.setXyEnabled(tags)
panel = TaskPanel(self.obj, self.jvoVisible)
todo.delay(FreeCADGui.Control.closeDialog, None)
todo.delay(FreeCADGui.Control.showDialog, panel)
todo.delay(panel.setupUi, None)
def addNewTag(self):
FreeCADGui.Snapper.getPoint(callback=self.addNewTagAt)
self.tags = self.getTags(True)
FreeCADGui.Snapper.getPoint(callback=self.addNewTagAt, extradlg=[self])
def setupSpinBox(self, widget, val, decimals = 2):
widget.setMinimum(0)
@ -898,10 +897,10 @@ class TaskPanel:
def setFields(self):
self.updateTagsView()
self.setupSpinBox(self.form.sbCount, len(self.tags), None)
self.setupSpinBox(self.form.dsbHeight, self.obj.Proxy.getHeight(self.obj))
self.setupSpinBox(self.form.dsbWidth, self.obj.Proxy.getWidth(self.obj))
self.setupSpinBox(self.form.dsbAngle, self.obj.Proxy.getAngle(self.obj), 0)
self.setupSpinBox(self.form.sbCount, len(self.obj.Positions), None)
self.setupSpinBox(self.form.dsbHeight, self.obj.Height)
self.setupSpinBox(self.form.dsbWidth, self.obj.Width)
self.setupSpinBox(self.form.dsbAngle, self.obj.Angle, 0)
self.form.dsbAngle.setMaximum(90)
self.form.dsbAngle.setSingleStep(5.)
@ -947,7 +946,7 @@ class SelObserver:
PST.clear()
def addSelection(self, doc, obj, sub, pnt):
FreeCADGui.doCommand('Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')')
#FreeCADGui.doCommand('Gui.Selection.addSelection(FreeCAD.ActiveDocument.' + obj + ')')
FreeCADGui.updateGui()
class ViewProviderDressup:
@ -1029,7 +1028,7 @@ class CommandPathDressupHoldingTags:
FreeCADGui.doCommand('PathScripts.PathDressupHoldingTags.ViewProviderDressup(obj.ViewObject)')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCADGui.doCommand('Gui.ActiveDocument.getObject(obj.Base.Name).Visibility = False')
FreeCADGui.doCommand('dbo.setup(obj)')
FreeCADGui.doCommand('dbo.setup(obj, 4.)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()