Example #1
1
    def paint(self, painter, option, index):
        option = QStyleOptionViewItem(option) # copy option
        self.initStyleOption(option, index)

        style = option.widget.style() if option.widget else QApplication.style()

        doc = QTextDocument()
        doc.setHtml(option.text)

        # painting item without text
        option.text = ""
        style.drawControl(QStyle.CE_ItemViewItem, option, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()

        # Hilight text if item is selected
        if option.state & QStyle.State_Selected:
            ctx.palette.setColor(QPalette.Text, option.palette.color(QPalette.Active, QPalette.HighlightedText))

        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, option)
        painter.save()
        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))
        doc.documentLayout().draw(painter, ctx)
        painter.restore()
Example #2
0
class HTMLDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super(HTMLDelegate, self).__init__(parent)
        self.doc = QTextDocument(self)

    def paint(self, painter, option, index):
        painter.save()

        options = QStyleOptionViewItem(option)
        self.initStyleOption(options, index)

        self.doc.setHtml(options.text)
        options.text = ""

        style = QApplication.style() if options.widget is None \
            else options.widget.style()
        style.drawControl(QStyle.CE_ItemViewItem, options, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()

        if option.state & QStyle.State_Selected:
            ctx.palette.setColor(
                QPalette.Text,
                option.palette.color(QPalette.Active,
                                     QPalette.HighlightedText))

        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options)
        painter.translate(textRect.topLeft())
        self.doc.documentLayout().draw(painter, ctx)

        painter.restore()
Example #3
0
    def paint(self, painter, option, index):
        self.initStyleOption(option, index)

        style = QApplication.style()

        doc = QTextDocument()
        if index.column() in (NetworkTableModel.columns_types.index('address'),
                              NetworkTableModel.columns_types.index('port'),
                              NetworkTableModel.columns_types.index('api')):
            doc.setHtml(option.text)
        else:
            doc.setPlainText(option.text)

        option.text = ""
        style.drawControl(QStyle.CE_ItemViewItem, option, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()

        text_rect = style.subElementRect(QStyle.SE_ItemViewItemText, option)
        painter.save()
        painter.translate(text_rect.topLeft())
        painter.setClipRect(text_rect.translated(-text_rect.topLeft()))
        doc.documentLayout().draw(painter, ctx)

        painter.restore()
Example #4
0
    def paint(self, painter, option, index):
        self.initStyleOption(option, index)

        foreground = index.data(Qt.ForegroundRole)
        font = index.data(Qt.FontRole)
        style = QApplication.style()

        doc = QTextDocument()
        if index.column() == HistoryTableModel.columns_types.index('pubkey'):
            doc.setHtml(option.text)
        else:
            doc.setPlainText(option.text)

        option.text = ""
        style.drawControl(QStyle.CE_ItemViewItem, option, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()
        if foreground:
            if foreground.isValid():
                ctx.palette.setColor(QPalette.Text, foreground)
        if font:
            doc.setDefaultFont(font)
        text_rect = style.subElementRect(QStyle.SE_ItemViewItemText, option)
        painter.save()
        painter.translate(text_rect.topLeft())
        painter.setClipRect(text_rect.translated(-text_rect.topLeft()))
        doc.documentLayout().draw(painter, ctx)

        painter.restore()
    def paint(self, painter, option, index):
        options = QStyleOptionViewItem(option)
        item = index.data(Qt.UserRole)
        if isinstance(item, (CommentItem, ChangeItem)):
            options.decorationAlignment = Qt.AlignHCenter
        self.initStyleOption(options,index)

        if options.widget is None:
            style = QApplication.style()
        else:
            style = options.widget.style()
        
        doc = QTextDocument()
        doc.setHtml(options.text)
        
        options.text = ""
        style.drawControl(QStyle.CE_ItemViewItem, options, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()

        # Highlighting text if item is selected
        #if (optionV4.state & QStyle::State_Selected)
            #ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText))

        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options)
        painter.save()
        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))
        doc.documentLayout().draw(painter, ctx)

        painter.restore()
Example #6
0
 def paint(self, painter, option, index):
     text = index.data()
     if isinstance(text, str):
         painter.save()
         doc = QTextDocument()
         doc.setHtml(text)
         doc.setPageSize(QSizeF(option.rect.size()))
         painter.setClipRect(option.rect)
         painter.translate(option.rect.x(), option.rect.y())
         doc.documentLayout().draw(
             painter, QAbstractTextDocumentLayout.PaintContext())
         painter.restore()
     else:
         QStyledItemDelegate.paint(self, painter, option, index)
