def draw(cls, x, y, self: PreparedText, painter: QPainter): font = QFont(self.fontName) if self.fontSize: font.setPointSizeF(self.fontSize) if self.fontBold: font.setBold(True) if self.fontItalic: font.setItalic(True) brushStyle = self.brushStyle or Qt.BrushStyle.SolidPattern w = self.width h = self.height tx = self.left + x ty = self.top + y if self.border: w -= self.border.width h -= self.border.width * 2 tx += self.border.width ty += self.border.width rect = QRectF(tx, ty, w, h) if self.backColor: painter.setBrush(brush_style_map[brushStyle]) painter.fillRect(rect, QColor('#' + hex(self.backColor)[2:])) if self.allowTags: doc = QTextDocument() doc.setDefaultFont(font) doc.setHtml(self.text) doc.setDocumentMargin(0) painter.save() painter.translate(tx + 2, ty + 1) doc.drawContents(painter, QRectF(0, 0, self.width, self.height)) painter.restore() else: painter.save() painter.setFont(font) flags = cls.textFlags(self) rect.setX(rect.x() + 2) rect.setY(rect.y() + 1) painter.drawText(rect, flags, self.text) painter.restore() if self.border and self.border.color is not None: old_pen = painter.pen() pen = QPen( QColor(self.border.color), self.border.width, pen_style_map.get(self.border.style, Qt.PenStyle.SolidLine)) painter.setPen(pen) painter.drawLines( cls.getLines(self, self.left + x, self.top + y, self.left + self.width + x, self.top + y + self.height)) painter.setPen(old_pen)
def f(): doc = QTextDocument() tables = lookup(line.text()) doc.setHtml( template.render(request={"script_root": ""}, tables=tables, url_for=lambda *_, **__: None)) doc.setTextWidth(doc.size().width()) pixmap = QPixmap(doc.size().width(), doc.size().height()) pixmap.fill(QColor(0, 0, 0, 0)) painter = QPainter(pixmap) doc.drawContents(painter) painter.end() lab.setPixmap(pixmap) lab.setFixedSize(pixmap.size())
class QBlockCode(QCachedGraphicsItem): """ Top-level code widget for a selection of text. Will construct an AST using QBlockCodeObj, mirroring the structure associated with the target object. This text is then rendered using a QTextDocument, with appropriate styles applied to it. Interaction events will be propagated to corresponding objects. """ GRAPH_ADDR_SPACING = 20 addr: int _addr_str: str obj: QBlockCodeObj _config: ConfigurationManager disasm_view: 'QDisassemblyBaseControl' workspace: 'Workspace' infodock: InfoDock parent: Any def __init__(self, addr: int, obj: QBlockCodeObj, config: ConfigurationManager, disasm_view: 'QDisassemblyBaseControl', workspace: 'Workspace', infodock: InfoDock, parent: Any = None): super().__init__(parent=parent) self.addr = addr self._addr_str = "%08x" % self.addr self._addr_item: QGraphicsSimpleTextItem = None self.obj = obj self._width = 0 self._height = 0 self._config = config self.parent = parent self.workspace = workspace self.infodock = infodock self._disasm_view = disasm_view self._qtextdoc = QTextDocument() self._qtextdoc.setDefaultFont(self._config.disasm_font) self._qtextdoc.setDocumentMargin(0) self._addr_item = QGraphicsSimpleTextItem(self._addr_str, self) self._addr_item.setBrush(Conf.disasm_view_node_address_color) self._addr_item.setFont(Conf.disasm_font) self.update_document() self.setToolTip("Address: " + self._addr_str) self.refresh() def refresh(self): self._addr_item.setVisible(self._disasm_view.show_address) self._layout_items_and_update_size() def update_document(self): self._qtextdoc.clear() cur = QTextCursor(self._qtextdoc) self.obj.render_to_doc(cur) def paint(self, painter, option, widget): #pylint: disable=unused-argument self.update_document() painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform | QPainter.HighQualityAntialiasing) painter.setFont(self._config.disasm_font) if self.infodock.is_instruction_selected( self.addr) or self.obj.should_highlight_line: highlight_color = Conf.disasm_view_node_instruction_selected_background_color painter.setBrush(highlight_color) painter.setPen(highlight_color) painter.drawRect(0, 0, self.width, self.height) x = 0 if self._disasm_view.show_address: x += self._addr_item.boundingRect().width( ) + self.GRAPH_ADDR_SPACING painter.translate(QPointF(x, 0)) self._qtextdoc.drawContents(painter) # # Event handlers # def get_obj_for_mouse_event(self, event: QMouseEvent) -> QBlockCodeObj: p = event.pos() if self._disasm_view.show_address: offset = self._addr_item.boundingRect().width( ) + self.GRAPH_ADDR_SPACING p.setX(p.x() - offset) if p.x() >= 0: hitpos = self._qtextdoc.documentLayout().hitTest( p, Qt.HitTestAccuracy.ExactHit) if hitpos >= 0: return self.obj.get_hit_obj(hitpos) return None def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.infodock.select_instruction(self.addr) obj = self.get_obj_for_mouse_event(event) if obj is not None: obj.mousePressEvent(event) def mouseDoubleClickEvent(self, event): obj = self.get_obj_for_mouse_event(event) if obj is not None: obj.mouseDoubleClickEvent(event) # # Private methods # def _layout_items_and_update_size(self): self.update_document() x, y = 0, 0 if self._disasm_view.show_address: self._addr_item.setPos(x, y) x += self._addr_item.boundingRect().width( ) + self.GRAPH_ADDR_SPACING x += self._qtextdoc.size().width() y += self._qtextdoc.size().height() self._width = x self._height = y self.recalculate_size() def _boundingRect(self): return QRectF(0, 0, self._width, self._height)
def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex): """ Displays dirty files in red with corresponding rebuild buttons if in developer mode (is_dev_mode). Otherwise, renders normally Args: painter (QPainter): Current painter option (QStyleOptionViewItem): Current option index (QModelIndex): Current index of related model """ if self.is_dev_mode: source_model = self.get_source_model(index.model(), self.source_model_type) model = index.model() # get data of filename filename = str( model.data( model.sibling(index.row(), source_model.FILENAME, index))) if source_model.is_file_dirty(filename): if index.column() == source_model.FILENAME: text = filename palette = option.palette document = QTextDocument() document.setDefaultFont(option.font) document.setHtml(f"<font color={'red'}>{text}</font>") background_color = palette.base().color() painter.save() painter.fillRect(option.rect, background_color) painter.translate(option.rect.x(), option.rect.y()) document.drawContents(painter) painter.restore() elif index.column() == source_model.REBUILD: if '.py' in filename: text = "rebuild" palette = option.palette document = QTextDocument() # needed to add Right Alignment: qt bug : # https://bugreports.qt.io/browse/QTBUG-22851 document.setTextWidth(option.rect.width()) text_options = document.defaultTextOption() text_options.setTextDirection(Qt.RightToLeft) document.setDefaultTextOption( text_options) # get right alignment document.setDefaultFont(option.font) document.setHtml( f'<font color={"red"}> <b> {text}</b> </font>') background_color = palette.base().color() painter.save() painter.fillRect(option.rect, background_color) painter.translate(option.rect.x(), option.rect.y()) document.drawContents(painter) painter.restore() else: QItemDelegate.paint(self, painter, option, index) else: QItemDelegate.paint(self, painter, option, index)