6 from Vispa.Main.Application
import Application
7 from Vispa.Gui.ConnectableWidget
import ConnectableWidget
8 from Vispa.Gui.WidgetContainer
import WidgetContainer
9 from Vispa.Gui.VispaWidget
import VispaWidget
10 from Vispa.Share.BasicDataAccessor
import BasicDataAccessor
11 from Vispa.Share.BasicDataAccessor
import BasicDataAccessorInterface
12 from Vispa.Share.RelativeDataAccessor
import RelativeDataAccessor
13 from Vispa.Share.ParticleDataAccessor
import ParticleDataAccessor
14 from Vispa.Gui.PortConnection
import LinearPortConnection
15 from Vispa.Views.WidgetView
import WidgetView
16 from Vispa.Main.Exceptions
import exception_traceback
17 from Vispa.Share.ThreadChain
import ThreadChain
20 """Visualizes a decay tree using boxes to represent containers as well as their contents.
22 Mother/daughter relations are represented by connection lines. The BoxDecayView is automatically filled using a DataAccessor.
25 LABEL =
"&Box Decay View"
27 NO_SORTING_ABOVE = 10000
31 logging.debug(__name__ +
": __init__")
32 WidgetView.__init__(self, parent)
42 self.setPalette(QPalette(Qt.black, Qt.white))
62 self._boxContentScript = script
68 """ Sets the DataAccessor from which the boxes are created.
70 You need to call updateContent() in order to make the changes visible.
72 if not isinstance(accessor, BasicDataAccessor):
73 raise TypeError(__name__ +
" requires data accessor of type BasicDataAccessor.")
74 if not isinstance(accessor, RelativeDataAccessor):
75 raise TypeError(__name__ +
" requires data accessor of type RelativeDataAccessor.")
76 WidgetView.setDataAccessor(self, accessor)
79 """ Stop all running operations.
84 numObjects=self.numberDataObjectChildren()
86 result=QCoreApplication.instance().showMessageBox(
"You are about to display more than "+str(numObjects)+
" (>"+str(self.
WARNING_ABOVE)+
") objects. This may take some time. ",
87 "Would you like to continue?",
88 QMessageBox.Yes | QMessageBox.No,
89 QMessageBox.Yes, [(
"Yes (remember my decision)",QMessageBox.YesRole)])
90 if result == QMessageBox.No:
97 """ Clear the BoxDecayView and refill it.
99 logging.debug(__name__ +
": updateContent")
101 if self.dataAccessor() ==
None:
103 self._updatingFlag+=1
105 if self.dataObject()==
None:
106 self._updatingFlag-=1
109 if not overrideCheck:
111 self._updatingFlag-=1
113 objects = self.applyFilter(self.dataObjects())
116 while thread.isRunning():
117 if not Application.NO_PROCESS_EVENTS:
118 QCoreApplication.instance().processEvents()
119 objects=thread.returnValue()
121 self._updatingFlag -=1
125 BoxDecayContainer.autolayoutAlgorithm(self)
126 self._updatingFlag -=1
129 def createBox(self, widgetParent, container, title, text):
130 """ Create a WidgetContainer or ConnectableWidget and set its properties.
135 widget = ConnectableWidget(widgetParent)
136 widget.noRearangeContent()
138 widget.textField().setOutputFlags(Qt.AlignLeft)
139 widget.setShowPortNames(
True)
140 widget.setDragable(
False)
141 widget.setDeletable(
False)
142 widget.enableAutosizing(
True,
False)
145 widget.setTitle(title)
149 """ Create a source port and set its properties.
151 port = w.sourcePort(name)
153 port = w.addSourcePort(name)
154 port.setDragable(
False)
155 port.setSelectable(
False)
162 """ Create a sink port and set its properties.
164 port = w.sinkPort(name)
166 port = w.addSinkPort(name)
167 port.setDragable(
False)
168 port.setSelectable(
False)
175 """ Create a connection widget between w1 and w2.
179 connection = LinearPortConnection(w1.parent(), port1, port2)
180 connection.setSelectable(
False)
181 connection.setDeletable(
False)
184 connection.FILL_COLOR2 = color
188 """ Create connection lines between objects.
190 In BoxDecayView default mother-daughter relations are vizualized by the connections.
192 for w1
in widgetParent.children():
197 if not Application.NO_PROCESS_EVENTS:
198 QCoreApplication.instance().processEvents()
202 if isinstance(w1, ConnectableWidget):
203 w1.setShowPortNames(
False)
204 for daughter
in self.dataAccessor().daughterRelations(w1.object):
205 if self.dataAccessor().isContainer(w1.object)
or self.dataAccessor().isContainer(daughter):
207 w2 = self.widgetByObject(daughter)
209 connectionWidget = self.
createConnection(w1,
'daughterRelations', w2,
'motherRelations',
None,
False)
210 connectionWidget.stackUnder(w2)
214 """ Creates a box from an object.
216 All children of this object are created recursively.
221 while thread.isRunning():
222 if not Application.NO_PROCESS_EVENTS:
223 QCoreApplication.instance().processEvents()
224 objects=thread.returnValue()
227 for object
in objects:
234 if not Application.NO_PROCESS_EVENTS:
235 QCoreApplication.instance().processEvents()
239 dataAccessorObject = BasicDataAccessorInterface(object, self.dataAccessor(),
False)
245 widget = self.
createBox(widgetParent, self.dataAccessor().isContainer(object), self.dataAccessor().
label(object), text)
246 child_positionName = positionName +
"-" + str(i)
247 self.addWidget(widget, object, child_positionName)
254 for widget
in widgetParent.children():
259 if isinstance(widget, WidgetContainer):
260 if not self.
createBoxesRecursive(operationId, self.applyFilter(self.dataAccessor().children(widget.object)), widget, positionName):
262 if isinstance(widget, (WidgetContainer,ConnectableWidget)):
263 widget.noRearangeContent(
False)
265 for widget
in widgetParent.children():
270 if isinstance(widget, (WidgetContainer,ConnectableWidget)):
272 self.autosizeScrollArea()
277 """ Sort a list of objects by their mother/daughter relations.
279 All daughter objects are put directly behind the mother object in the list.
280 This sorting algorithm is run before the display of objects with relations.
283 if len(objects) == 0:
287 unsortedObjects =
list(objects)
289 for object
in reversed(
list(objects)):
291 for mother
in self.dataAccessor().allMotherRelations(object):
292 if mother
in unsortedObjects:
295 if object
in unsortedObjects
and globalMother:
296 unsortedObjects.remove(object)
297 sortedObjects.insert(0, object)
299 for child
in self.dataAccessor().allDaughterRelations(object):
300 if child
in unsortedObjects:
302 unsortedObjects.remove(child)
303 sortedObjects.insert(i, child)
304 sortedObjects += unsortedObjects
305 return tuple(sortedObjects)
309 WidgetView.closeEvent(self, event)
312 return 10 * self.zoomFactor()
315 return 10 * self.zoomFactor()
318 for widget
in self.widgets():
319 if isinstance(widget,WidgetContainer)
and widget.collapsed():
320 widget.toggleCollapse()
323 for widget
in self.widgets():
324 if isinstance(widget,WidgetContainer)
and not widget.collapsed():
325 widget.toggleCollapse()
328 for widget
in self.widgets():
329 if isinstance(widget,WidgetContainer):
332 while isinstance(mother.parent(),WidgetContainer):
333 mother=mother.parent()
335 if not widget.collapsed()
and d>=depth
or\
336 widget.collapsed()
and d<depth:
337 widget.toggleCollapse()
340 widget=self.widgetByObject(object)
341 if isinstance(widget,WidgetContainer)
and widget.collapsed():
342 widget.toggleCollapse()
345 widget=self.widgetByObject(object)
346 if isinstance(widget,WidgetContainer)
and not widget.collapsed():
347 widget.toggleCollapse()
350 self.emit(SIGNAL(
"toggleCollapsed"), object)
354 AUTOSIZE_KEEP_ASPECT_RATIO =
False
355 AUTOLAYOUT_CHILDREN_ENABLED =
True
358 WidgetContainer.__init__(self, parent)
373 self.__class__.autolayoutAlgorithm(self)
377 """ Arrange box position according to mother relations.
379 widgetParent = self.parent()
380 min_x = round(self.contentStartX())
381 min_y = round(self.contentStartY())
383 leftMargin = VispaWidget.LEFT_MARGIN
384 topMargin = VispaWidget.TOP_MARGIN
385 for widget
in self.children():
386 if isinstance(widget, VispaWidget)
and hasattr(widget,
"object"):
390 for mother
in self.
dataAccessor().motherRelations(widget.object):
394 if x < w.x() + w.width():
395 x = w.x() + w.width() + leftMargin
402 min_y = y + widget.height() + widget.getDistance(
"topMargin")
404 self.updateConnections()
406 autolayoutAlgorithm = staticmethod(autolayoutAlgorithm)
409 WidgetContainer.toggleCollapse(self)
def setArrangeUsingRelations
_arrangeUsingRelationsFlag
def arrangeUsingRelations
def setSortBeforeArranging
tuple autolayoutAlgorithm
def arrangeUsingRelations
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run