Example #7
0
    def sizeHint(self, styleOption, modelIndex):
        """Return the size of Data Edit Cells with rich text.

        Other cells return the base class size.
        Arguments:
            styleOption -- the data for styles and geometry
            modelIndex -- the index of the cell to be painted
        """
        cell = self.parent().item(modelIndex.row(), modelIndex.column())
        if isinstance(cell, DataEditCell):
            doc = cell.doc
            doc.setTextWidth(styleOption.rect.width())
            size = doc.documentLayout().documentSize().toSize()
            maxHeight = self.parent().height() * 9 // 10  # 90% of view height
            if (size.height() > maxHeight
                    and globalref.genOptions['EditorLimitHeight']):
                size.setHeight(maxHeight)
            if cell.field.numLines > 1:
                minDoc = QTextDocument('\n' * (cell.field.numLines - 1))
                minDoc.setDefaultFont(cell.doc.defaultFont())
                minHeight = (
                    minDoc.documentLayout().documentSize().toSize().height())
                if minHeight > size.height():
                    size.setHeight(minHeight)
            return size + QSize(0, 4)
        return super().sizeHint(styleOption, modelIndex)
Example #8
0
    def paint(self, painter: QPainter, option, index):
        # reference following link
        # https://stackoverflow.com/questions/53353450/how-to-highlight-a-words-in-qtablewidget-from-a-searchlist
        # https://stackoverflow.com/questions/34623036/implementing-a-delegate-for-wordwrap-in-a-qtreeview-qt-pyside-pyqt
        painter.save()
        doc = QTextDocument(self)
        # option.palette.setColor(QPalette.HighlightedText, QColor.fromRgb(30, 136, 200))
        # remove dotted border in table
        if option.state & QStyle.State_HasFocus:
            option.state = option.state ^ QStyle.State_HasFocus
        options = QStyleOptionViewItem(option)
        self.initStyleOption(options, index)
        doc.setPlainText(options.text)
        # keyword = index.data(Qt.UserRole)
        # if self.keywords:
        self.keywordHighlight(doc)
        options.text = ""
        # print(dir(options.palette))

        # print(options.palette.Highlight)
        style = QApplication.style() if options.widget is None \
            else options.widget.style()
        style.drawControl(QStyle.CE_ItemViewItem, options, painter,
                          options.widget)  # for selection highlight

        ctx = QAbstractTextDocumentLayout.PaintContext()

        if index.data(Qt.UserRole) == 'reserved':
            ctx.palette.setColor(QPalette.Text, QColor.fromRgb(100, 100, 100))
            doc.setDefaultFont(
                QFont(option.font.family(),
                      option.font.pointSize() * 2 // 3))

        else:
            ctx.palette.setColor(QPalette.Text, QColor.fromRgb(217, 217, 217))
            doc.setDefaultFont(option.font)

        textRect = option.rect
        # margin = 4
        # textRect.setTop(textRect.top() + margin)
        textRect.setTop(textRect.top())
        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))

        doc.setTextWidth(option.rect.width())
        doc.documentLayout().draw(painter, ctx)
        painter.restore()
Example #9
0
class TableDelegate(QStyledItemDelegate):
    """Table 富文本"""
    def __init__(self, parent=None):
        super(TableDelegate, self).__init__(parent)
        self.doc = QTextDocument(self)

    def paint(self, painter, option, index):
        painter.save()
        options = QStyleOptionViewItem(option)
        self.initStyleOption(options, index)
        self.doc.setHtml(options.text)
        options.text = ""  # 原字符
        style = QApplication.style(
        ) if options.widget is None else options.widget.style()
        style.drawControl(QStyle.CE_ItemViewItem, options, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()

        if option.state & QStyle.State_Selected:
            ctx.palette.setColor(
                QPalette.Text,
                option.palette.color(QPalette.Active,
                                     QPalette.HighlightedText))
        else:
            ctx.palette.setColor(
                QPalette.Text,
                option.palette.color(QPalette.Active, QPalette.Text))

        text_rect = style.subElementRect(QStyle.SE_ItemViewItemText, options)

        the_fuck_your_shit_up_constant = 3  #  ̄へ ̄ #
        margin = (option.rect.height() - options.fontMetrics.height()) // 2
        margin = margin - the_fuck_your_shit_up_constant
        text_rect.setTop(text_rect.top() + margin)

        painter.translate(text_rect.topLeft())
        painter.setClipRect(text_rect.translated(-text_rect.topLeft()))
        self.doc.documentLayout().draw(painter, ctx)

        painter.restore()

    def sizeHint(self, option, index):
        options = QStyleOptionViewItem(option)
        self.initStyleOption(options, index)
        self.doc.setHtml(options.text)
        self.doc.setTextWidth(options.rect.width())
        return QSize(self.doc.idealWidth(), self.doc.size().height())
Example #10
0
    def paint(self, painter, option, index):
        self.initStyleOption(option, index)

        style = option.widget.style() if option.widget else QApplication.style()

        palette = QApplication.palette()
        color = palette.highlight().color() \
            if option.state & QStyle.State_Selected \
            else palette.base()
        ctx = QAbstractTextDocumentLayout.PaintContext()
        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, option)

        painter.save()
        painter.fillRect(option.rect, color)
        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))

        doc = QTextDocument()
        doc.setHtml(option.text)
        doc.documentLayout().draw(painter, ctx)
        painter.restore()
