graphics_node_item.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. """
  2. QGraphics representation class for a node element.
  3. An object with a defined size (120x120) on screen which can either be
  4. an image file or a set of primitives.
  5. """
  6. from enum import Enum
  7. import base64
  8. from PyQt5.QtWidgets import QGraphicsItem, QStyleOptionGraphicsItem, QWidget
  9. from PyQt5.Qt import QRectF, QPainter, QFont, Qt, QBrush, QColor, QImage
  10. class IconType(Enum):
  11. IMAGE = 0
  12. PRIMITIVE = 1
  13. class GraphicsNodeItem(QGraphicsItem):
  14. def __init__(self, node_id, node_type="", consyn=None):
  15. QGraphicsItem.__init__(self)
  16. self.node_id = node_id
  17. self._type = node_type
  18. self._consyn = consyn
  19. self._is_highlighted = False
  20. self._highlight_color = None
  21. self._icon_type = None
  22. self._font = QFont()
  23. self._font.setPixelSize(12)
  24. self.setZValue(1.0)
  25. def set_type(self, node_type):
  26. self._type = node_type
  27. self.update(self.boundingRect())
  28. def update_consyn(self, consyn):
  29. self._consyn = consyn
  30. self.update(self.boundingRect())
  31. def get_type(self):
  32. return self._type
  33. def boundingRect(self):
  34. bbox = QRectF(0, 0, 120, 120)
  35. return bbox
  36. def set_highlighted(self, highlight, color):
  37. self._is_highlighted = highlight
  38. self._highlight_color = color
  39. def paint(self, painter, option, widget=None):
  40. # type: (QPainter, QStyleOptionGraphicsItem, QWidget) -> None
  41. # draw type text and bounding rectangle
  42. painter.setFont(self._font)
  43. # draw bounding rectangle
  44. painter.setBrush(QBrush(Qt.white))
  45. if self._is_highlighted:
  46. painter.setPen(self._highlight_color)
  47. painter.drawRect(self.boundingRect())
  48. text_box = QRectF(0, 100, 120, 20)
  49. painter.drawRect(text_box)
  50. painter.setPen(Qt.black)
  51. painter.setBrush(QBrush(QColor(0, 0, 0, 0)))
  52. painter.drawText(text_box, Qt.AlignCenter | Qt.TextDontClip, self._type)
  53. # draw concrete syntax
  54. if not self._consyn:
  55. # nothing to draw, so leave empty
  56. return
  57. # first, determine if we have an actual image file or a primitive group
  58. for item in self._consyn:
  59. if item["type"] == "Icon":
  60. if item["is_primitive"]:
  61. self._icon_type = IconType.PRIMITIVE
  62. else:
  63. self._icon_type = IconType.IMAGE
  64. break
  65. if not self._icon_type:
  66. print("Could not determine CS icon type for type {}".format(self._type))
  67. return
  68. if self._icon_type == IconType.IMAGE:
  69. # an actual image file, so load and display it
  70. img_data_b64 = None
  71. for item in self._consyn:
  72. if item["type"] == "Image":
  73. img_data_b64 = item["data"]
  74. break
  75. if not img_data_b64:
  76. print("Could not find image data for type {}".format(self._type))
  77. return
  78. img_data = base64.b64decode(img_data_b64)
  79. qimg = QImage.fromData(img_data)
  80. painter.drawImage(QRectF(0, 0, 100, 100), qimg)
  81. else:
  82. # a set of primitives
  83. for item in self._consyn:
  84. item_type = item["type"]
  85. # ignore the "useless" Icon class
  86. if item_type == "Icon":
  87. continue
  88. if item_type == "Rectangle":
  89. rect = QRectF(item["x"], item["y"], item["width"], item["height"])
  90. painter.drawRect(rect)
  91. elif item_type == "Ellipse":
  92. painter.drawEllipse(item["x"], item["y"], item["width"], item["height"])
  93. elif item_type == "Line":
  94. painter.drawLine(item["start_x"], item["start_y"], item["end_x"], item["end_y"])
  95. else:
  96. print("No paint implemented for primitive {}".format(item_type))