|
|
|
@ -1,118 +1,21 @@
|
|
|
|
|
from includes import *
|
|
|
|
|
from tree import Node
|
|
|
|
|
from geosolver import GeometricCluster
|
|
|
|
|
from parameters import Settings
|
|
|
|
|
|
|
|
|
|
class CVCluster(QtGui.QGraphicsItem, Node):
|
|
|
|
|
class CVCluster(QtGui.QGraphicsItem):
|
|
|
|
|
""" Visualisation of the clusters (nodes) in the decompositionView """
|
|
|
|
|
def __init__(self, compView, parentNode, id, parent=None):
|
|
|
|
|
QtGui.QGraphicsItem.__init__(self, parent)
|
|
|
|
|
Node.__init__(self, parentNode)
|
|
|
|
|
def __init__(self, compView, cluster, x,y):
|
|
|
|
|
QtGui.QGraphicsItem.__init__(self)
|
|
|
|
|
|
|
|
|
|
self.compositionView = compView
|
|
|
|
|
self.setFlags(QtGui.QGraphicsItem.ItemIsSelectable)
|
|
|
|
|
self.setAcceptsHoverEvents(True)
|
|
|
|
|
self.startAngle = 0
|
|
|
|
|
self.spanAngle = 0
|
|
|
|
|
self.paintRect = QtCore.QRectF(0, 0, self.width, self.height)
|
|
|
|
|
self.boundary = QtCore.QRectF(0.0, 0.0, 0.0, 0.0)
|
|
|
|
|
self.fixGraphic = QtGui.QGraphicsSimpleTextItem("F", self)
|
|
|
|
|
self.cluster = cluster
|
|
|
|
|
self.position = QtCore.QPointF(x, y)
|
|
|
|
|
|
|
|
|
|
self.identifier = id
|
|
|
|
|
|
|
|
|
|
self.bezierCurve = None
|
|
|
|
|
self.initAngles()
|
|
|
|
|
self.bound = QtCore.QRectF()
|
|
|
|
|
self.updateBound()
|
|
|
|
|
self.flag = None
|
|
|
|
|
self.clusterHighlight = None
|
|
|
|
|
self.permCluster = None
|
|
|
|
|
self.clusterActive = False
|
|
|
|
|
self.fixGraphic.hide()
|
|
|
|
|
|
|
|
|
|
def initAngles(self):
|
|
|
|
|
""" Initialize the angles for the visual representation of the nodes, these are dependent on the orientation of the tree """
|
|
|
|
|
self.startAngle = 60 * 16
|
|
|
|
|
self.spanAngle = 60 * 16
|
|
|
|
|
|
|
|
|
|
if self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
|
|
|
|
|
self.startAngle = -self.startAngle
|
|
|
|
|
self.spanAngle = -self.spanAngle
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
|
|
|
|
|
self.startAngle = self.startAngle + 90 * 16
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
|
|
|
|
|
self.startAngle = self.startAngle - 90 * 16
|
|
|
|
|
|
|
|
|
|
def updateBound(self):
|
|
|
|
|
""" The bound where the user can click in to do a certain action, is set here. This bound is tightly set around the object """
|
|
|
|
|
pointBegin = QtCore.QPointF(0.0, 0.0)
|
|
|
|
|
pointBegin.setX((self.paintRect.width()/2.0) * math.cos(math.radians(self.startAngle/16.0)))
|
|
|
|
|
pointBegin.setY((self.paintRect.height()/2.0) * math.sin(math.radians(self.startAngle/16.0)))
|
|
|
|
|
|
|
|
|
|
pointEnd = QtCore.QPointF(0.0, 0.0)
|
|
|
|
|
pointEnd.setX((self.paintRect.width()/2.0) * math.cos(math.radians((self.startAngle+self.spanAngle)/16.0)))
|
|
|
|
|
pointEnd.setY((self.paintRect.height()/2.0) * math.sin(math.radians((self.startAngle+self.spanAngle)/16.0)))
|
|
|
|
|
|
|
|
|
|
pointMiddle = QtCore.QPointF(0.0, 0.0)
|
|
|
|
|
halfDegree = (self.startAngle+(self.spanAngle/2.0))/16.0
|
|
|
|
|
pointMiddle.setX((self.paintRect.width()/2.0) * math.cos(math.radians(halfDegree)))
|
|
|
|
|
pointMiddle.setY((self.paintRect.height()/2.0) * math.sin(math.radians(halfDegree)))
|
|
|
|
|
|
|
|
|
|
if pointBegin.x() < pointMiddle.x() and pointBegin.x() < pointEnd.x():
|
|
|
|
|
self.boundary.setLeft(pointBegin.x())
|
|
|
|
|
elif pointMiddle.x() < pointEnd.x():
|
|
|
|
|
self.boundary.setLeft(pointMiddle.x())
|
|
|
|
|
else:
|
|
|
|
|
self.boundary.setLeft(pointEnd.x())
|
|
|
|
|
|
|
|
|
|
if self.boundary.left() > 0.0:
|
|
|
|
|
self.boundary.setLeft(0.0)
|
|
|
|
|
|
|
|
|
|
if pointBegin.x() > pointMiddle.x() and pointBegin.x() > pointEnd.x():
|
|
|
|
|
self.boundary.setRight(pointBegin.x())
|
|
|
|
|
elif pointMiddle.x() > pointEnd.x():
|
|
|
|
|
self.boundary.setRight(pointMiddle.x())
|
|
|
|
|
else:
|
|
|
|
|
self.boundary.setRight(pointEnd.x())
|
|
|
|
|
|
|
|
|
|
if self.boundary.right() < 0.0:
|
|
|
|
|
self.boundary.setRight(0.0)
|
|
|
|
|
|
|
|
|
|
if pointBegin.y() < pointMiddle.y() and pointBegin.y() < pointEnd.y():
|
|
|
|
|
self.boundary.setBottom(pointBegin.y())
|
|
|
|
|
elif pointMiddle.y() < pointEnd.y():
|
|
|
|
|
self.boundary.setBottom(pointMiddle.y())
|
|
|
|
|
else:
|
|
|
|
|
self.boundary.setBottom(pointEnd.y())
|
|
|
|
|
|
|
|
|
|
if self.boundary.bottom() > 0.0:
|
|
|
|
|
self.boundary.setBottom(0.0)
|
|
|
|
|
|
|
|
|
|
if pointBegin.y() > pointMiddle.y() and pointBegin.y() > pointEnd.y():
|
|
|
|
|
self.boundary.setTop(pointBegin.y())
|
|
|
|
|
elif pointMiddle.y() > pointEnd.y():
|
|
|
|
|
self.boundary.setTop(pointMiddle.y())
|
|
|
|
|
else:
|
|
|
|
|
self.boundary.setTop(pointEnd.y())
|
|
|
|
|
|
|
|
|
|
if self.boundary.top() < 0.0:
|
|
|
|
|
self.boundary.setTop(0.0)
|
|
|
|
|
|
|
|
|
|
self.__translateBound()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __translateBound(self):
|
|
|
|
|
""" Translation of the boundary, so that it fits exactly around the figure"""
|
|
|
|
|
self.boundary.setLeft(self.boundary.left()+self.paintRect.center().x())
|
|
|
|
|
self.boundary.setRight(self.boundary.right()+self.paintRect.center().x())
|
|
|
|
|
self.boundary.setTop(-self.boundary.top()+self.paintRect.center().y())
|
|
|
|
|
self.boundary.setBottom(-self.boundary.bottom()+self.paintRect.center().y())
|
|
|
|
|
|
|
|
|
|
def shape(self):
|
|
|
|
|
""" Overridden function to set the boundary wherein the user can perform an action """
|
|
|
|
|
path = QtGui.QPainterPath()
|
|
|
|
|
path.addRect(self.boundary)
|
|
|
|
|
return path
|
|
|
|
|
self.textGraphic = QtGui.QGraphicsSimpleTextItem(str(list(self.cluster.variables)), self)
|
|
|
|
|
#self.textGraphic.translate(x,y)
|
|
|
|
|
self.paintRect = self.textGraphic.boundingRect()
|
|
|
|
|
#self.paintRect.translate(x,y)
|
|
|
|
|
self.translate(x,y)
|
|
|
|
|
|
|
|
|
|
def boundingRect(self):
|
|
|
|
|
""" Overridden function where a update area is determined for painting and returned """
|
|
|
|
@ -122,480 +25,53 @@ class CVCluster(QtGui.QGraphicsItem, Node):
|
|
|
|
|
""" Visualisation of a clusteritem """
|
|
|
|
|
painter.setPen(QtGui.QColor(0,155,50))
|
|
|
|
|
|
|
|
|
|
if self.flag != None:
|
|
|
|
|
if self.flag == GeometricCluster.OK:
|
|
|
|
|
if self.cluster.flag != None:
|
|
|
|
|
if self.cluster.flag == GeometricCluster.OK:
|
|
|
|
|
painter.setBrush(QtGui.QBrush(self.compositionView.wellConstrainedColor))
|
|
|
|
|
elif self.flag == GeometricCluster.I_UNDER or self.flag == GeometricCluster.S_UNDER:
|
|
|
|
|
elif self.cluster.flag == GeometricCluster.I_UNDER or self.cluster.flag == GeometricCluster.S_UNDER:
|
|
|
|
|
painter.setBrush(QtGui.QBrush(self.compositionView.underConstrainedColor))
|
|
|
|
|
elif self.flag == GeometricCluster.I_OVER or self.flag == GeometricCluster.S_OVER:
|
|
|
|
|
elif self.cluster.flag == GeometricCluster.I_OVER or self.cluster.flag == GeometricCluster.S_OVER:
|
|
|
|
|
painter.setBrush(QtGui.QBrush(self.compositionView.overConstrainedColor))
|
|
|
|
|
elif self.flag == GeometricCluster.UNSOLVED:
|
|
|
|
|
elif self.cluster.flag == GeometricCluster.UNSOLVED:
|
|
|
|
|
painter.setBrush(QtGui.QBrush(self.compositionView.unsolvedColor))
|
|
|
|
|
painter.drawPie(self.paintRect, self.startAngle, self.spanAngle)
|
|
|
|
|
painter.drawRect(self.paintRect)
|
|
|
|
|
|
|
|
|
|
def setInfoOverlay(self):
|
|
|
|
|
constrInfo = QtCore.QString("")
|
|
|
|
|
if self.flag == GeometricCluster.OK:
|
|
|
|
|
constrInfo = QtCore.QString("Well-Constrained\n")
|
|
|
|
|
elif self.flag == GeometricCluster.I_UNDER:
|
|
|
|
|
constrInfo = QtCore.QString("Inc. Underconstrained\n")
|
|
|
|
|
elif self.flag == GeometricCluster.S_UNDER:
|
|
|
|
|
constrInfo = QtCore.QString("Struct. Underconstrained\n")
|
|
|
|
|
elif self.flag == GeometricCluster.I_OVER:
|
|
|
|
|
constrInfo = QtCore.QString("Inc. Overconstrained\n")
|
|
|
|
|
elif self.flag == GeometricCluster.S_OVER:
|
|
|
|
|
constrInfo = QtCore.QString("Struct. Overconstrained\n")
|
|
|
|
|
elif self.flag == GeometricCluster.UNSOLVED:
|
|
|
|
|
constrInfo = QtCore.QString("Unsolved\n")
|
|
|
|
|
constrInfo.append("Points: ")
|
|
|
|
|
|
|
|
|
|
for point in self.variables:
|
|
|
|
|
pointObject = self.compositionView.prototypeManager.getObjectByKey(point)
|
|
|
|
|
if pointObject != None:
|
|
|
|
|
constrInfo.append(pointObject.name)
|
|
|
|
|
if point != self.variables[-1]:
|
|
|
|
|
constrInfo.append(", ")
|
|
|
|
|
|
|
|
|
|
self.compositionView.infoOverlay.infoText = constrInfo
|
|
|
|
|
|
|
|
|
|
#painter.setBrush(QtCore.Qt.NoBrush)
|
|
|
|
|
#painter.drawRect(self.bound)
|
|
|
|
|
|
|
|
|
|
def mousePressEvent(self, event):
|
|
|
|
|
""" Handling the mouse press, where the cluster (visualisation) and tree can be updated
|
|
|
|
|
|
|
|
|
|
Parameters:
|
|
|
|
|
event - pressed mousebutton
|
|
|
|
|
"""
|
|
|
|
|
if event.button() == QtCore.Qt.LeftButton:
|
|
|
|
|
self.updateCluster()
|
|
|
|
|
self.updateBound()
|
|
|
|
|
self.compositionView.updateTree()
|
|
|
|
|
elif event.button() == QtCore.Qt.RightButton:
|
|
|
|
|
if not self.clusterActive:
|
|
|
|
|
self.permanentCluster()
|
|
|
|
|
self.clusterActive = True
|
|
|
|
|
self.fixGraphic.show()
|
|
|
|
|
self.compositionView.stateChange(self.identifier, True)
|
|
|
|
|
else:
|
|
|
|
|
self.compositionView.prototypeManager.removeClusterObjects([self.permCluster], True, True)
|
|
|
|
|
self.clusterActive = False
|
|
|
|
|
self.fixGraphic.hide()
|
|
|
|
|
self.compositionView.stateChange(self.identifier, False)
|
|
|
|
|
self.permCluster = None
|
|
|
|
|
self.compositionView.prototypeManager.setObjectVisibilityByClusters()
|
|
|
|
|
self.compositionView.updateViewports()
|
|
|
|
|
|
|
|
|
|
def hoverEnterEvent(self, event):
|
|
|
|
|
self.setZValue(2)
|
|
|
|
|
self.setInfoOverlay()
|
|
|
|
|
self.compositionView.infoOverlay.setPosition(event.scenePos())
|
|
|
|
|
self.compositionView.infoOverlay.show()
|
|
|
|
|
if not self.clusterActive:
|
|
|
|
|
self.compositionView.prototypeManager.selectObjectsByKeys(self.variables)
|
|
|
|
|
self.highlightCluster()
|
|
|
|
|
self.compositionView.update()
|
|
|
|
|
self.compositionView.updateViewports()
|
|
|
|
|
|
|
|
|
|
def hoverMoveEvent(self, event):
|
|
|
|
|
self.overlayPosition = self.compositionView.ui.graphicsView.mapFromScene(event.scenePos())
|
|
|
|
|
self.compositionView.infoOverlay.setPosition(event.scenePos())
|
|
|
|
|
|
|
|
|
|
self.compositionView.updateConnections()
|
|
|
|
|
self.compositionView.update()
|
|
|
|
|
|
|
|
|
|
def hoverLeaveEvent(self, event):
|
|
|
|
|
self.setZValue(0)
|
|
|
|
|
self.compositionView.infoOverlay.infoText = ""
|
|
|
|
|
self.compositionView.infoOverlay.hide()
|
|
|
|
|
self.compositionView.infoOverlay.update()
|
|
|
|
|
if not self.clusterActive:
|
|
|
|
|
self.compositionView.prototypeManager.deselectAllObjects()
|
|
|
|
|
self.compositionView.prototypeManager.removeClusterObjects([self.clusterHighlight], True, False)
|
|
|
|
|
self.compositionView.updateViewports()
|
|
|
|
|
|
|
|
|
|
def updateCluster(self):
|
|
|
|
|
""" Cluster update, where the cluster is (un-)collapsed depending on the state of the cluster, to visualise a certain part of the tree """
|
|
|
|
|
if self.canCollapse:
|
|
|
|
|
if self.isCollapsed:
|
|
|
|
|
self.isCollapsed = False
|
|
|
|
|
self.showChildren()
|
|
|
|
|
height = self.paintRect.height()*0.5
|
|
|
|
|
width = self.paintRect.width()*0.5
|
|
|
|
|
height2 = self.paintRect.height()
|
|
|
|
|
if self.compositionView.tree.orientation == TreeOrientation.TOP:
|
|
|
|
|
self.paintRect.setTop(self.paintRect.top() + height )
|
|
|
|
|
self.paintRect.setBottom(self.paintRect.bottom() + height)
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
|
|
|
|
|
self.paintRect.setTop(self.paintRect.top()- height )
|
|
|
|
|
self.paintRect.setBottom(self.paintRect.bottom() - height)
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
|
|
|
|
|
self.paintRect.setLeft(self.paintRect.left() + width)
|
|
|
|
|
self.paintRect.setRight(self.paintRect.right() + width)
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
|
|
|
|
|
self.paintRect.setLeft(self.paintRect.left() - width)
|
|
|
|
|
self.paintRect.setRight(self.paintRect.right() - width)
|
|
|
|
|
else:
|
|
|
|
|
self.isCollapsed = True
|
|
|
|
|
self.showChildren()
|
|
|
|
|
height = self.paintRect.height()*0.5
|
|
|
|
|
width = self.paintRect.width()*0.5
|
|
|
|
|
height2 = self.paintRect.height()
|
|
|
|
|
if self.compositionView.tree.orientation == TreeOrientation.TOP:
|
|
|
|
|
self.paintRect.setTop(self.paintRect.top() - height)
|
|
|
|
|
self.paintRect.setBottom(self.paintRect.bottom() - height)
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
|
|
|
|
|
self.paintRect.setTop(self.paintRect.top() + height)
|
|
|
|
|
self.paintRect.setBottom(self.paintRect.bottom() + height)
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
|
|
|
|
|
self.paintRect.setLeft(self.paintRect.left() - width)
|
|
|
|
|
self.paintRect.setRight(self.paintRect.right() - width)
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
|
|
|
|
|
self.paintRect.setLeft(self.paintRect.left() + width)
|
|
|
|
|
self.paintRect.setRight(self.paintRect.right() + width)
|
|
|
|
|
|
|
|
|
|
if self.compositionView.tree.orientation == TreeOrientation.LEFT or self.compositionView.tree.orientation == TreeOrientation.RIGHT:
|
|
|
|
|
self.startAngle = self.startAngle + 180 * 16
|
|
|
|
|
else:
|
|
|
|
|
self.startAngle = -self.startAngle
|
|
|
|
|
self.spanAngle = -self.spanAngle
|
|
|
|
|
|
|
|
|
|
def highlightCluster(self):
|
|
|
|
|
if self.clusterHighlight != None:
|
|
|
|
|
if self.clusterHighlight.temporary:
|
|
|
|
|
self.compositionView.prototypeManager.addClusterObject(self.clusterHighlight)
|
|
|
|
|
self.clusterHighlight.selected = True
|
|
|
|
|
else:
|
|
|
|
|
self.clusterHighlight = self.compositionView.prototypeManager.selectClusterObjectByKeys(self.variables)
|
|
|
|
|
if self.clusterHighlight == None:
|
|
|
|
|
self.clusterHighlight = self.compositionView.prototypeManager.createCluster(self.variables)
|
|
|
|
|
if self.clusterHighlight != None:
|
|
|
|
|
self.clusterHighlight.temporary = True
|
|
|
|
|
if self.clusterHighlight != None:
|
|
|
|
|
self.clusterHighlight.selected = True
|
|
|
|
|
|
|
|
|
|
def permanentCluster(self):
|
|
|
|
|
if self.permCluster == None:
|
|
|
|
|
self.permCluster = self.compositionView.prototypeManager.createCluster(self.variables, self.flag)
|
|
|
|
|
self.permCluster.temporary = True
|
|
|
|
|
self.permCluster.fixed = True
|
|
|
|
|
self.compositionView.prototypeManager.setObjectVisibilityByClusters()
|
|
|
|
|
else:
|
|
|
|
|
self.compositionView.prototypeManager.addClusterObject(self.permCluster)
|
|
|
|
|
self.permCluster.selected = False
|
|
|
|
|
|
|
|
|
|
def showChildren(self):
|
|
|
|
|
""" Show the children of this node """
|
|
|
|
|
if self.isCollapsed or (self.isVisible()==False):
|
|
|
|
|
for child in self.children:
|
|
|
|
|
child.hide()
|
|
|
|
|
child.showChildren()
|
|
|
|
|
if child.clusterActive:
|
|
|
|
|
child.fixGraphic.hide()
|
|
|
|
|
else:
|
|
|
|
|
for child in self.children:
|
|
|
|
|
child.show()
|
|
|
|
|
child.showChildren()
|
|
|
|
|
if child.clusterActive:
|
|
|
|
|
child.fixGraphic.show()
|
|
|
|
|
else:
|
|
|
|
|
child.fixGraphic.hide()
|
|
|
|
|
|
|
|
|
|
def collapseFromResult(self):
|
|
|
|
|
if self.flag == GeometricCluster.I_UNDER or self.flag == GeometricCluster.S_UNDER or self.flag == GeometricCluster.I_OVER or self.flag == GeometricCluster.S_OVER or self.flag == GeometricCluster.UNSOLVED:
|
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def collapse(self):
|
|
|
|
|
if not self.isCollapsed:
|
|
|
|
|
self.updateCluster()
|
|
|
|
|
self.updateBound()
|
|
|
|
|
|
|
|
|
|
def expand(self):
|
|
|
|
|
if self.isCollapsed:
|
|
|
|
|
self.updateCluster()
|
|
|
|
|
self.updateBound()
|
|
|
|
|
|
|
|
|
|
class CVPoint(QtGui.QGraphicsItem, Node):
|
|
|
|
|
""" Visualisation of the leaves of the 'leaf' clusters in the tree """
|
|
|
|
|
def __init__(self, compView, parentNode, id, parent=None):
|
|
|
|
|
QtGui.QGraphicsItem.__init__(self, parent)
|
|
|
|
|
Node.__init__(self, parentNode)
|
|
|
|
|
|
|
|
|
|
self.compositionView = compView
|
|
|
|
|
self.setFlags(QtGui.QGraphicsItem.ItemIsSelectable)
|
|
|
|
|
self.setAcceptsHoverEvents(True)
|
|
|
|
|
self.startAngle = 0
|
|
|
|
|
self.spanAngle = 0
|
|
|
|
|
self.paintRect = QtCore.QRectF(0, 0, self.width/2, self.height/2)
|
|
|
|
|
self.fixGraphic = QtGui.QGraphicsSimpleTextItem("F", self)
|
|
|
|
|
self.fixGraphic.hide()
|
|
|
|
|
self.bezierCurve = None
|
|
|
|
|
self.flag = None
|
|
|
|
|
self.prtRef = None
|
|
|
|
|
self.boundary = self.paintRect
|
|
|
|
|
self.clusterHighlight = None
|
|
|
|
|
self.permCluster = None
|
|
|
|
|
self.clusterActive = False
|
|
|
|
|
self.identifier = id
|
|
|
|
|
|
|
|
|
|
def paint(self, painter, option, widget):
|
|
|
|
|
painter.setPen(QtGui.QColor(0,155,50))
|
|
|
|
|
painter.setBrush(QtGui.QBrush(QtGui.QColor(0,155,50)))
|
|
|
|
|
painter.drawEllipse(self.paintRect)
|
|
|
|
|
|
|
|
|
|
def setInfoOverlay(self):
|
|
|
|
|
constrInfo = QtCore.QString("Points \n")
|
|
|
|
|
if self.prtRef != None:
|
|
|
|
|
constrInfo += "Name: " + self.prtRef.name + "\n"
|
|
|
|
|
constrInfo += "Position: (" + str(round(self.prtRef.position[0],2)) + " , " + str(round(self.prtRef.position[1])) + " , " + str(round(self.prtRef.position[2])) + ")"
|
|
|
|
|
self.compositionView.infoOverlay.infoText = constrInfo
|
|
|
|
|
|
|
|
|
|
def mousePressEvent(self, event):
|
|
|
|
|
""" Handling the mouse press, where the cluster (visualisation) is handled
|
|
|
|
|
|
|
|
|
|
Parameters:
|
|
|
|
|
event - pressed mousebutton
|
|
|
|
|
"""
|
|
|
|
|
if event.button() == QtCore.Qt.RightButton:
|
|
|
|
|
if not self.clusterActive:
|
|
|
|
|
self.permanentCluster()
|
|
|
|
|
self.clusterActive = True
|
|
|
|
|
self.fixGraphic.show()
|
|
|
|
|
self.compositionView.stateChange(self.identifier, True)
|
|
|
|
|
else:
|
|
|
|
|
self.compositionView.prototypeManager.removeClusterObjects([self.permCluster], True, True)
|
|
|
|
|
self.clusterActive = False
|
|
|
|
|
self.permCluster = None
|
|
|
|
|
self.fixGraphic.hide()
|
|
|
|
|
self.compositionView.stateChange(self.identifier, False)
|
|
|
|
|
self.compositionView.prototypeManager.setObjectVisibilityByClusters()
|
|
|
|
|
self.compositionView.updateViewports()
|
|
|
|
|
|
|
|
|
|
def hoverEnterEvent(self, event):
|
|
|
|
|
self.setZValue(2)
|
|
|
|
|
self.setInfoOverlay()
|
|
|
|
|
self.compositionView.infoOverlay.setPosition(event.scenePos())
|
|
|
|
|
self.compositionView.infoOverlay.show()
|
|
|
|
|
|
|
|
|
|
if not self.clusterActive:
|
|
|
|
|
self.compositionView.prototypeManager.selectObject(self.prtRef)
|
|
|
|
|
self.highlightCluster()
|
|
|
|
|
self.compositionView.update()
|
|
|
|
|
self.compositionView.updateViewports()
|
|
|
|
|
|
|
|
|
|
def hoverMoveEvent(self, event):
|
|
|
|
|
self.compositionView.infoOverlay.setPosition(event.scenePos())
|
|
|
|
|
self.compositionView.update()
|
|
|
|
|
|
|
|
|
|
def hoverLeaveEvent(self, event):
|
|
|
|
|
self.setZValue(0)
|
|
|
|
|
self.compositionView.infoOverlay.infoText = ""
|
|
|
|
|
self.compositionView.infoOverlay.hide()
|
|
|
|
|
self.compositionView.infoOverlay.update()
|
|
|
|
|
if not self.clusterActive:
|
|
|
|
|
self.compositionView.prototypeManager.deselectAllObjects()
|
|
|
|
|
self.compositionView.prototypeManager.removeClusterObjects([self.clusterHighlight], True)
|
|
|
|
|
self.compositionView.updateViewports()
|
|
|
|
|
|
|
|
|
|
def highlightCluster(self):
|
|
|
|
|
if self.clusterHighlight != None:
|
|
|
|
|
if self.clusterHighlight.temporary:
|
|
|
|
|
self.compositionView.prototypeManager.addClusterObject(self.clusterHighlight)
|
|
|
|
|
self.clusterHighlight.selected = True
|
|
|
|
|
else:
|
|
|
|
|
self.clusterHighlight = self.compositionView.prototypeManager.selectClusterObjectByKeys([self.prtRef.key])
|
|
|
|
|
if self.clusterHighlight == None:
|
|
|
|
|
self.clusterHighlight = self.compositionView.prototypeManager.createCluster([self.prtRef.key])
|
|
|
|
|
if self.clusterHighlight != None:
|
|
|
|
|
self.clusterHighlight.temporary = True
|
|
|
|
|
if self.clusterHighlight != None:
|
|
|
|
|
self.clusterHighlight.selected = True
|
|
|
|
|
|
|
|
|
|
def permanentCluster(self):
|
|
|
|
|
if self.permCluster == None:
|
|
|
|
|
self.permCluster = self.compositionView.prototypeManager.createCluster([self.prtRef.key])
|
|
|
|
|
self.permCluster.temporary = True
|
|
|
|
|
self.permCluster.fixed = True
|
|
|
|
|
self.compositionView.prototypeManager.setObjectVisibilityByClusters()
|
|
|
|
|
else:
|
|
|
|
|
self.compositionView.prototypeManager.addClusterObject(self.permCluster)
|
|
|
|
|
self.permCluster.selected = False
|
|
|
|
|
|
|
|
|
|
def boundingRect(self):
|
|
|
|
|
return self.paintRect
|
|
|
|
|
|
|
|
|
|
def setWidthAndHeight(self, width, height):
|
|
|
|
|
self.width = width
|
|
|
|
|
self.height = height
|
|
|
|
|
self.paintRect.setWidth(width)
|
|
|
|
|
self.paintRect.setHeight(height)
|
|
|
|
|
|
|
|
|
|
def showChildren(self):
|
|
|
|
|
""" Show the children of this node """
|
|
|
|
|
if self.isCollapsed or (self.isVisible()==False):
|
|
|
|
|
for child in self.children:
|
|
|
|
|
child.hide()
|
|
|
|
|
child.showChildren()
|
|
|
|
|
else:
|
|
|
|
|
for child in self.children:
|
|
|
|
|
child.show()
|
|
|
|
|
child.showChildren()
|
|
|
|
|
|
|
|
|
|
def collapse(self):
|
|
|
|
|
self.isCollapsed = True
|
|
|
|
|
|
|
|
|
|
def expand(self):
|
|
|
|
|
self.isCollapsed = False
|
|
|
|
|
|
|
|
|
|
class CVInfoOverlay(QtGui.QGraphicsItem):
|
|
|
|
|
def __init__(self, compView, parent=None):
|
|
|
|
|
QtGui.QGraphicsItem.__init__(self, parent)
|
|
|
|
|
self.node = None
|
|
|
|
|
self.compositionView = compView
|
|
|
|
|
self.infoText = QtCore.QString("")
|
|
|
|
|
self.setZValue(3)
|
|
|
|
|
self.infoOverlay = QtCore.QRectF(0, 0, 140, 50)
|
|
|
|
|
self.overlayPosition = QtCore.QPointF()
|
|
|
|
|
self.scenePosition = QtCore.QPointF()
|
|
|
|
|
|
|
|
|
|
self.overlayBGColor = QtGui.QColor(204, 251, 255, 200)
|
|
|
|
|
self.overlayLineColor = QtGui.QColor(33, 116, 154)
|
|
|
|
|
self.overlayTextColor = QtGui.QColor(0, 0, 0)
|
|
|
|
|
|
|
|
|
|
def paint(self, painter, option, widget):
|
|
|
|
|
painter.save()
|
|
|
|
|
painter.resetMatrix()
|
|
|
|
|
painter.translate(self.overlayPosition)
|
|
|
|
|
painter.translate(10.0, 10.0)
|
|
|
|
|
painter.setPen(self.overlayLineColor)
|
|
|
|
|
painter.setBrush(self.overlayBGColor)
|
|
|
|
|
painter.drawRect(self.infoOverlay)
|
|
|
|
|
|
|
|
|
|
infoFont = QtGui.QFont("Arial", 7)
|
|
|
|
|
infoFont.setStyleStrategy(QtGui.QFont.ForceOutline)
|
|
|
|
|
painter.setFont(infoFont)
|
|
|
|
|
painter.setRenderHint(QtGui.QPainter.TextAntialiasing, False)
|
|
|
|
|
painter.setPen(self.overlayTextColor)
|
|
|
|
|
textRect = QtCore.QRect(self.infoOverlay.left()+4, self.infoOverlay.top(), self.infoOverlay.width()-3, self.infoOverlay.height()-3)
|
|
|
|
|
|
|
|
|
|
painter.drawText(textRect, QtCore.Qt.AlignLeft|QtCore.Qt.TextWordWrap, self.infoText)
|
|
|
|
|
painter.restore()
|
|
|
|
|
|
|
|
|
|
def setPosition(self, position):
|
|
|
|
|
self.scenePosition = position
|
|
|
|
|
self.overlayPosition = self.compositionView.ui.graphicsView.mapFromScene(position)
|
|
|
|
|
|
|
|
|
|
def boundingRect(self):
|
|
|
|
|
check = QtCore.QRectF(self.infoOverlay)
|
|
|
|
|
return check
|
|
|
|
|
|
|
|
|
|
class CVConnection(QtGui.QGraphicsItem):
|
|
|
|
|
""" Visualisation of the connections between the clusters, where two types of visualisation can be chosen: Bezier(default) and Lines """
|
|
|
|
|
def __init__(self, compView, nodeFrom , nodeTo, parent=None):
|
|
|
|
|
QtGui.QGraphicsItem.__init__(self, parent)
|
|
|
|
|
def __init__(self, compView, nodeFrom , nodeTo):
|
|
|
|
|
QtGui.QGraphicsItem.__init__(self)
|
|
|
|
|
self.settings = Settings()
|
|
|
|
|
self.compositionView = compView
|
|
|
|
|
self.nodeFrom = nodeFrom
|
|
|
|
|
self.nodeTo = nodeTo
|
|
|
|
|
self.connectType = self.settings.dvData.treeConnection
|
|
|
|
|
#self.boundRect = QtCore.QRectF(0.0, 0.0, 0.0, 0.0)
|
|
|
|
|
self.beziercurve = None
|
|
|
|
|
self.paintRect = QtCore.QRectF(0, 0, 0, 0)
|
|
|
|
|
self.paintRect = None
|
|
|
|
|
self.setZValue(1)
|
|
|
|
|
|
|
|
|
|
self.determinePath()
|
|
|
|
|
|
|
|
|
|
def determinePath(self):
|
|
|
|
|
if self.nodeFrom != None and self.nodeTo != None:
|
|
|
|
|
self.beziercurve = QtGui.QPainterPath()
|
|
|
|
|
x1 = self.nodeFrom.position.x() + self.nodeFrom.paintRect.width()/2
|
|
|
|
|
x2 = self.nodeTo.position.x() + self.nodeTo.paintRect.width()/2
|
|
|
|
|
y1 = self.nodeFrom.position.y()
|
|
|
|
|
y2 = self.nodeTo.position.y() + self.nodeFrom.paintRect.height()
|
|
|
|
|
p1 = QtCore.QPointF(x1,y1)
|
|
|
|
|
p2 = QtCore.QPointF(x1,y1+(y2-y1)/2)
|
|
|
|
|
p3 = QtCore.QPointF(x2,y1+(y2-y1)/2)
|
|
|
|
|
p4 = QtCore.QPointF(x2,y2)
|
|
|
|
|
self.beziercurve.moveTo(p1)
|
|
|
|
|
self.beziercurve.cubicTo(p2,p3,p4)
|
|
|
|
|
|
|
|
|
|
def paint(self, painter, option, widget):
|
|
|
|
|
""" Visualisation of the connection between two nodes """
|
|
|
|
|
if self.nodeFrom != None and self.nodeTo != None:
|
|
|
|
|
painter.setPen(QtGui.QColor(0,0,0))
|
|
|
|
|
|
|
|
|
|
diffPosExt = self.paintRect
|
|
|
|
|
endPoint = self.determineEndpoint(diffPosExt)
|
|
|
|
|
|
|
|
|
|
if self.connectType == ConnectionType.BEZIER:
|
|
|
|
|
""" display a bezier curve as connection """
|
|
|
|
|
self.beziercurve = QtGui.QPainterPath()
|
|
|
|
|
|
|
|
|
|
if self.compositionView.tree.orientation == TreeOrientation.TOP:
|
|
|
|
|
self.beziercurve.moveTo(diffPosExt.x(), diffPosExt.y())
|
|
|
|
|
firstPoint = QtCore.QPointF(diffPosExt.x(), diffPosExt.height()*0.5)
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
|
|
|
|
|
self.beziercurve.moveTo(diffPosExt.x(), diffPosExt.bottom())
|
|
|
|
|
firstPoint = QtCore.QPointF(diffPosExt.x(), -diffPosExt.height()*0.5 + self.nodeTo.paintRect.height())
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
|
|
|
|
|
self.beziercurve.moveTo(diffPosExt.x(), diffPosExt.y())
|
|
|
|
|
firstPoint = QtCore.QPointF(diffPosExt.width()*0.5, diffPosExt.y())
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
|
|
|
|
|
self.beziercurve.moveTo(diffPosExt.x(), diffPosExt.y())
|
|
|
|
|
firstPoint = QtCore.QPointF(self.nodeTo.paintRect.width() + diffPosExt.width()*0.5,diffPosExt.y())
|
|
|
|
|
|
|
|
|
|
if self.compositionView.tree.orientation == TreeOrientation.TOP:
|
|
|
|
|
secondPoint = QtCore.QPointF(diffPosExt.right(),diffPosExt.height()*0.5)
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
|
|
|
|
|
secondPoint = QtCore.QPointF(diffPosExt.right(), self.nodeTo.paintRect.height() - diffPosExt.height()*0.5)
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
|
|
|
|
|
secondPoint = QtCore.QPointF(diffPosExt.width()*0.5, diffPosExt.bottom())
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
|
|
|
|
|
secondPoint = QtCore.QPointF(self.nodeTo.paintRect.width() + diffPosExt.width()*0.5, diffPosExt.bottom())
|
|
|
|
|
|
|
|
|
|
self.beziercurve.cubicTo(firstPoint, secondPoint, endPoint)
|
|
|
|
|
if self.beziercurve:
|
|
|
|
|
painter.drawPath(self.beziercurve)
|
|
|
|
|
|
|
|
|
|
elif self.connectType == ConnectionType.LINES:
|
|
|
|
|
""" draw a straight line """
|
|
|
|
|
if self.compositionView.tree.orientation == TreeOrientation.TOP:
|
|
|
|
|
painter.drawLine(QtCore.QPointF(self.nodeTo.paintRect.width()*0.5, 0.0), QtCore.QPointF(endPoint.x(), endPoint.y()))
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
|
|
|
|
|
painter.drawLine(QtCore.QPointF(self.nodeTo.paintRect.width()*0.5, self.nodeTo.paintRect.height()), QtCore.QPointF(endPoint.x(), endPoint.y()))
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
|
|
|
|
|
painter.drawLine(QtCore.QPointF(0.0, self.nodeTo.paintRect.height()*0.5), QtCore.QPointF(endPoint.x(), endPoint.y()))
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
|
|
|
|
|
painter.drawLine(QtCore.QPointF(self.nodeTo.paintRect.width(), self.nodeTo.paintRect.height()*0.5), QtCore.QPointF(endPoint.x(), endPoint.y()))
|
|
|
|
|
|
|
|
|
|
def areaBetweenNodes(self):
|
|
|
|
|
diffPos = self.nodeTo.position - self.nodeFrom.position
|
|
|
|
|
area = QtCore.QRectF(0.0, 0.0, 0.0 , 0.0)
|
|
|
|
|
if self.compositionView.tree.orientation == TreeOrientation.TOP:
|
|
|
|
|
area.setX(self.nodeTo.paintRect.width()*0.5)
|
|
|
|
|
area.setY(0.0)
|
|
|
|
|
area.setRight(self.nodeFrom.paintRect.width()*0.5 - diffPos.x())
|
|
|
|
|
area.setBottom(self.nodeTo.boundary.height()-diffPos.y())
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
|
|
|
|
|
area.setX(self.nodeTo.paintRect.width()*0.5)
|
|
|
|
|
area.setY(-diffPos.y()+self.nodeFrom.boundary.height())
|
|
|
|
|
area.setRight(-diffPos.x()+self.nodeFrom.paintRect.width()*0.5)
|
|
|
|
|
area.setBottom(self.nodeTo.paintRect.height())
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
|
|
|
|
|
area.setX(0.0)
|
|
|
|
|
area.setY(self.nodeTo.paintRect.height()*0.5)
|
|
|
|
|
area.setRight(-diffPos.x()+self.nodeFrom.boundary.width())
|
|
|
|
|
area.setBottom(-diffPos.y() + self.nodeFrom.paintRect.height()*0.5)
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
|
|
|
|
|
area.setX(self.nodeTo.paintRect.width())
|
|
|
|
|
area.setY(self.nodeTo.paintRect.height()*0.5)
|
|
|
|
|
area.setRight(-diffPos.x() + self.nodeFrom.paintRect.width()*0.5)
|
|
|
|
|
area.setBottom(-diffPos.y() + self.nodeFrom.paintRect.height()*0.5)
|
|
|
|
|
return area
|
|
|
|
|
|
|
|
|
|
def determineEndpoint(self, area):
|
|
|
|
|
endPoint = QtCore.QPointF(0.0, 0.0)
|
|
|
|
|
|
|
|
|
|
if self.compositionView.tree.orientation == TreeOrientation.TOP:
|
|
|
|
|
endPoint.setX(area.right())
|
|
|
|
|
endPoint.setY(area.height())
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.BOTTOM:
|
|
|
|
|
endPoint.setX(area.right())
|
|
|
|
|
endPoint.setY(area.y())
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.LEFT:
|
|
|
|
|
endPoint.setX(area.right())
|
|
|
|
|
endPoint.setY(area.bottom())
|
|
|
|
|
elif self.compositionView.tree.orientation == TreeOrientation.RIGHT:
|
|
|
|
|
endPoint.setX(area.right())
|
|
|
|
|
endPoint.setY(area.bottom())
|
|
|
|
|
return endPoint
|
|
|
|
|
|
|
|
|
|
def boundingRect(self):
|
|
|
|
|
""" Overridden function where a update area is determined for painting and returned """
|
|
|
|
|
self.paintRect = self.areaBetweenNodes()
|
|
|
|
|
return self.paintRect
|
|
|
|
|
return self.beziercurve.boundingRect()
|
|
|
|
|
|
|
|
|
|