Example #11
0
    def paint(self, painter, option, index):
        """QStyledItemDelegate.paint implementation
        """
        option.state &= ~QStyle.State_HasFocus  # never draw focus rect

        options = QStyleOptionViewItem(option)
        self.initStyleOption(options, index)

        style = QApplication.style(
        ) if options.widget is None else options.widget.style()

        doc = QTextDocument()
        doc.setDocumentMargin(1)
        doc.setHtml(options.text)
        if options.widget is not None:
            doc.setDefaultFont(options.widget.font())
        #  bad long (multiline) strings processing doc.setTextWidth(options.rect.width())

        options.text = ""
        style.drawControl(QStyle.CE_ItemViewItem, options, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()

        # Highlighting text if item is selected
        if option.state & QStyle.State_Selected:
            ctx.palette.setColor(
                QPalette.Text,
                option.palette.color(QPalette.Active,
                                     QPalette.HighlightedText))

        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options)
        painter.save()
        painter.translate(textRect.topLeft())
        """Original example contained line
            painter.setClipRect(textRect.translated(-textRect.topLeft()))
        but text is drawn clipped with it on kubuntu 12.04
        """
        doc.documentLayout().draw(painter, ctx)

        painter.restore()
Example #12
0
    def paint(self, painter, option, index):
        """QStyledItemDelegate.paint implementation
        """
        option.state &= ~QStyle.State_HasFocus  # never draw focus rect

        options = QStyleOptionViewItem(option)
        self.initStyleOption(options,index)

        style = QApplication.style() if options.widget is None else options.widget.style()

        doc = QTextDocument()
        doc.setDocumentMargin(1)
        doc.setHtml(options.text)
        if options.widget is not None:
            doc.setDefaultFont(options.widget.font())
        #  bad long (multiline) strings processing doc.setTextWidth(options.rect.width())

        options.text = ""
        style.drawControl(QStyle.CE_ItemViewItem, options, painter);

        ctx = QAbstractTextDocumentLayout.PaintContext()

        # Highlighting text if item is selected
        if option.state & QStyle.State_Selected:
            ctx.palette.setColor(QPalette.Text, option.palette.color(QPalette.Active, QPalette.HighlightedText))

        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options)
        painter.save()
        painter.translate(textRect.topLeft())
        """Original example contained line
            painter.setClipRect(textRect.translated(-textRect.topLeft()))
        but text is drawn clipped with it on kubuntu 12.04
        """
        doc.documentLayout().draw(painter, ctx)

        painter.restore()
Example #13
0
    def paint(self, painter, option, index):
        """QStyledItemDelegate.paint implementation
        """
        option.state &= ~QStyle.State_HasFocus  # never draw focus rect

        option.state |= QStyle.State_Active  # draw fuzzy-open completion as focused, even if focus is on the line edit

        options = QStyleOptionViewItem(option)
        self.initStyleOption(options, index)

        style = QApplication.style() if options.widget is None else options.widget.style()

        doc = QTextDocument()
        if self._font is not None:
            doc.setDefaultFont(self._font)

        doc.setDocumentMargin(1)
        doc.setHtml(options.text)
        #  bad long (multiline) strings processing doc.setTextWidth(options.rect.width())

        options.text = ""
        style.drawControl(QStyle.CE_ItemViewItem, options, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()

        # Highlighting text if item is selected
        if option.state & QStyle.State_Selected:
            ctx.palette.setColor(QPalette.Text, option.palette.color(QPalette.Active, QPalette.Text))

        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options)
        painter.save()
        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))
        doc.documentLayout().draw(painter, ctx)

        painter.restore()
