123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- """
- QGraphics representation class for a node element.
- An object with a defined size (120x120) on screen which can either be
- an image file or a set of primitives.
- """
- from enum import Enum
- import base64
- from PyQt5.QtWidgets import QGraphicsItem, QStyleOptionGraphicsItem, QWidget
- from PyQt5.Qt import QRectF, QPainter, QFont, Qt, QBrush, QColor, QImage
- class IconType(Enum):
- IMAGE = 0
- PRIMITIVE = 1
- class GraphicsNodeItem(QGraphicsItem):
- def __init__(self, node_id, node_type="", consyn=None):
- QGraphicsItem.__init__(self)
- self.node_id = node_id
- self._type = node_type
- self._consyn = consyn
- self._is_highlighted = False
- self._highlight_color = None
- self._icon_type = None
- self._font = QFont()
- self._font.setPixelSize(12)
- self.setZValue(1.0)
- def set_type(self, node_type):
- self._type = node_type
- self.update(self.boundingRect())
- def update_consyn(self, consyn):
- self._consyn = consyn
- self.update(self.boundingRect())
- def get_type(self):
- return self._type
- def boundingRect(self):
- bbox = QRectF(0, 0, 120, 120)
- return bbox
- def set_highlighted(self, highlight, color):
- self._is_highlighted = highlight
- self._highlight_color = color
- def paint(self, painter, option, widget=None):
- # type: (QPainter, QStyleOptionGraphicsItem, QWidget) -> None
- # draw type text and bounding rectangle
- painter.setFont(self._font)
- painter.setRenderHint(QPainter.SmoothPixmapTransform)
- # draw bounding rectangle
- painter.setBrush(QBrush(Qt.white))
- if self._is_highlighted:
- painter.setPen(self._highlight_color)
- painter.drawRect(self.boundingRect())
- text_box = QRectF(0, 100, 120, 20)
- painter.drawRect(text_box)
- painter.setPen(Qt.black)
- painter.setBrush(QBrush(QColor(0, 0, 0, 0)))
- painter.drawText(text_box, Qt.AlignCenter | Qt.TextDontClip, self._type)
- # draw concrete syntax
- if not self._consyn:
- # nothing to draw, so leave empty
- return
- # first, determine if we have an actual image file or a primitive group
- for item in self._consyn:
- if item["type"] == "Icon":
- if item["is_primitive"]:
- self._icon_type = IconType.PRIMITIVE
- else:
- self._icon_type = IconType.IMAGE
- break
- if not self._icon_type:
- print("Could not determine CS icon type for type {}".format(self._type))
- return
- if self._icon_type == IconType.IMAGE:
- # an actual image file, so load and display it
- img_data_b64 = None
- for item in self._consyn:
- if item["type"] == "Image":
- img_data_b64 = item["data"]
- break
- if not img_data_b64:
- print("Could not find image data for type {}".format(self._type))
- return
- img_data = base64.b64decode(img_data_b64)
- qimg = QImage.fromData(img_data)
- painter.drawImage(QRectF(5, 5, 95, 95), qimg)
- else:
- # a set of primitives
- for item in self._consyn:
- item_type = item["type"]
- # ignore the "useless" Icon class
- if item_type == "Icon":
- continue
- if item_type == "Rectangle":
- rect = QRectF(item["x"], item["y"], item["width"], item["height"])
- painter.drawRect(rect)
- elif item_type == "Ellipse":
- painter.drawEllipse(item["x"], item["y"], item["width"], item["height"])
- elif item_type == "Line":
- painter.drawLine(item["start_x"], item["start_y"], item["end_x"], item["end_y"])
- else:
- print("No paint implemented for primitive {}".format(item_type))
|