def __init__(self, spline, label, label_center, from_node, to_node, parent=None, **kwargs): super(EdgeItem, self).__init__(parent, **kwargs) self._edge_pen_width = kwargs.get('edge_pen_width', self.EDGE_PEN_WIDTH) self.from_node = from_node self.from_node.add_outgoing_edge(self) self.to_node = to_node self.to_node.add_incoming_edge(self) self._brush = QBrush(self._color) self._label_pen = QPen() self._label_pen.setColor(self._color) self._label_pen.setJoinStyle(Qt.RoundJoin) self._label_pen.setWidthF(self._label_pen_width) self._edge_pen = QPen() self._edge_pen.setColor(self._color) self._edge_pen.setWidthF(self._edge_pen_width) self._sibling_edges = set() self._label = None if label is not None: self._label = QGraphicsSimpleTextItem(label) font = self._label.font() font.setPointSize(8) self._label.setFont(font) label_rect = self._label.boundingRect() label_rect.moveCenter(label_center) self._label.setPos(label_rect.x(), label_rect.y()) # spline specification according to http://www.graphviz.org/doc/info/attrs.html#k:splineType coordinates = spline.split(' ') # extract optional end_point end_point = None if coordinates[0].startswith('e,'): parts = coordinates.pop(0)[2:].split(',') end_point = QPointF(float(parts[0]), -float(parts[1])) # extract optional start_point if coordinates[0].startswith('s,'): parts = coordinates.pop(0).split(',') # first point parts = coordinates.pop(0).split(',') point = QPointF(float(parts[0]), -float(parts[1])) path = QPainterPath(point) while len(coordinates) > 2: # extract triple of points for a cubic spline parts = coordinates.pop(0).split(',') point1 = QPointF(float(parts[0]), -float(parts[1])) parts = coordinates.pop(0).split(',') point2 = QPointF(float(parts[0]), -float(parts[1])) parts = coordinates.pop(0).split(',') point3 = QPointF(float(parts[0]), -float(parts[1])) path.cubicTo(point1, point2, point3) self._arrow = None if end_point is not None: # draw arrow self._arrow = QGraphicsPolygonItem() polygon = QPolygonF() polygon.append(point3) offset = QPointF(end_point - point3) corner1 = QPointF(-offset.y(), offset.x()) * 0.35 corner2 = QPointF(offset.y(), -offset.x()) * 0.35 polygon.append(point3 + corner1) polygon.append(end_point) polygon.append(point3 + corner2) self._arrow.setPolygon(polygon) self._path = QGraphicsPathItem() self._path.setPath(path) self.addToGroup(self._path) self._brush.setColor(self._color) self._edge_pen.setColor(self._color) self._label_pen.setColor(self._color) self._path.setPen(self._edge_pen) if self._arrow is not None: self._arrow.setBrush(self._brush) self._arrow.setPen(self._edge_pen) if self._label is not None: self._label.setBrush(self._brush) self._label.setPen(self._label_pen)
def __init__(self, highlight_level, spline, label_center, label, from_node, to_node, parent=None, penwidth=1, edge_color=None, style='solid'): super(EdgeItem, self).__init__(highlight_level, parent) self.from_node = from_node self.from_node.add_outgoing_edge(self) self.to_node = to_node self.to_node.add_incoming_edge(self) self._default_edge_color = self._COLOR_BLACK if edge_color is not None: self._default_edge_color = edge_color self._default_text_color = self._COLOR_BLACK self._default_color = self._COLOR_BLACK self._text_brush = QBrush(self._default_color) self._shape_brush = QBrush(self._default_color) if style in ['dashed', 'dotted']: self._shape_brush = QBrush(Qt.transparent) self._label_pen = QPen() self._label_pen.setColor(self._default_text_color) self._label_pen.setJoinStyle(Qt.RoundJoin) self._edge_pen = QPen(self._label_pen) self._edge_pen.setWidth(penwidth) self._edge_pen.setColor(self._default_edge_color) self._edge_pen.setStyle(self._qt_pen_styles.get(style, Qt.SolidLine)) self._sibling_edges = set() self._label = None if label is not None: self._label = QGraphicsSimpleTextItem(label) label_rect = self._label.boundingRect() label_rect.moveCenter(label_center) self._label.setPos(label_rect.x(), label_rect.y()) self._label.hoverEnterEvent = self._handle_hoverEnterEvent self._label.hoverLeaveEvent = self._handle_hoverLeaveEvent self._label.setAcceptHoverEvents(True) # spline specification according to http://www.graphviz.org/doc/info/attrs.html#k:splineType coordinates = spline.split(' ') # extract optional end_point end_point = None if (coordinates[0].startswith('e,')): parts = coordinates.pop(0)[2:].split(',') end_point = QPointF(float(parts[0]), -float(parts[1])) # extract optional start_point if (coordinates[0].startswith('s,')): parts = coordinates.pop(0).split(',') # first point parts = coordinates.pop(0).split(',') point = QPointF(float(parts[0]), -float(parts[1])) path = QPainterPath(point) while len(coordinates) > 2: # extract triple of points for a cubic spline parts = coordinates.pop(0).split(',') point1 = QPointF(float(parts[0]), -float(parts[1])) parts = coordinates.pop(0).split(',') point2 = QPointF(float(parts[0]), -float(parts[1])) parts = coordinates.pop(0).split(',') point3 = QPointF(float(parts[0]), -float(parts[1])) path.cubicTo(point1, point2, point3) self._arrow = None if end_point is not None: # draw arrow self._arrow = QGraphicsPolygonItem() polygon = QPolygonF() polygon.append(point3) offset = QPointF(end_point - point3) corner1 = QPointF(-offset.y(), offset.x()) * 0.35 corner2 = QPointF(offset.y(), -offset.x()) * 0.35 polygon.append(point3 + corner1) polygon.append(end_point) polygon.append(point3 + corner2) self._arrow.setPolygon(polygon) self._arrow.hoverEnterEvent = self._handle_hoverEnterEvent self._arrow.hoverLeaveEvent = self._handle_hoverLeaveEvent self._arrow.setAcceptHoverEvents(True) self._path = QGraphicsPathItem() self._path.setPath(path) self.addToGroup(self._path) self.set_node_color() self.set_label_color()
def addGraph(self, graph_str): graph = graph_str.splitlines() header = graph[0].split() if header[0] != 'graph': raise Exception('wrong graph format', 'header is: ' + graph[0]) self.scale_factor = 100.0 self.width = float(header[2]) self.height = float(header[3]) print "QGraphicsScene size:", self.width, self.height self.scene = GraphScene( QRectF(0, 0, self.scX(self.width), self.scY(self.height))) for l in graph: items = l.split() if len(items) == 0: continue elif items[0] == 'stop': break elif items[0] == 'node': #node CImp 16.472 5.25 0.86659 0.5 CImp filled ellipse lightblue lightblue if len(items) != 11: raise Exception('wrong number of items in line', 'line is: ' + l) name = items[6] if name == "\"\"": name = "" w = self.scX(items[4]) h = self.scY(items[5]) x = self.tfX(items[2]) y = self.tfY(items[3]) self.nodes[name] = self.scene.addEllipse( x - w / 2, y - h / 2, w, h) self.nodes[name].setData(0, name) text_item = self.scene.addSimpleText(name) br = text_item.boundingRect() text_item.setPos(x - br.width() / 2, y - br.height() / 2) elif items[0] == 'edge': # without label: # edge CImp Ts 4 16.068 5.159 15.143 4.9826 12.876 4.5503 11.87 4.3583 solid black # # with label: # edge b_stSplit TorsoVelAggregate 7 7.5051 6.3954 7.7054 6.3043 7.9532 6.1899 8.1728 6.0833 8.4432 5.9522 8.7407 5.8012 8.9885 5.6735 aa 8.6798 5.9792 solid black line_len = int(items[3]) label_text = None label_pos = None if (line_len * 2 + 6) == len(items): # no label pass elif (line_len * 2 + 9) == len(items): # edge with label label_text = items[4 + line_len * 2] label_pos = QPointF(self.tfX(items[4 + line_len * 2 + 1]), self.tfY(items[4 + line_len * 2 + 2])) else: raise Exception( 'wrong number of items in line', 'should be: ' + str(line_len * 2 + 6) + " or " + str(line_len * 2 + 9) + ', line is: ' + l) line = [] for i in range(line_len): line.append((self.tfX(items[4 + i * 2]), self.tfY(items[5 + i * 2]))) control_points_idx = 1 path = QPainterPath(QPointF(line[0][0], line[0][1])) while True: q1 = line[control_points_idx] q2 = line[control_points_idx + 1] p2 = line[control_points_idx + 2] path.cubicTo(q1[0], q1[1], q2[0], q2[1], p2[0], p2[1]) control_points_idx = control_points_idx + 3 if control_points_idx >= len(line): break edge = self.scene.addPath(path) edge.setData(0, (items[1], items[2])) self.edges.append(edge) end_p = QPointF(line[-1][0], line[-1][1]) p0 = end_p - QPointF(line[-2][0], line[-2][1]) p0_norm = math.sqrt(p0.x() * p0.x() + p0.y() * p0.y()) p0 = p0 / p0_norm p0 = p0 * self.scale_factor * 0.15 p1 = QPointF(p0.y(), -p0.x()) * 0.25 p2 = -p1 poly = QPolygonF() poly.append(p0 + end_p) poly.append(p1 + end_p) poly.append(p2 + end_p) poly.append(p0 + end_p) # poly_path = QPainterPath() # poly_path.addPolygon(poly) # painter = QPainter() self.scene.addPolygon(poly) if label_text and label_pos: if label_text[0] == "\"": label_text = label_text[1:] if label_text[-1] == "\"": label_text = label_text[:-1] label_text = label_text.replace("\\n", "\n") label_item = self.scene.addSimpleText(label_text) br = label_item.boundingRect() label_item.setPos(label_pos.x() - br.width() / 2, label_pos.y() - br.height() / 2)