class HyperlinkItemDelegate(QStyledItemDelegate):
    linkActivated = QtCore.pyqtSignal(str)

    def __init__(self, parentView: QTableView, link_color: str = ''):
        QStyledItemDelegate.__init__(self, parentView)

        parentView.setMouseTracking(True)
        self.doc_hovered_item = QTextDocument(self)
        self.doc_hovered_item.setDocumentMargin(0)
        self.doc_not_hovered = QTextDocument(self)
        self.doc_not_hovered.setDocumentMargin(0)
        self.last_hovered_pos = QPoint(0, 0)
        self.ctx_mnu = QMenu()
        self.last_link = None
        self.last_text = None
        if not link_color:
            self.link_color = parentView.palette().color(
                QPalette.Normal,
                parentView.palette().Link).name()
        else:
            self.link_color = link_color
        self.action_copy_link = self.ctx_mnu.addAction("Copy Link Location")
        self.action_copy_link.triggered.connect(
            self.on_action_copy_link_triggered)
        self.action_copy_text = self.ctx_mnu.addAction("Copy text")
        self.action_copy_text.triggered.connect(
            self.on_action_copy_text_triggered)

    def paint(self, painter, option: QStyleOptionViewItem, index: QModelIndex):

        self.initStyleOption(option, index)
        has_focus = self.parent().hasFocus()
        mouse_over = option.state & QStyle.State_MouseOver
        painter.save()

        if option.state & QStyle.State_Selected:
            if has_focus:
                painter.fillRect(
                    option.rect,
                    QBrush(
                        option.palette.color(QPalette.Active,
                                             option.palette.Highlight)))
                color = option.palette.color(
                    QPalette.Normal, option.palette.HighlightedText).name()
            else:
                painter.fillRect(
                    option.rect,
                    QBrush(
                        option.palette.color(QPalette.Inactive,
                                             option.palette.Highlight)))
                color = option.palette.color(
                    QPalette.Inactive, option.palette.HighlightedText).name()
        else:
            painter.setBrush(
                QBrush(
                    option.palette.color(QPalette.Normal,
                                         option.palette.Base)))
            color = self.link_color

        if mouse_over:
            doc = self.doc_hovered_item
            self.last_hovered_pos = option.rect.topLeft()
            doc.setDefaultStyleSheet(f"a {{color: {color}}}")
        else:
            doc = self.doc_not_hovered
            self.parent().unsetCursor()
            doc.setDefaultStyleSheet(
                f"a {{text-decoration: none;color: {color};}}")

        doc.setDefaultFont(option.font)
        doc.setHtml(option.text)

        painter.translate(option.rect.topLeft() +
                          QPoint(HTML_LINK_HORZ_MARGIN, 0))
        ctx = QAbstractTextDocumentLayout.PaintContext()
        ctx.palette = option.palette
        clip = QRect(0, 0,
                     option.rect.width() - HTML_LINK_HORZ_MARGIN * 2,
                     option.rect.height())
        painter.setClipRect(clip)
        doc.documentLayout().draw(painter, ctx)
        painter.restore()

    def editorEvent(self, event, model, option, index):
        if event.type() not in [QEvent.MouseMove, QEvent.MouseButtonRelease] \
            or not (option.state & QStyle.State_Enabled):
            return False

        pos = QPointF(event.pos() - option.rect.topLeft())
        anchor = self.doc_hovered_item.documentLayout().anchorAt(pos)
        if not anchor:
            self.parent().unsetCursor()
        else:
            self.parent().setCursor(Qt.PointingHandCursor)
            if event.type() == QEvent.MouseButtonRelease:
                if event.button() == Qt.LeftButton:
                    self.linkActivated.emit(anchor)
                    return True
                elif event.button() == Qt.RightButton:
                    self.last_text = self.doc_hovered_item.toRawText()
                    self.last_link = anchor

                    p = QPoint(
                        event.pos().x(),
                        event.pos().y() + min(32, self.ctx_mnu.height()))
                    p = option.widget.mapToGlobal(p)
                    self.ctx_mnu.exec(p)
        return False

    def on_action_copy_link_triggered(self):
        clipboard = QApplication.clipboard()
        clipboard.setText(self.last_link)

    def on_action_copy_text_triggered(self):
        clipboard = QApplication.clipboard()
        clipboard.setText(self.last_text)
