node_item.py
Go to the documentation of this file.
00001 # Copyright (c) 2011, Dirk Thomas, TU Darmstadt
00002 # All rights reserved.
00003 #
00004 # Redistribution and use in source and binary forms, with or without
00005 # modification, are permitted provided that the following conditions
00006 # are met:
00007 #
00008 #   * Redistributions of source code must retain the above copyright
00009 #     notice, this list of conditions and the following disclaimer.
00010 #   * Redistributions in binary form must reproduce the above
00011 #     copyright notice, this list of conditions and the following
00012 #     disclaimer in the documentation and/or other materials provided
00013 #     with the distribution.
00014 #   * Neither the name of the TU Darmstadt nor the names of its
00015 #     contributors may be used to endorse or promote products derived
00016 #     from this software without specific prior written permission.
00017 #
00018 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00022 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00026 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00027 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00028 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029 # POSSIBILITY OF SUCH DAMAGE.
00030 
00031 from __future__ import print_function
00032 
00033 import sys
00034 
00035 from python_qt_binding.QtCore import Qt
00036 from python_qt_binding.QtGui import QBrush, QGraphicsEllipseItem, QGraphicsRectItem, QGraphicsSimpleTextItem, QPainterPath, QPen
00037 
00038 from .dot_shapes import QGraphicsBox3dItem
00039 from .graph_item import GraphItem
00040 
00041 
00042 class NodeItem(GraphItem):
00043 
00044     def __init__(self, highlight_level, bounding_box, label, shape, color=None, parent=None, label_pos=None, tooltip=None):
00045         super(NodeItem, self).__init__(highlight_level, parent)
00046 
00047         self._default_color = self._COLOR_BLACK if color is None else color
00048         self._brush = QBrush(self._default_color)
00049         self._label_pen = QPen()
00050         self._label_pen.setColor(self._default_color)
00051         self._label_pen.setJoinStyle(Qt.RoundJoin)
00052         self._ellipse_pen = QPen(self._label_pen)
00053         self._ellipse_pen.setWidth(1)
00054 
00055         self._incoming_edges = set()
00056         self._outgoing_edges = set()
00057 
00058         self.parse_shape(shape, bounding_box)
00059         self.addToGroup(self._graphics_item)
00060 
00061         self._label = QGraphicsSimpleTextItem(label)
00062         self._label.setFont(GraphItem._LABEL_FONT)
00063         label_rect = self._label.boundingRect()
00064         if label_pos is None:
00065             label_rect.moveCenter(bounding_box.center())
00066         else:
00067             label_rect.moveCenter(label_pos)
00068         self._label.setPos(label_rect.x(), label_rect.y())
00069         self.addToGroup(self._label)
00070         if tooltip is not None:
00071             self.setToolTip(tooltip)
00072 
00073         self.set_node_color()
00074 
00075         self.setAcceptHoverEvents(True)
00076 
00077         self.hovershape = None
00078 
00079     def parse_shape(self, shape, bounding_box):
00080         if shape in ('box', 'rect', 'rectangle'):
00081             self._graphics_item = QGraphicsRectItem(bounding_box)
00082         elif shape in ('ellipse', 'oval', 'circle'):
00083             self._graphics_item = QGraphicsEllipseItem(bounding_box)
00084         elif shape in ('box3d', ):
00085             self._graphics_item = QGraphicsBox3dItem(bounding_box)
00086         else:
00087             print("Invalid shape '%s', defaulting to ellipse" % shape, file=sys.stderr)
00088             self._graphics_item = QGraphicsEllipseItem(bounding_box)
00089 
00090     def set_hovershape(self, newhovershape):
00091         self.hovershape = newhovershape
00092 
00093     def shape(self):
00094         if self.hovershape is not None:
00095             path = QPainterPath()
00096             path.addRect(self.hovershape)
00097             return path
00098         else:
00099             return super(self.__class__, self).shape()
00100 
00101     def add_incoming_edge(self, edge):
00102         self._incoming_edges.add(edge)
00103 
00104     def add_outgoing_edge(self, edge):
00105         self._outgoing_edges.add(edge)
00106 
00107     def set_node_color(self, color=None):
00108         if color is None:
00109             color = self._default_color
00110 
00111         self._brush.setColor(color)
00112         self._ellipse_pen.setColor(color)
00113         self._label_pen.setColor(color)
00114 
00115         self._graphics_item.setPen(self._ellipse_pen)
00116         self._label.setBrush(self._brush)
00117         self._label.setPen(self._label_pen)
00118 
00119     def hoverEnterEvent(self, event):
00120         # hovered node item in red
00121         self.set_node_color(self._COLOR_RED)
00122 
00123         if self._highlight_level > 1:
00124             cyclic_edges = self._incoming_edges.intersection(self._outgoing_edges)
00125             # incoming edges in blue
00126             incoming_nodes = set()
00127             for incoming_edge in self._incoming_edges.difference(cyclic_edges):
00128                 incoming_edge.set_node_color(self._COLOR_BLUE)
00129                 if incoming_edge.from_node != self:
00130                     incoming_nodes.add(incoming_edge.from_node)
00131             # outgoing edges in green
00132             outgoing_nodes = set()
00133             for outgoing_edge in self._outgoing_edges.difference(cyclic_edges):
00134                 outgoing_edge.set_node_color(self._COLOR_GREEN)
00135                 if outgoing_edge.to_node != self:
00136                     outgoing_nodes.add(outgoing_edge.to_node)
00137             # incoming/outgoing edges in teal
00138             for edge in cyclic_edges:
00139                 edge.set_node_color(self._COLOR_TEAL)
00140 
00141             if self._highlight_level > 2:
00142                 cyclic_nodes = incoming_nodes.intersection(outgoing_nodes)
00143                 # incoming nodes in blue
00144                 for incoming_node in incoming_nodes.difference(cyclic_nodes):
00145                     incoming_node.set_node_color(self._COLOR_BLUE)
00146                 # outgoing nodes in green
00147                 for outgoing_node in outgoing_nodes.difference(cyclic_nodes):
00148                     outgoing_node.set_node_color(self._COLOR_GREEN)
00149                 # incoming/outgoing nodes in teal
00150                 for node in cyclic_nodes:
00151                     node.set_node_color(self._COLOR_TEAL)
00152 
00153     def hoverLeaveEvent(self, event):
00154         self.set_node_color()
00155         if self._highlight_level > 1:
00156             for incoming_edge in self._incoming_edges:
00157                 incoming_edge.set_node_color()
00158                 if self._highlight_level > 2 and incoming_edge.from_node != self:
00159                     incoming_edge.from_node.set_node_color()
00160             for outgoing_edge in self._outgoing_edges:
00161                 outgoing_edge.set_node_color()
00162                 if self._highlight_level > 2 and outgoing_edge.to_node != self:
00163                     outgoing_edge.to_node.set_node_color()


qt_dotgraph
Author(s): Thibault Kruse
autogenerated on Thu Jun 6 2019 18:07:32