def draw_word_boxes(self, word_boxes: list) -> None: """Sets up and draws translated words and their corresponding frames :param word_boxes: list of WordBox namedtuples, each representing a word and frame to be drawn. ex: [WordBox('word'=str, 'geometry'=[(int, int)], WordBox('word'=str, 'geometry'=[(int, int)]) """ for wPoly in self.__word_polygons: self.__scene.removeItem(wPoly[0]) self.__scene.removeItem(wPoly[1]) self.__word_polygons = [] for word_box in word_boxes: points = list(map(lambda x: QPoint(x[0], x[1]), word_box.geometry)) text = QGraphicsTextItem(word_box.word) text.setOpacity(0) text.setAcceptHoverEvents(False) font = QFont() font.setPixelSize(abs(points[0].y() - points[3].y())) text.setFont(font) w = text.boundingRect().width() h = text.boundingRect().height() text.setPos( points[0].x() + abs(points[0].x() - points[1].x()) / 2 - w / 2, points[0].y() + abs(points[0].y() - points[3].y()) / 2 - h / 2) frame = WordPolygon(QPolygonF(QPolygon(points)), text) self.__word_polygons.append([text, frame]) self.__scene.addItem(frame) self.__scene.addItem(text)
def drawScene(self, scene): scaleDpi = 101.0 / 72.0 # (true res for 344x193 mm, 1366x768) / 72 LLx = self.graph.boundingBox['LLx'] LLy = self.graph.boundingBox['LLx'] URx = self.graph.boundingBox['URx'] URy = self.graph.boundingBox['URy'] scene.addRect(LLx * scaleDpi, LLy * scaleDpi, URx * scaleDpi, URy * scaleDpi) scale = 96 # maybe this is because GV uses 96 dpi and operates in inches for node in self.graph.nodesPtr: ng = self.graph.nodeGeometry(node) x = ng['centerX'] * scaleDpi y = (self.graph.boundingBox['URy'] - ng['centerY']) * scaleDpi rx = (ng['width'] / 2) * scale ry = (ng['height'] / 2) * scale el = NodeShape(x - rx, y - ry, 2 * rx, 2 * ry) label = self.graph.nodeLabel(node) lbl = QGraphicsTextItem(self.tr(label), el) # TODO: text positioniong lbl.setAcceptHoverEvents(False) # TODO: try to make child.event() lbl.setPos(x, y) scene.addItem(el) for edge in self.graph.edgesGeom: # TODO: edges hover spl = edge[0] if not spl['sflag']: start = spl['points'][0] else: start = spl['sarrowtip'] if not spl['eflag']: end = spl['points'][-1] else: end = spl['earrowtip'] x1 = start['x'] * scaleDpi y1 = (self.graph.boundingBox['URy'] - start['y']) * scaleDpi x2 = end['x'] * scaleDpi y2 = (self.graph.boundingBox['URy'] - end['y']) * scaleDpi scene.addLine(x1, y1, x2, y2)
class BaseItem(QAbstractGraphicsShapeItem): """ Base class for visualization items. """ cycleValuesOnKeypress = {} hotkeys = {} defaultAutoTextKeys = [] def __init__(self, model_item=None, prefix="", parent=None): """ Creates a visualization item. """ QAbstractGraphicsShapeItem.__init__(self, parent) self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemSendsGeometryChanges | QGraphicsItem.ItemSendsScenePositionChanges) self._model_item = model_item if self._model_item is not None: self._model_item.model().dataChanged.connect(self.onDataChanged) # initialize members self._prefix = prefix self._auto_text_keys = self.defaultAutoTextKeys[:] self._text = "" self._text_bg_brush = None self._text_item = QGraphicsTextItem(self) self._text_item.setPos(0, 0) self._text_item.setAcceptHoverEvents(False) self._text_item.setFlags(QGraphicsItem.ItemIgnoresTransformations) self._text_item.setHtml(self._compile_text()) self._valid = True if len(self.cycleValuesOnKeypress) > 0: logging.warning( "cycleValueOnKeypress is deprecated and will be removed in the future. " + "Set BaseItem.hotkeys instead with cycleValue()") self.changeColor() def changeColor(self): if self._model_item is not None: c = self._model_item.getColor() if c is not None: self.setColor(c) return self.setColor(Qt.yellow) def onDataChanged(self, indexFrom, indexTo): # FIXME why is this not updated, when changed graphically via attribute box ? #print "onDataChanged", self._model_item.index(), indexFrom, indexTo, indexFrom.parent() if indexFrom == self._model_item.index(): self.changeColor() #print "hit" # self._text_item.setHtml(self._compile_text()) def modelItem(self): """ Returns the model item of this items. """ return self._model_item def index(self): """ Returns the index of this item. """ return self._model_item.index() def prefix(self): """ Returns the key prefix of the item. """ return self._prefix def setPen(self, pen): pen = QPen(pen) # convert to pen if argument is a QColor QAbstractGraphicsShapeItem.setPen(self, pen) self._text_item.setDefaultTextColor(pen.color()) def setText(self, text=""): """ Sets a text to be displayed on this item. """ self._text = text self._text_item.setHtml(self._compile_text()) def text(self): return self._text def setTextBackgroundBrush(self, brush=None): """ Sets the brush to be used to fill the background region behind the text. Set to None to not draw a background (leave transparent). """ self._text_bg_brush = brush def textBackgroundBrush(self): """ Returns the background brush for the text region. """ return self._text_bg_brush def setAutoTextKeys(self, keys=None): """ Sets the keys for which the values from the annotations are displayed automatically as text. """ self._auto_text_keys = keys or [] self._text_item.setHtml(self._compile_text()) def autoTextKeys(self): """ Returns the list of keys for which the values from the annotations are displayed as text automatically. """ return self._auto_text_keys def isValid(self): """ Return whether this graphics item is valid, i.e. has a matching, valid model item connected to it. An item is by default valid, will only be set invalid on failure. """ return self._valid def setValid(self, val): self._valid = val def _compile_text(self): text_lines = [] if self._text != "" and self._text is not None: text_lines.append(self._text) for key in self._auto_text_keys: text_lines.append("%s: %s" % \ (key, self._model_item.get(key, ""))) return '<br/>'.join(text_lines) def dataChanged(self): self.dataChange() self._text_item.setHtml(self._compile_text()) self.update() def dataChange(self): pass def updateModel(self, ann=None): if ann is not None: self._model_item.update(ann) def boundingRect(self): return QRectF(0, 0, 0, 0) def setColor(self, color): self.setPen(color) self.setBrush(color) self.update() def paint(self, painter, option, widget=None): pass def itemChange(self, change, value): if change == QGraphicsItem.ItemPositionHasChanged: self.updateModel() return QAbstractGraphicsShapeItem.itemChange(self, change, value) def keyPressEvent(self, event): """ This handles the value cycling as defined in cycleValuesOnKeypress. """ if str(event.text()) in self.cycleValuesOnKeypress: itemkey, valuelist = self.cycleValuesOnKeypress[str(event.text())] if isinstance(itemkey, IgnorePrefix): itemkey = itemkey.value else: itemkey = self.prefix() + itemkey if len(valuelist) > 0: oldvalue = self._model_item.get(itemkey, None) if oldvalue is None: nextindex = 0 else: try: nextindex = valuelist.index(oldvalue) + 1 nextindex %= len(valuelist) except ValueError: nextindex = 0 newvalue = valuelist[nextindex] if newvalue is None: if oldvalue is not None: self._model_item.delete(itemkey) else: self._model_item[itemkey] = valuelist[nextindex] self.dataChanged() event.accept() elif str(event.text()) in self.hotkeys: self.hotkeys[str(event.text())](self) event.accept()