Example #15
0
class SyntaxHighlightDelegate(QStyledItemDelegate):
    def __init__(self, parent=None, arch: str = "x86", dark_theme: bool = False):
        super(SyntaxHighlightDelegate, self).__init__(parent)
        self.doc = QTextDocument(self)
        self.highlighted_columns = [3]

        self.syntax_colors = []
        self.custom_hl = []
        self.register_hl = {}

        if dark_theme:
            self.load_syntax_file("gui/syntax_hl/syntax_x86_dark.txt")
            self.reg_hl_color = QColor("#000000")
            self.reg_hl_bg_color = QColor("#ffffff")
        else:
            self.load_syntax_file("gui/syntax_hl/syntax_x86_light.txt")
            self.reg_hl_color = QColor("#ffffff")
            self.reg_hl_bg_color = QColor("#333333")

    def set_reg_highlight(self, reg: str, enabled: bool):

        regs_hl = prefs.HL_REGS_X86
        words = regs_hl.get(reg, [reg])

        if enabled:
            self.register_hl[reg] = words
        elif reg in self.register_hl:
            del self.register_hl[reg]

    def load_syntax_file(self, filename: str):
        with open(filename) as f:
            self.syntax_colors = json.load(f)

    def paint(self, painter, option, index):
        painter.save()

        options = QStyleOptionViewItem(option)
        self.initStyleOption(options, index)

        self.doc.setPlainText(options.text)

        if index.column() in self.highlighted_columns:
            options.font.setWeight(QFont.Bold)
            self.highlight()

        self.doc.setDefaultFont(options.font)

        options.text = ""

        style = (
            QApplication.style() if options.widget is None else options.widget.style()
        )
        style.drawControl(QStyle.CE_ItemViewItem, options, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()
        if option.state & QStyle.State_Selected:
            ctx.palette.setColor(
                QPalette.Text,
                option.palette.color(QPalette.Active, QPalette.HighlightedText),
            )
        else:
            ctx.palette.setColor(
                QPalette.Text,
                option.palette.color(QPalette.Active, QPalette.Text),
            )

        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options)

        if index.column() != 0:
            textRect.adjust(5, 0, 0, 0)

        the_constant = 4
        margin = (option.rect.height() - options.fontMetrics.height()) // 2
        margin = margin - the_constant
        textRect.setTop(textRect.top() + margin)

        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))
        self.doc.documentLayout().draw(painter, ctx)

        painter.restore()

    def highlight(self):
        char_format = QTextCharFormat()
        cursor = QTextCursor(self.doc)

        while not cursor.isNull() and not cursor.atEnd():
            cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor)

            color = self.get_register_hl_color(cursor.selectedText())
            if color is not None:
                char_format.setBackground(self.reg_hl_bg_color)
            else:
                color = self.get_color(cursor.selectedText())

            if color is not None:
                char_format.setForeground(color)
                cursor.mergeCharFormat(char_format)

            char_format.clearBackground()
            self.move_to_next_word(self.doc, cursor)

    def move_to_next_word(self, doc, cursor):
        while not cursor.isNull() and not cursor.atEnd():
            if doc.characterAt(cursor.position()) not in (" ", ",", "+", "[", "]"):
                return
            cursor.movePosition(QTextCursor.NextCharacter)

    def get_register_hl_color(self, word_to_check: str):
        for words in self.register_hl.values():
            if word_to_check in words:
                return QColor(self.reg_hl_color)
        return None

    def get_color(self, word_to_check: str):

        for syntax in self.syntax_colors:
            if "words" in syntax:
                for word in syntax["words"]:
                    if word == word_to_check:
                        return QColor(syntax["color"])
            if "startswith" in syntax:
                for sw in syntax["startswith"]:
                    if word_to_check.startswith(sw):
                        return QColor(syntax["color"])
            if "has" in syntax:
                for has in syntax["has"]:
                    if has in word_to_check:
                        return QColor(syntax["color"])

        return None
