4 from PyQt4.QtCore import Qt, QPoint, QPointF, QRect, QSize, SIGNAL, QCoreApplication, QMimeData, QRectF
5 from PyQt4.QtGui import QWidget, QPainter, QPolygon, QColor, QPen, QPalette, QPainterPath, QFont, QFontMetrics, QApplication, QDrag, QPixmap,QSizePolicy,QMessageBox, QTransform, QBrush
23 import_autolayout_error=
None
24 except Exception
as e:
29 LABEL =
"&Line Decay View"
31 DECAY_OBJECT_MIME_TYPE =
"text/x-decay-object"
35 WidgetView.__init__(self, parent)
36 self.setAutoFillBackground(
True)
37 self.setPalette(QPalette(Qt.white))
38 self.setAcceptDrops(
True)
60 """ Overwrite WidgetView's function.
62 Do not clear content. This will be done by updateContent() only if it is necessary.
64 AbstractView.setDataObjects(self, objects)
68 """ Stop all running operations.
73 logging.debug(self.__class__.__name__ +
": updateContent()")
80 result=QCoreApplication.instance().showMessageBox(
"You are about to display more than "+str(numObjects)+
" (>"+str(self.
WARNING_ABOVE)+
") objects. This may take some time. Labels will not be displayed.",
81 "Would you like to continue?",
82 QMessageBox.Yes | QMessageBox.No,
83 QMessageBox.Yes, [(
"Yes (remember my decision)",QMessageBox.YesRole)])
84 if result == QMessageBox.No:
98 existingWidgets += [eventWidget]
101 particleWidget =
ParticleWidget(self, ParticleWidget.NONE,
"",
"")
102 particleWidget.setMinimumSize(DecayLine.DEFAULT_LENGTH, 40)
103 particleWidget.setColors(QColor(
'white'), QColor(
'white'), QColor(
'white'))
104 particleWidget.setSelectable(
True)
105 particleWidget.setObject(object)
106 decayLine =
DecayLine(particleWidget, QPoint(5, 20), QPoint(particleWidget.width() -5, 20))
110 decayLine.setLineStyle(self.
dataAccessor().lineStyle(object))
112 decayLine.setLabel(
"Particle")
114 particleWidget.setDecayObject(decayLine)
115 existingWidgets += [particleWidget]
117 for child
in self.children():
121 if hasattr(child,
"object")
and not child
in existingWidgets:
123 child.setDeletable(
True)
125 elif hasattr(child,
"createDecayObjectsFromPxlObject"):
131 child.createDecayObjectsFromPxlObject(operationId)
132 child.setDeletable(
False)
133 child.setDragable(
False)
147 if import_autolayout_error!=
None:
148 logging.error(__name__ +
": Could not import autolayout algorithm: "+import_autolayout_error[1])
149 QCoreApplication.instance().errorMessage(
"Could not import autolayout algorithm (see logfile for details):\n"+import_autolayout_error[0])
154 for child
in self.children():
155 if isinstance(child, QWidget):
156 if isinstance(child, LineDecayContainer):
159 y += child.height() + margin
169 """ Returns the widget component representing the given pxl object.
175 for child
in self.children():
176 if isinstance(child, LineDecayContainer):
179 subChild = child.childContainer(objectId)
197 oldParent = existingWidget.parent()
199 if parentWidget != oldParent:
200 self.disconnect(existingWidget, SIGNAL(
"finishedAutolayouting"), oldParent.childFinishedAutolayouting)
201 existingWidget.setParent(parentWidget)
202 self.connect(existingWidget, SIGNAL(
"finishedAutolayouting"), parentWidget.childFinishedAutolayouting)
203 existingWidget.setVisible(
True)
205 return existingWidget
210 logging.warning(self.__class__.__name__ +
": createLineDecayContainer() - Cannot add child object to given object. Object does not belong to this "+ self.__class__.__name__ +
".")
213 lineDecayView = parentWidget.createChildContainer(object)
218 lineDecayView.setPxlObject(object)
220 self.connect(lineDecayView, SIGNAL(
"selected"), self.
onSelected)
231 """ Return tab controller.
233 See setTabController()
237 if hasattr(parent,
"controller"):
238 return parent.controller()
239 parent=parent.parent()
246 """ When item is selected in SubView forward signal.
249 self.emit(SIGNAL(
"selected"), object)
253 for child
in self.children():
254 if isinstance(child, LineDecayContainer):
255 child.setEditable(editable)
261 for child
in self.children():
262 if isinstance(child, LineDecayContainer):
263 child.scheduleUpdateVisibleList(
True)
267 """ Represents an Event or EventView
271 AUTOSIZE_KEEP_ASPECT_RATIO =
False
272 AUTOLAYOUT_CHILDREN_ENABLED =
True
273 AUTOSIZE_ADJUST_CONTAINER_POSITION =
False
278 logging.debug(self.__class__.__name__ +
": __init__()")
281 ObjectHolder.__init__(self)
282 WidgetContainer.__init__(self, parent)
289 self.setMouseTracking(
True)
299 if isinstance(parent, LineDecayContainer):
300 self.connect(self, SIGNAL(
"finishedAutolayouting"), parent.childFinishedAutolayouting)
306 """ Redirect filtering to parent.
311 """ Do not filter widget but rather the pxl objects
321 if isinstance(child, LineDecayContainer):
322 child.setEditable(editable)
328 """ Sets whether this view accepts drops and forwards the information to sub LineDecayContainers.
330 WidgetContainer.setAcceptDrops(self, accept)
332 if isinstance(child, LineDecayContainer):
333 child.setAcceptDrops(accept)
336 """ Sets the DataAccessor from which the lines are created.
338 You need to call updateContent() in order to make the changes visible.
340 if not isinstance(accessor, BasicDataAccessor):
341 raise TypeError(__name__ +
" requires data accessor of type BasicDataAccessor.")
342 if not isinstance(accessor, RelativeDataAccessor):
343 raise TypeError(__name__ +
" requires data accessor of type RelativeDataAccessor.")
344 if not isinstance(accessor, ParticleDataAccessor):
345 raise TypeError(__name__ +
" requires data accessor of type ParticleDataAccessor.")
346 AbstractView.setDataAccessor(self, accessor)
349 """ If there is only one container in parent increase it so it fills whole space.
352 return WidgetContainer.sizeHint(self)
366 sizeHint = WidgetContainer.sizeHint(self)
367 return QSize(
max(sizeHint.width() + increaseSize, minWidth),
max(sizeHint.height() + increaseSize, minHeight))
370 """ Overwrites QWidget's method and includes DecayObjects in addition to QWidgets.
379 if not isinstance(object, DecayNode):
381 if first
or minX > object.x():
383 if first
or minY > object.y():
385 if first
or maxX < object.x():
387 if first
or maxY < object.y():
394 return QRect(minX, minY, maxX - minX, maxY - minY).united(WidgetContainer.childrenRect(self))
397 return WidgetContainer.children(self) + [node
for node
in self.
dataObjects()
if isinstance(node, DecayNode)]
400 """ Overwrite VispaWidgetOwner's method so in addition deselectAllObjects() is called.
403 WidgetContainer.deselectAllWidgets(self, exception)
406 """ Sets zoom of this widget and of it's children.
408 WidgetContainer.setZoom(self, zoom)
411 if isinstance(child, Zoomable):
431 """ Return tab controller.
433 See setTabController()
441 """ Returns the widget component representing the given pxl object.
447 if isinstance(child, LineDecayContainer):
450 subChild = child.childContainer(object)
457 lineDecayView.setPxlObject(object)
461 pos = QPoint(margin, margin)
463 pos -= QPoint(0.5* lineDecayView.width(), 0.5* lineDecayView.height())
465 lineDecayView.move(pos)
469 """ Accepts drag enter event if module is dragged.
474 if event.mimeData().hasFormat(LineDecayView.DECAY_OBJECT_MIME_TYPE):
475 event.acceptProposedAction()
479 if dropType ==
"Node":
483 elif dropType ==
"EventView":
485 newObject.select(
True)
489 while hasattr(parent,
"parent"):
490 if hasattr(parent,
"onSelected"):
491 self.connect(newObject, SIGNAL(
"selected"), parent.onSelected)
493 parent=parent.parent()
501 self.update(newObject.boundingRect())
511 """ Handle drop of module.
513 logging.debug(self.__class__.__name__ +
": dropEvent()")
517 if event.mimeData().hasFormat(LineDecayView.DECAY_OBJECT_MIME_TYPE):
518 dropType = str(event.mimeData().
data(LineDecayView.DECAY_OBJECT_MIME_TYPE))
521 event.acceptProposedAction()
524 """ This function asks the data accessor to create a new particle and makes sure it gets the properties (name, pdg id, charge) of the desired type.
526 particleType may either be None or a string specifying the object type.
527 pos is in 100% coordinates.
535 newParticle = dataAccessor.createParticle()
537 categoryName =
"Object info"
538 dataAccessor.setProperty(newParticle,
"Name", particleType, categoryName)
539 particleId = self.
dataAccessor().particleId(newParticle)
540 if particleId !=
None:
542 dataAccessor.setProperty(newParticle,
"PdgNumber", particleId, categoryName)
543 particleName = self.
dataAccessor().defaultName(newParticle)
547 dataAccessor.setProperty(newParticle,
"Name", particleName, categoryName)
549 dataAccessor.setProperty(newParticle,
"Charge", dataAccessor.charge(newParticle), categoryName)
550 self._pxlObject.setObject(newParticle)
555 """ This function accepts a data object (e.g. a pxl object), creates a DecayLine for it and adds the latter to this container's objects list.
564 pos -= QPoint(0.5 * DecayLine.DEFAULT_LENGTH, 0)
572 self._existingObjectIds.append(str(dataObjectId))
579 for daughter
in self.
dataAccessor().daughterRelations(object):
580 if daughter
in self._particlesDict.keys():
583 daughterNode = daughterDecayObject.motherNode()
584 elif daughterDecayObject.motherNode() != daughterNode
and \
585 daughterDecayObject.motherNode().unite(daughterNode):
589 daughterNode = daughterDecayObject.motherNode()
591 for mother
in self.
dataAccessor().motherRelations(object):
592 if mother
in self._particlesDict.keys():
595 motherNode = motherDecayObject.daughterNode()
596 elif motherDecayObject.daughterNode() != motherNode
and \
597 motherDecayObject.daughterNode().unite(motherNode):
601 motherNode = motherDecayObject.daughterNode()
603 motherNode = QPoint(pos)
605 daughterNode = QPoint(pos.x() + DecayLine.DEFAULT_LENGTH, pos.y())
608 newDecayLine =
DecayLine(self, motherNode, daughterNode)
609 newDecayLine.setObject(object)
613 newDecayLine.setLineStyle(self.
dataAccessor().lineStyle(object))
629 """ Creates DecayObjects for all particles in the set pxl object.
631 In addition this function is called on all child LineDecayContainers.
648 if isinstance(child, LineDecayContainer):
649 if not child.createDecayObjectsFromPxlObject(operationId):
654 """ Returns the DecayObject which represents the given pxlObject or None if there is no such one.
656 This function is to slow for massive usage with many dataObjects as it loops over all dataObjects.
659 if decayObject.object() == pxlObject:
664 if type(decayObject) == type(
True):
665 WidgetContainer.select(self, decayObject)
677 self._selectedList.append(decayObject)
678 self.update(decayObject.boundingRect())
680 logging.error(self.__class__.__name__ +
": select() - Tried to remove non data object from data objects list. This is not supposed to happen. Check it.")
688 self.update(object.boundingRect())
692 boundingRect = decayObject.boundingRect()
694 self.update(boundingRect.unite(oldBoundingRect))
696 self.update(boundingRect)
699 objectIsVisible =
False
700 if self.visibleRegion().intersects(boundingRect):
701 objectIsVisible =
True
703 if not objectIsVisible:
704 self._visibleList.remove(decayObject)
705 elif objectIsVisible:
706 self._visibleList.append(decayObject)
711 if isinstance(child, LineDecayContainer):
712 child.scheduleUpdateVisibleList(update)
720 region = self.visibleRegion()
724 if region.intersects(decayObject.boundingRect()):
725 self._visibleList.append(decayObject)
733 WidgetContainer.paint(self, painter)
739 generalPaintMode = 0x0
741 generalPaintMode = DecayObject.PAINT_MODE_NO_DECORATIONS
748 painterClipRegion = self.visibleRegion()
750 if isinstance(decayObject, DecayLine):
752 if isinstance(decayObject, DecayNode):
754 decayNodes.append(decayObject)
756 for decayObject
in decayNodes:
760 paintMode = generalPaintMode
762 paintMode |= DecayObject.PAINT_MODE_SELECTED
764 paintMode |= DecayObject.PAINT_MODE_HOVERED
765 decayObject.paint(painter, paintMode)
769 WidgetContainer.mousePressEvent(self, event)
776 toSelectObject =
None
778 if object.containsPoint(event.pos()):
779 if isinstance(object, DecayNode):
781 toSelectObject = object
783 elif not toSelectObject:
784 toSelectObject = object
786 toSelectObject.select(event.pos())
787 self.
select(toSelectObject)
789 WidgetContainer.mousePressEvent(self, event)
794 WidgetContainer.mouseMoveEvent(self, event)
803 if not bool(event.buttons()):
805 to_hover_object =
None
810 if object.containsPoint(event.pos()):
811 if isinstance(object, DecayNode):
813 to_hover_object = object
815 elif not to_hover_object:
816 to_hover_object = object
821 self.update(self._hoveredObject.boundingRect())
822 if previously_hovered_object:
824 self.update(previously_hovered_object.boundingRect())
826 self.update(self._hoveredObject.boundingRect())
834 """ Join nodes if they belong to objects with relations.
840 for obj
in dataObjects:
841 if obj != self.
_selectedList[0]
and isinstance(obj, DecayNode)
and obj.containsPoint(event.pos()):
844 hasRelations=hasRelations
and self.
dataAccessor().hasRelations(decayLine.object())
850 self._selectedList.append(obj)
856 """ Calls delete() method if backspace or delete key is pressed when widget has focus.
858 if (event.key() == Qt.Key_Backspace
or event.key() == Qt.Key_Delete)
and self.
_editable:
861 controller.tab().propertyView().
clear()
869 controller.setModified()
870 if hasattr(controller,
"updateTreeView"):
871 controller.updateTreeView()
875 parent = self.parent()
876 if WidgetContainer.delete(self)
and hasattr(parent,
"object"):
883 self.update(decayObject.boundingRect())
884 if decayObject.delete():
886 self._selectedList.remove(decayObject)
887 if decayObject.object():
891 self._existingObjectIds.remove(id)
892 self._particlesDict.pop(decayObject.object(),
None)
893 self._pxlObject.removeObject(decayObject.object())
894 ObjectHolder.removeObject(self, decayObject)
899 logging.debug(self.__class__.__name__ +
": autolayout() - %s" % str(self.
title()))
900 if self._threadChain.isRunning():
901 logging.info(self.__class__.__name__ +
": autolayout() - Autolayout thread is already running. Aborting...")
909 if isinstance(object, DecayLine):
912 if not object.motherNode()
in self._allNodes.keys():
915 motherNode.position = Vector2(0, 0)
916 motherNode.isVertex =
False
917 self.
_allNodes[object.motherNode()] = motherNode
921 motherNode = self.
_allNodes[object.motherNode()]
923 if not object.daughterNode()
in self._allNodes.keys():
924 daughterNode =
Node()
925 daughterNode.position = Vector2(0, 0)
926 daughterNode.isVertex =
False
927 self.
_allNodes[object.daughterNode()] = daughterNode
930 daughterNode = self.
_allNodes[object.daughterNode()]
935 motherNode.children.append(daughterNode)
936 daughterNode.mothers.append(motherNode)
940 self._nodeVector.append(motherNode)
942 self._nodeVector.append(daughterNode)
944 nodeVectorSize = self._nodeVector.size()
945 if nodeVectorSize > 1:
946 adhoc = nodeVectorSize > 40
947 autolayouter = AutoLayout()
950 logging.debug(self.__class__.__name__ +
": calling pxl::AutoLayout.layout(%s) with %d Particles" % (str(adhoc), nodeVectorSize))
952 autolayouter.layout(
False)
954 autolayouter.layout(
True)
961 if isinstance(child, LineDecayContainer):
962 self._autolayoutingChildren.append(child)
966 logging.debug(self.__class__.__name__ +
" autolayoutThreadFinished() - %s" % str(self.
title()))
967 if self._threadChain.isRunning():
968 logging.info(self.__class__.__name__ +
": autolayoutThreadFinished() - Thread is still running. Aborting...")
972 firstMinOrphanY =
True
973 firstMaxNonOrphanY =
True
977 if i == 0
or self.
_nodeVector[i].position.y < minY:
979 if i == 0
or self.
_nodeVector[i].position.y > maxY:
986 if firstMinOrphanY
or self.
_nodeVector[i].position.y > minOrphanY:
988 firstMinOrphanY =
False
991 if firstMaxNonOrphanY
or self.
_nodeVector[i].position.y < maxNonOrphanY:
993 firstMaxNonOrphanY =
False
999 if isinstance(decayNode, DecayNode)
and decayNode
in self._allNodes.keys():
1000 decayNode.setPosition(QPoint(self.
_allNodes[decayNode].position.x + xOffset, self.
_allNodes[decayNode].position.y + yOffset))
1015 logging.debug(self.__class__.__name__ +
": childFinishedAutolayouting() - %s" % str(self.
title()))
1016 if self.sender()
and isinstance(self.sender(), LineDecayContainer):
1017 child = self.sender()
1019 self._autolayoutingChildren.remove(child)
1033 self.emit(SIGNAL(
"finishedAutolayouting"))
1037 CONTAINS_AREA_SIZE = 4
1038 PAINT_MODE_SELECTED = 0x1
1039 PAINT_MODE_HOVERED = 0x2
1040 PAINT_MODE_NO_DECORATIONS = 0x4
1043 Zoomable.__init__(self)
1045 if isinstance(self.
_parent, Zoomable):
1046 self.
setZoom(self._parent.zoom())
1051 def paint(self, painter, paintMode=0x0):
1052 raise NotImplementedError
1055 raise NotImplementedError
1058 raise NotImplementedError
1061 raise NotImplementedError
1067 raise NotImplementedError
1077 CONTAINS_AREA_SIZE = 8
1082 DecayObject.__init__(self, parent)
1083 ObjectHolder.__init__(self)
1092 if decayObject2.object()
in self.
parent().
dataAccessor().motherRelations(decayObject.object()):
1093 decayObject.object().unlinkMother(decayObject2.object())
1094 if decayObject2.object()
in self.
parent().
dataAccessor().daughterRelations(decayObject.object()):
1095 decayObject.object().unlinkDaughter(decayObject2.object())
1107 return self._position.x()
1110 return self._position.y()
1112 def paint(self, painter, paintMode=0x0):
1113 if paintMode & DecayObject.PAINT_MODE_SELECTED:
1114 penColor = QColor(Qt.blue)
1118 penColor = QColor(Qt.blue).lighter(140)
1119 if paintMode & DecayObject.PAINT_MODE_HOVERED:
1120 penColor = penColor.lighter(120)
1122 painter.setPen(QPen(penColor, 1 * self.
zoomFactor(), Qt.SolidLine))
1123 painter.setBrush(penColor)
1143 pos = QPoint(arg[0], arg[1])
1147 oldBoundingRects = {}
1149 oldBoundingRects[object] = object.boundingRect()
1155 self.
parent().objectMoved(object, oldBoundingRects[object])
1156 self.
parent().objectMoved(self, oldBoundingRect)
1163 useDataAccessor =
False
1165 useDataAccessor =
True
1168 newDecayObjects = node.dataObjects()[:]
1169 for newDecayObject
in newDecayObjects:
1172 nodeType = newDecayObject.replaceNode(node, self)
1175 for oldDecayObject
in oldDecayObjects:
1176 if nodeType == DecayNode.TYPE_MOTHER
and oldDecayObject.nodeType(self) == DecayNode.TYPE_DAUGHTER:
1178 self.
parent().
dataAccessor().linkMother(newDecayObject.object(), oldDecayObject.object())
1179 if nodeType == DecayNode.TYPE_DAUGHTER
and oldDecayObject.nodeType(self) == DecayNode.TYPE_MOTHER:
1181 self.
parent().
dataAccessor().linkDaughter(newDecayObject.object(), oldDecayObject.object())
1195 HUNDREDEIGHTY_OVER_PI = 180 / math.pi
1197 def __init__(self, parent, startPointOrNode, endPointOrNode):
1213 DecayObject.__init__(self, parent)
1215 if isinstance(parent, LineDecayContainer):
1217 if isinstance(startPointOrNode, QPoint):
1223 if isinstance(endPointOrNode, QPoint):
1235 self._startNode.appendObject(self)
1236 self._endNode.appendObject(self)
1239 DecayObject.setZoom(self, zoom)
1241 self._labelFont.setPointSize(12 * self.
zoomFactor())
1244 self._startNode.removeObject(self)
1245 self._endNode.removeObject(self)
1287 self._labelFont.setPointSize(12 * self.
zoomFactor())
1294 return DecayNode.TYPE_MOTHER
1296 return DecayNode.TYPE_DAUGHTER
1301 self._startNode.removeObject(self)
1303 self._startNode.appendObject(self)
1305 self._endNode.removeObject(self)
1307 self._endNode.appendObject(self)
1320 """ Returns True if instead of simple line a spiral or a sinus function is plotted.
1327 """ Returns QTransform that sets the origin to the start point and rotates by the slope angle.
1329 Used to change coordinates of painter in paint().
1336 if self._startNode.x() < self._endNode.x():
1338 xNull = self._startNode.x() * z
1339 yNull = self._startNode.y() * z
1342 xNull = self._endNode.x() * z
1343 yNull = self._endNode.y() * z
1345 slope = self.
slope()
1346 angle = math.atan(slope)
1350 self._transform.translate(xNull, yNull)
1351 self._transform.rotate(angleDegree)
1354 def paint(self, painter, paintMode=0x0):
1355 if paintMode & DecayObject.PAINT_MODE_SELECTED:
1356 penColor = QColor(Qt.blue)
1359 if paintMode & DecayObject.PAINT_MODE_HOVERED:
1360 penColor = penColor.lighter(80)
1362 showDirectionArrow = paintMode & DecayObject.PAINT_MODE_HOVERED
or paintMode & DecayObject.PAINT_MODE_SELECTED
1366 l = self.
length(zoomed =
True)
1372 painter.setPen(QPen(penColor, 0.5*self.
lineWidth(), Qt.SolidLine))
1375 designRadius = 1.2 * z
1377 n =
max(int(1.0 * l / (2 * math.pi * designRadius)), 4)
1379 r = 1.0 * l / (2 * math.pi * (n + 0.5))
1384 path = QPainterPath()
1390 phase = 1.0 * (xM-a)/r
1391 x = xM - a * math.cos(phase)
1392 y = yM - a * math.sin(phase)
1397 path.lineTo(QPointF(x, y))
1399 painter.drawPath(path)
1401 path = QPainterPath()
1403 while x < l - 0.5*a:
1404 y = a * math.cos(x/r)
1405 path.lineTo(QPointF(x, y))
1407 painter.drawPath(path)
1409 painter.setBrush(QBrush(penColor, Qt.SolidPattern))
1410 painter.drawEllipse(QPointF(l/2.,0.),l/2.,a)
1414 painter.drawLine(QPoint(0,0), QPoint(l, 0))
1416 if not paintMode & DecayObject.PAINT_MODE_NO_DECORATIONS:
1420 if showDirectionArrow:
1421 painter.setPen(QPen(penColor, 0.8*self.
lineWidth(), Qt.SolidLine, Qt.RoundCap))
1429 painter.resetTransform()
1433 self._startNode.paint(painter, paintMode)
1434 self._endNode.paint(painter, paintMode)
1458 """ Draws self._label on given painter.
1460 Expects coordinates of painter transformed as returned by transform()
1465 if paintMode & DecayObject.PAINT_MODE_SELECTED:
1466 textColor = QColor(Qt.blue)
1467 elif paintMode & DecayObject.PAINT_MODE_HOVERED:
1468 textColor = QColor(Qt.gray)
1470 textColor = QColor(Qt.black)
1472 path = QPainterPath()
1474 painter.fillPath(path, textColor)
1478 arrowPixelOffset = 0.7* self.
lineWidth()
1480 arrowBoundingRectLeft = arrowBoundingRect.left() + arrowPixelOffset
1481 arrowBoundingRectRight = arrowBoundingRect.right() - arrowPixelOffset
1482 arrowBoundingRectTop = arrowBoundingRect.top() + arrowPixelOffset
1483 arrowBoundingRectBottom = arrowBoundingRect.bottom() - arrowPixelOffset
1484 arrowBoundingRectVerticalCenter = arrowBoundingRect.center().y()
1486 painter.drawLine(arrowBoundingRectLeft, arrowBoundingRectTop, arrowBoundingRectRight, arrowBoundingRectVerticalCenter)
1487 painter.drawLine(arrowBoundingRectLeft, arrowBoundingRectBottom, arrowBoundingRectRight, arrowBoundingRectVerticalCenter)
1490 painter.drawLine(arrowBoundingRectLeft, arrowBoundingRectVerticalCenter, arrowBoundingRectRight, arrowBoundingRectTop)
1491 painter.drawLine(arrowBoundingRectLeft, arrowBoundingRectVerticalCenter, arrowBoundingRectRight, arrowBoundingRectBottom)
1506 labelWidth = self._labelBoundingRect.width()
1507 offset = QPointF(0.5 * (self.
length(zoomed=
True) - labelWidth), - label_offset * self.
zoomFactor())
1508 self._labelBoundingRect.translate(offset.x(), offset.y())
1515 l = self.
length(zoomed =
True)
1520 self.
_arrowBoundingRect = QRect(l-arrowLength - horizontalOffset, -arrowWidth, arrowLength, 2*arrowWidth)
1522 self.
_arrowBoundingRect = QRect(horizontalOffset, -arrowWidth, arrowLength, 2*arrowWidth)
1533 contains_area_size += 4
1536 offset = contains_area_size * zoomFactor
1537 startPoint = self._startNode.position() * zoomFactor
1538 endPoint = self._endNode.position() * zoomFactor
1540 topLeft = QPoint(
min(startPoint.x(), endPoint.x()) - offset,
min(startPoint.y(), endPoint.y()) - offset)
1541 bottomRight = QPoint(
max(startPoint.x(), endPoint.x()) + offset,
max(startPoint.y(), endPoint.y()) + offset)
1543 rect = QRect(topLeft, bottomRight)
1554 deltaX = self._endNode.x() - self._startNode.x()
1558 return 1.0 * (self._endNode.y() - self._startNode.y()) / deltaX
1561 l = math.sqrt((self._endNode.x() - self._startNode.x())**2 + (self._endNode.y() - self._startNode.y())**2)
1578 if self._endNode.position().x() == self._startNode.position().x():
1580 if abs(pos.x() - self._endNode.position().x()) < line_width:
1584 if pos.x() < (
min(self._startNode.position().x(), self._endNode.position().x()) - line_width)
or pos.x() > (
max(self._startNode.position().x(), self._endNode.position().x()) + line_width):
1587 slope = self.
slope()
1588 deltaY = slope * (pos.x() - self._startNode.position().x()) + self._startNode.position().y() - pos.y()
1589 if abs(deltaY) < 0.5* line_width *
max(1,
abs(slope)):
1595 pos = (self._startNode.position() + self._endNode.position()) * 0.5
1596 self._startNode.select(pos)
1597 self._endNode.select(pos)
1601 self._startNode.move(pos)
1602 self._endNode.move(pos)
1625 VispaWidget.__init__(self, parent)
1627 self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
1632 self.
textField().setPenColor(QColor(
"white"))
1642 self.
setColors(QColor(117, 57, 18), QColor(180, 88, 28), QColor(244, 119, 38))
1643 elif type == self.
QUARK:
1644 self.
setColors(QColor(19, 56, 0), QColor(27, 79, 27), QColor(57, 129, 51))
1645 elif type == self.
BOSON:
1646 self.
setColors(QColor(64, 0, 0), QColor(127, 0, 0), QColor(191, 0, 0))
1647 elif type == self.
HIGGS:
1648 self.
setColors(QColor(28, 63, 253), QColor(27, 118, 255), QColor(21, 169, 250))
1650 if hasattr(parent,
"particleDoubleClicked"):
1651 self.connect(self,SIGNAL(
"mouseDoubleClicked"),parent.particleDoubleClicked)
1652 if hasattr(parent,
"particleRightClicked"):
1653 self.connect(self,SIGNAL(
"mouseRightPressed"),parent.particleRightClicked)
1662 self.emit(SIGNAL(
"mouseDoubleClicked"), self)
1665 if event.button() == Qt.LeftButton:
1667 if isinstance(self.parent(), WidgetView):
1668 self.parent().widgetSelected(self)
1669 if event.button()==Qt.RightButton:
1670 self.emit(SIGNAL(
"mouseRightPressed"), event.globalPos(), self)
1673 if not (event.buttons() & Qt.LeftButton):
1675 if (event.pos() - self.
_dragStartPosition).manhattanLength() < QApplication.startDragDistance():
1679 mimeData = QMimeData()
1681 drag.setMimeData(mimeData)
1682 drag.setPixmap(QPixmap.grabWidget(self))
1683 drag.setHotSpot(QPoint(drag.pixmap().
width()/2, drag.pixmap().
height()/2))
1687 """ Will be painted in content area.
1692 """ The particle widget can optionally carry a real physics object, e.g. pxl particle.
1694 Required for example if widget's parent is a WidgetView that should react on clicks.
1702 VispaWidget.paint(self, painter)
1706 paintMode |= DecayObject.PAINT_MODE_SELECTED
1707 self._decayObect.paint(painter, paintMode)
1710 """ Return None for decay object.
bool contains(EventRange const &lh, EventID const &rh)
_lineStyle
l = (n + 1/2) * r * 2 * math.pi
def childFinishedAutolayouting
_crateDecayObjectsDecaysThreadChain
def autolayoutPostprocess
int HUNDREDEIGHTY_OVER_PI
def scrollBarValueChanged
void clear(CLHEP::HepGenMatrix &m)
Helper function: Reset all elements of a matrix to 0.
def createDecayObjectsFromPxlObject
Abs< T >::type abs(const T &t)
string DECAY_OBJECT_MIME_TYPE
bool insert(Storage &iStorage, ItemType *iItem, const IdTag &iIdTag)
def containsAreaSquareRect
def childFinishedAutolayouting
def numberDataObjectChildren
def createLineDecayContainer
def createDecayObjectsThreadChainFinished
def scheduleUpdateVisibleList
char data[epos_bytes_allocation]
def autolayoutThreadFinished
edm::TrieNode< PDet > Node
def mouseDoubleClickEvent