# -*- coding: utf-8 -*- # # Copyright (C) 2014 GNS3 Technologies Inc. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import xml.etree.ElementTree as ET from ..qt import QtCore, QtWidgets, QtGui from .drawing_item import DrawingItem from .utils import colorFromSvg import logging log = logging.getLogger(__name__) class TextItem(QtWidgets.QGraphicsTextItem, DrawingItem): """ Text item for the QGraphicsView. """ def __init__(self, svg=None, **kws): super().__init__(**kws) from ..main_window import MainWindow main_window = MainWindow.instance() view_settings = main_window.uiGraphicsView.settings() qt_font = QtGui.QFont() qt_font.fromString(view_settings["default_note_font"]) self.setDefaultTextColor(QtGui.QColor(view_settings["default_note_color"])) self.setFont(qt_font) if svg: try: svg = self.fromSvg(svg) except ET.ParseError as e: log.warning(str(e)) # re-evaluate `z` position after creation if 'z' in kws.keys(): self.setZValue(kws['z']) if self._id is None: self.create() def editText(self): """ Edit mode for this note. """ self.setTextInteractionFlags(QtCore.Qt.TextInteractionFlag.TextEditorInteraction) self.setSelected(True) self.setFocus() cursor = self.textCursor() cursor.select(QtGui.QTextCursor.SelectionType.Document) self.setTextCursor(cursor) def mouseDoubleClickEvent(self, event): """ Handles all mouse double click events. :param event: QMouseEvent instance """ self.editText() def focusOutEvent(self, event): """ Handles all focus out events. :param event: QFocusEvent instance """ self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsFocusable, False) cursor = self.textCursor() if cursor.hasSelection(): cursor.clearSelection() self.setTextCursor(cursor) self.setTextInteractionFlags(QtCore.Qt.TextInteractionFlag.NoTextInteraction) if not self.toPlainText(): # delete the note if empty self.delete() return else: self.updateDrawing() return super().focusOutEvent(event) def paint(self, painter, option, widget=None): """ Paints the contents of an item in local coordinates. :param painter: QPainter instance :param option: QStyleOptionGraphicsItem instance :param widget: QWidget instance """ super().paint(painter, option, widget) self.drawLayerInfo(painter) def toSvg(self): """ Return an SVG version of the text """ svg = ET.Element("svg") svg.set("width", str(int(self.boundingRect().width()))) svg.set("height", str(int(self.boundingRect().height()))) text = ET.SubElement(svg, "text") text.set("font-family", self.font().family()) text.set("font-size", str(self.font().pointSizeF())) if self.font().italic(): text.set("font-style", "italic") if self.font().bold(): text.set("font-weight", "bold") if self.font().strikeOut(): text.set("text-decoration", "line-through") elif self.font().underline(): text.set("text-decoration", "underline") text.set("fill", "#" + hex(self.defaultTextColor().rgba())[4:]) text.set("fill-opacity", str(self.defaultTextColor().alphaF())) text.text = self.toPlainText() or " " svg = ET.tostring(svg, encoding="utf-8").decode("utf-8") return svg def fromSvg(self, svg): # sometimes we receive \0 at the end of string inside element try: svg = svg.replace("\u0000", "") except AttributeError: pass try: svg = ET.fromstring(svg) except ET.ParseError: self.setPlainText("Unable to parse `text_item`") return text = svg[0] font = QtGui.QFont() color = text.get("fill") if color: new_color = colorFromSvg(color) color = self.defaultTextColor() color.setBlue(new_color.blue()) color.setRed(new_color.red()) color.setGreen(new_color.green()) self.setDefaultTextColor(color) opacity = text.get("fill-opacity") if opacity: color = self.defaultTextColor() color.setAlphaF(float(opacity)) self.setDefaultTextColor(color) font.setPointSizeF(float(text.get("font-size", self.font().pointSizeF()))) font.setFamily(text.get("font-family", self.font().family())) if text.get("font-style") == "italic": font.setItalic(True) if text.get("font-weight") == "bold": font.setBold(True) if text.get("text-decoration") == "underline": font.setUnderline(True) if text.get("text-decoration") == "line-through": font.setStrikeOut(True) self.setFont(font) self.setPlainText(text.text) def editable(self): """ Returns either the note is editable or not. :return: boolean """ return True def keyPressEvent(self, event): """ Handles all key press events :param event: QKeyEvent """ if not self.handleKeyPressEvent(event): super().keyPressEvent(event)