Example #16
0
class SyntaxHighlightDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super(SyntaxHighlightDelegate, self).__init__(parent)

        self.doc = QTextDocument(self)

        self.disasm_columns = []
        self.value_columns = []

        self.highlighted_regs = {}
        self.reg_hl_color = prefs.REG_HL_COLOR
        self.reg_hl_bg_colors = prefs.REG_HL_BG_COLORS

        self.ignored_chars = (" ", ",", "+", "[", "]")

        self.disasm_rules = self.load_rules_file(prefs.DISASM_RULES_FILE)
        self.value_rules = self.load_rules_file(prefs.VALUE_RULES_FILE)

    def load_rules_file(self, filename: str) -> list:
        """Loads syntax highlighting rules from json file"""
        with open(filename) as f:
            return json.load(f)

    def reset(self):
        """Resets highlighter"""
        self.highlighted_regs = {}

    def paint(self, painter, option, index):
        painter.save()

        options = QStyleOptionViewItem(option)
        self.initStyleOption(options, index)

        self.doc.setPlainText(options.text)

        column = index.column()
        if column in self.disasm_columns:
            options.font.setWeight(QFont.Bold)
            self.highlight(self.doc, self.disasm_rules)
        elif column in self.value_columns:
            options.font.setWeight(QFont.Bold)
            self.highlight(self.doc, self.value_rules)

        self.doc.setDefaultFont(options.font)

        options.text = ""

        style = (QApplication.style()
                 if options.widget is None else options.widget.style())
        style.drawControl(QStyle.CE_ItemViewItem, options, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()
        if option.state & QStyle.State_Selected:
            ctx.palette.setColor(
                QPalette.Text,
                option.palette.color(QPalette.Active,
                                     QPalette.HighlightedText),
            )
        else:
            ctx.palette.setColor(
                QPalette.Text,
                option.palette.color(QPalette.Active, QPalette.Text),
            )

        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options)

        if index.column() != 0:
            textRect.adjust(5, 0, 0, 0)

        the_constant = 4
        margin = (option.rect.height() - options.fontMetrics.height()) // 2
        margin = margin - the_constant
        textRect.setTop(textRect.top() + margin)

        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))
        self.doc.documentLayout().draw(painter, ctx)

        painter.restore()

    def set_reg_highlight(self, reg: str, enabled: bool):
        """Enables or disables register highlight"""
        regs_hl = prefs.HL_REGS_X86
        words = regs_hl.get(reg, [reg])

        if enabled:
            self.highlighted_regs[reg] = words
        elif reg in self.highlighted_regs:
            del self.highlighted_regs[reg]

    def highlight(self, document: QTextDocument, rules: list):
        """Highlights document"""
        char_format = QTextCharFormat()
        cursor = QTextCursor(document)

        while not cursor.isNull() and not cursor.atEnd():
            cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor)

            text = cursor.selectedText()
            color, bgcolor = self.get_register_hl_color(
                text, self.highlighted_regs)

            if not color:
                color, bgcolor = self.get_color(text, rules)

            if color:
                char_format.setForeground(QColor(color))

            if bgcolor:
                char_format.setBackground(QColor(bgcolor))

            if color or bgcolor:
                cursor.mergeCharFormat(char_format)
                char_format.clearBackground()

            self.move_to_next_word(document, cursor)

    def move_to_next_word(self, doc: QTextDocument, cursor: QTextCursor):
        """Moves cursor to next word"""
        while not cursor.isNull() and not cursor.atEnd():
            if doc.characterAt(cursor.position()) not in self.ignored_chars:
                return
            cursor.movePosition(QTextCursor.NextCharacter)

    def get_register_hl_color(self, word_to_check: str,
                              regs_hl: dict) -> tuple:
        """Gets color and bgcolor if given word is found in regs_hl"""
        color_index = 0

        for words in regs_hl.values():
            if word_to_check in words:
                if color_index < len(self.reg_hl_bg_colors):
                    bg_color = self.reg_hl_bg_colors[color_index]
                else:
                    bg_color = self.reg_hl_bg_colors[-1]
                return (self.reg_hl_color, bg_color)
            color_index += 1

        return ("", "")

    def get_color(self, word_to_check: str, rules: dict) -> tuple:
        """Gets color and bgcolor if given word is found in rules"""
        for rule in rules:
            if "words" in rule:
                for word in rule["words"]:
                    if word == word_to_check:
                        return (rule["color"], rule.get("bgcolor", ""))
            if "startswith" in rule:
                for sw in rule["startswith"]:
                    if word_to_check.startswith(sw):
                        return (rule["color"], rule.get("bgcolor", ""))
            if "has" in rule:
                for has in rule["has"]:
                    if has in word_to_check:
                        return (rule["color"], rule.get("bgcolor", ""))

        return ("", "")
