00001 """
00002 Copyright (c) 2013, Cogniteam
00003 All rights reserved.
00004
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met:
00007
00008 * Redistributions of source code must retain the above copyright
00009 notice, this list of conditions and the following disclaimer.
00010
00011 * Redistributions in binary form must reproduce the above copyright
00012 notice, this list of conditions and the following disclaimer in the
00013 documentation and/or other materials provided with the distribution.
00014
00015 * Neither the name of the Cogniteam nor the
00016 names of its contributors may be used to endorse or promote products
00017 derived from this software without specific prior written permission.
00018
00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00020 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
00023 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 """
00030
00031 from python_qt_binding.QtCore import Qt
00032 from python_qt_binding.QtGui import QBrush, QGraphicsTextItem, QPen, QPainterPath, QColor
00033 from .graph_item import GraphItem
00034 from .shape_factory import ShapeFactory
00035
00036
00037 class DmgHtmlNodeItem(GraphItem):
00038 HIGHLIGHT_LEVEL = 1
00039 HOVERED_COLOR = QColor(250, 0, 0)
00040 HIGHLIGHTED_COLOR = QColor(100, 100, 100)
00041 HIGHLIGHTED_PEN_WIDTH = 2.0
00042 HIGHLIGHTED_LABEL_PEN_WIDTH = 1.0
00043
00044 def __init__(self, bounding_box, shape, label, label_pos=None, url=None, parent=None, **kwargs):
00045 super(DmgHtmlNodeItem, self).__init__(parent, **kwargs)
00046 self.url = url
00047 self._incoming_edges = set()
00048 self._outgoing_edges = set()
00049 self._brush = QBrush(self._color)
00050
00051 self._label_pen = QPen()
00052 self._label_pen.setColor(self._color)
00053 self._label_pen.setJoinStyle(Qt.RoundJoin)
00054 self._label_pen.setWidthF(self._label_pen_width)
00055
00056 self._graphics_item_pen = QPen(self._label_pen)
00057 self._graphics_item_pen.setWidthF(self._pen_width)
00058
00059 self._label = QGraphicsTextItem()
00060 self._label.setHtml(label)
00061
00062 label_rectangle = self._label.boundingRect()
00063 if label_pos is None:
00064 label_rectangle.moveCenter(bounding_box.center())
00065 else:
00066 label_rectangle.moveCenter(label_pos)
00067 self._label.setPos(label_rectangle.x(), label_rectangle.y())
00068
00069 self.addToGroup(self._label)
00070
00071 self._graphics_item = ShapeFactory.create(shape, bounding_box)
00072 if ShapeFactory.message is not None:
00073 print ShapeFactory.message
00074 self.addToGroup(self._graphics_item)
00075
00076 self._brush.setColor(self._color)
00077 self._graphics_item_pen.setColor(self._color)
00078 self._label_pen.setColor(self._color)
00079
00080 self._graphics_item.setPen(self._graphics_item_pen)
00081
00082 self._highlight_level = kwargs.get('highlight_level', self.HIGHLIGHT_LEVEL)
00083 self._hovered_color = kwargs.get('hovered_color', self.HOVERED_COLOR)
00084 self._highlighted_color = kwargs.get('highlighted_color', self.HIGHLIGHTED_COLOR)
00085 self._highlighted_pen_width = kwargs.get('highlighted_pen_width', self.HIGHLIGHTED_PEN_WIDTH)
00086 self._highlighted_label_pen_width = kwargs.get('highlighted_label_pen_width', self.HIGHLIGHTED_LABEL_PEN_WIDTH)
00087
00088 self.hover_shape = None
00089 self.setAcceptHoverEvents(True)
00090
00091 def add_incoming_edge(self, edge):
00092 self._incoming_edges.add(edge)
00093
00094 def add_outgoing_edge(self, edge):
00095 self._outgoing_edges.add(edge)
00096
00097 def set_color(self, color=None):
00098 if color is None:
00099 color = self._color
00100
00101 self._brush.setColor(color)
00102 self._graphics_item_pen.setColor(color)
00103 self._label.setDefaultTextColor(color)
00104
00105 self._graphics_item.setPen(self._graphics_item_pen)
00106
00107 def set_hover_shape(self, shape):
00108 self.hover_shape = shape
00109
00110 def shape(self):
00111 if self.hover_shape is not None:
00112 path = QPainterPath()
00113 path.addRect(self.hover_shape)
00114 return path
00115
00116 return super(GraphItem, self).shape()
00117
00118 def hoverEnterEvent(self, event):
00119 self.set_color(self._highlighted_color)
00120 self._highlight_connections()
00121
00122 def hoverLeaveEvent(self, event):
00123 self.set_color()
00124 self._highlight_connections(False)
00125
00126 def _highlight_connections(self, highlighted=True):
00127 if highlighted:
00128 if self._highlight_level > 1:
00129 cyclic_edges = self._incoming_edges.intersection(self._outgoing_edges)
00130
00131 incoming_nodes = set()
00132 for incoming_edge in self._incoming_edges.difference(cyclic_edges):
00133 incoming_edge.set_color(self.COLOR_BLUE)
00134 if incoming_edge.from_node != self:
00135 incoming_nodes.add(incoming_edge.from_node)
00136
00137 outgoing_nodes = set()
00138 for outgoing_edge in self._outgoing_edges.difference(cyclic_edges):
00139 outgoing_edge.set_color(self.COLOR_GREEN)
00140 if outgoing_edge.to_node != self:
00141 outgoing_nodes.add(outgoing_edge.to_node)
00142
00143 for edge in cyclic_edges:
00144 edge.set_color(self.COLOR_TEAL)
00145
00146 if self._highlight_level > 2:
00147 cyclic_nodes = incoming_nodes.intersection(outgoing_nodes)
00148
00149 for incoming_node in incoming_nodes.difference(cyclic_nodes):
00150 incoming_node.set_color(self.COLOR_BLUE)
00151
00152 for outgoing_node in outgoing_nodes.difference(cyclic_nodes):
00153 outgoing_node.set_color(self.COLOR_GREEN)
00154
00155 for node in cyclic_nodes:
00156 node.set_color(self.COLOR_TEAL)
00157 else:
00158 if self._highlight_level > 1:
00159 for incoming_edge in self._incoming_edges:
00160 incoming_edge.set_color()
00161 if self.highlight_level > 2 and incoming_edge.from_node != self:
00162 incoming_edge.from_node.set_color()
00163 for outgoing_edge in self._outgoing_edges:
00164 outgoing_edge.set_color()
00165 if self.highlight_level > 2 and outgoing_edge.to_node != self:
00166 outgoing_edge.to_node.set_color()
00167
00168 def highlight(self, highlighted=True):
00169 if highlighted:
00170 self._graphics_item_pen.setWidthF(self._highlighted_pen_width)
00171 else:
00172 self._graphics_item_pen.setWidthF(self._pen_width)
00173
00174 self._graphics_item.setPen(self._graphics_item_pen)