class SyntaxHighlightDelegate(QStyledItemDelegate):
    def __init__(self, parent=None, arch="x86", use_darker_text_color=False):
        super(SyntaxHighlightDelegate, self).__init__(parent)
        self.doc = QTextDocument(self)
        self.syntax_colors = SYNTAX_COLORS_X86
        self.highlighted_columns = [3]
        self.use_darker_text_color = use_darker_text_color

    def paint(self, painter, option, index):
        painter.save()
        options = QStyleOptionViewItem(option)
        self.initStyleOption(options, index)
        self.doc.setPlainText(options.text)

        if index.column() in self.highlighted_columns:
            self.highlight()

        options.text = ""
        style = (QApplication.style()
                 if options.widget is None else options.widget.style())
        style.drawControl(QStyle.CE_ItemViewItem, options, painter)

        ctx = QAbstractTextDocumentLayout.PaintContext()
        if option.state & QStyle.State_Selected:
            ctx.palette.setColor(
                QPalette.Text,
                option.palette.color(QPalette.Active,
                                     QPalette.HighlightedText),
            )
        else:
            ctx.palette.setColor(
                QPalette.Text,
                option.palette.color(QPalette.Active, QPalette.Text),
            )

        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options)

        if index.column() != 0:
            textRect.adjust(5, 0, 0, 0)

        the_constant = 4
        margin = (option.rect.height() - options.fontMetrics.height()) // 2
        margin = margin - the_constant
        textRect.setTop(textRect.top() + margin)

        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))
        self.doc.documentLayout().draw(painter, ctx)

        painter.restore()

    def highlight(self):
        char_format = QTextCharFormat()
        cursor = QTextCursor(self.doc)
        while not cursor.isNull() and not cursor.atEnd():
            cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor)
            color = self.get_color(cursor.selectedText())
            if color is not None:
                if self.use_darker_text_color:
                    color = color.darker()
                char_format.setForeground(color)
                cursor.mergeCharFormat(char_format)
            self.move_to_next_word(self.doc, cursor)

    def move_to_next_word(self, doc, cursor):
        while not cursor.isNull() and not cursor.atEnd():
            if doc.characterAt(cursor.position()) not in (" ", ",", "+", "[",
                                                          "]"):
                return
            cursor.movePosition(QTextCursor.NextCharacter)

    def get_color(self, word_to_check: str):
        for syntax in self.syntax_colors:
            if "words" in syntax:
                for word in syntax["words"]:
                    if word == word_to_check:
                        return syntax["color"]
            if "startswith" in syntax:
                for sw in syntax["startswith"]:
                    if word_to_check.startswith(sw):
                        return syntax["color"]
            if "has" in syntax:
                for has in syntax["has"]:
                    if has in word_to_check:
                        return syntax["color"]
        return None
Example #18
0
class OutputItem:
    """Class to store output for a single node.

    Stores text lines and original indent level.
    """
    def __init__(self, spot, level):
        """Convert the spot's node into an output item.

        Create a blank item if spot is None.

        Arguments:
            spot -- the tree spot to convert
            level -- the node's original indent level
        """
        if spot:
            node = spot.nodeRef
            nodeFormat = node.formatRef
            if not nodeFormat.useTables:
                self.textLines = [
                    line + '<br />' for line in node.output(spotRef=spot)
                ]
            else:
                self.textLines = node.output(keepBlanks=True, spotRef=spot)
            if not self.textLines:
                self.textLines = ['']
            self.addSpace = nodeFormat.spaceBetween
            self.siblingPrefix = nodeFormat.siblingPrefix
            self.siblingSuffix = nodeFormat.siblingSuffix
            if nodeFormat.useBullets and self.textLines:
                # remove <br /> extra space for bullets
                self.textLines[-1] = self.textLines[-1][:-6]
            self.uId = node.uId
        else:
            self.textLines = ['']
            self.addSpace = False
            self.siblingPrefix = ''
            self.siblingSuffix = ''
            self.uId = None
        self.level = level
        # following variables used by printdata only:
        self.height = 0
        self.pageNum = 0
        self.columnNum = 0
        self.pagePos = 0
        self.doc = None
        self.parentItem = None
        self.lastChildItem = None

    def duplicate(self):
        """Return an independent copy of this OutputItem.
        """
        item = OutputItem(None, 0)
        item.textLines = self.textLines[:]
        item.addSpace = self.addSpace
        item.siblingPrefix = self.siblingPrefix
        item.siblingSuffix = self.siblingSuffix
        item.uId = self.uId
        item.level = self.level
        item.height = self.height
        item.pageNum = self.pageNum
        item.columnNum = self.columnNum
        item.pagePos = self.pagePos
        item.doc = None
        item.parentItem = self.parentItem
        item.lastChildItem = self.lastChildItem
        return item

    def addIndent(self, prevLevel, nextLevel):
        """Add <div> tags to define indent levels in the output.

        Arguments:
            prevLevel -- the level of the previous item in the list
            nextLevel -- the level of the next item in the list
        """
        for num in range(self.level - prevLevel):
            self.textLines[0] = '<div>' + self.textLines[0]
        for num in range(self.level - nextLevel):
            self.textLines[-1] += '</div>'

    def addAbsoluteIndent(self, pixels):
        """Add tags for an individual indentation.

        Removes the <br /> tag from the last line to avoid excess space,
        since <div> starts a new line.
        The Qt output view does not fully support nested <div> tags.
        Arguments:
            pixels -- the amount to indent
        """
        self.textLines[0] = ('<div style="margin-left: {0}">{1}'.format(
            pixels * self.level, self.textLines[0]))
        if not self.siblingPrefix and self.textLines[-1].endswith('<br />'):
            self.textLines[-1] = self.textLines[-1][:-6]
        self.textLines[-1] += '</div>'

    def addSiblingPrefix(self):
        """Add the sibling prefix before this output.
        """
        if self.siblingPrefix:
            self.textLines[0] = self.siblingPrefix + self.textLines[0]

    def addSiblingSuffix(self):
        """Add the sibling suffix after this output.
        """
        if self.siblingSuffix:
            self.textLines[-1] += self.siblingSuffix

    def addAnchor(self):
        """Add a link anchor to this item.
        """
        self.textLines[0] = '<a id="{0}" />{1}'.format(self.uId,
                                                       self.textLines[0])

    def intLinkIds(self):
        """Return a set of uIDs from any internal links in this item.
        """
        linkIds = set()
        for line in self.textLines:
            startPos = 0
            while True:
                match = _linkRe.search(line, startPos)
                if not match:
                    break
                uId = match.group(1)
                if uId:
                    linkIds.add(uId)
                startPos = match.start(1)
        return linkIds

    def numLines(self):
        """Return the number of text lines in the item.
        """
        return len(self.textLines)

    def equalPrefix(self, otherItem):
        """Return True if sibling prefixes and suffixes are equal.

        Arguments:
            otherItem -- the item to compare
        """
        return (self.siblingPrefix == otherItem.siblingPrefix
                and self.siblingSuffix == otherItem.siblingSuffix)

    def setDocHeight(self, paintDevice, width, printFont, replaceDoc=False):
        """Set the height of this item for use in printer output.

        Creates an output document if not already created.
        Arguments:
            paintDevice -- the printer or other device for settings
            width -- the width available for the output text
            printFont -- the default font for the document
            replaceDoc -- if true, re-create the text document
        """
        if not self.doc or replaceDoc:
            self.doc = QTextDocument()
            lines = '\n'.join(self.textLines)
            if lines.endswith('<br />'):
                # remove trailing <br /> tag to avoid excess space
                lines = lines[:-6]
            self.doc.setHtml(lines)
            self.doc.setDefaultFont(printFont)
            frameFormat = self.doc.rootFrame().frameFormat()
            frameFormat.setBorder(0)
            frameFormat.setMargin(0)
            frameFormat.setPadding(0)
            self.doc.rootFrame().setFrameFormat(frameFormat)
        layout = self.doc.documentLayout()
        layout.setPaintDevice(paintDevice)
        self.doc.setTextWidth(width)
        self.height = layout.documentSize().height()

    def splitDocHeight(self, initHeight, maxHeight, paintDevice, width,
                       printFont):
        """Split this item into two items and return them.

        The first item will fit into initHeight if practical.
        Splits at line endings if posible.
        Arguments:
            initHeight -- the preferred height of the first page
            maxheight -- the max height of any pages
            paintDevice -- the printer or other device for settings
            width -- the width available for the output text
            printFont -- the default font for the document
        """
        newItem = self.duplicate()
        fullHeight = self.height
        lines = '\n'.join(self.textLines)
        allLines = [line + '<br />' for line in lines.split('<br />')]
        self.textLines = []
        prevHeight = 0
        for line in allLines:
            self.textLines.append(line)
            self.setDocHeight(paintDevice, width, printFont, True)
            if ((prevHeight and self.height > initHeight
                 and fullHeight - prevHeight > maxHeight)
                    or (prevHeight and self.height > maxHeight)):
                self.textLines = self.textLines[:-1]
                self.setDocHeight(paintDevice, width, printFont, True)
                newItem.textLines = allLines[len(self.textLines):]
                newItem.setDocHeight(paintDevice, width, printFont, True)
                return (self, newItem)
            if self.height > maxHeight:
                break
            prevHeight = self.height
        # no line ending breaks found
        text = ' \n'.join(allLines)
        allWords = [word + ' ' for word in text.split(' ')]
        newWords = []
        prevHeight = 0
        for word in allWords:
            if word.strip() == '<img':
                break
            newWords.append(word)
            self.textLines = [''.join(newWords)]
            self.setDocHeight(paintDevice, width, printFont, True)
            if ((prevHeight and self.height > initHeight
                 and fullHeight - prevHeight < maxHeight)
                    or (prevHeight and self.height > maxHeight)):
                self.textLines = [''.join(newWords[:-1])]
                self.setDocHeight(paintDevice, width, printFont, True)
                newItem.textLines = [''.join(allWords[len(newWords):])]
                newItem.setDocHeight(paintDevice, width, printFont, True)
                return (self, newItem)
            if self.height > maxHeight:
                break
            prevHeight = self.height
        newItem.setDocHeight(paintDevice, width, printFont, True)
        return (newItem, None)  # fail to split