Новая функция для предыдущего вопроса о Стили текста в QTableView с PySide2 - PullRequest
0 голосов
/ 25 января 2019

Это относится к предыдущему вопросу .Если теперь текст между круглыми скобками (включая круглые скобки) был заменен на другой текст, сложно ли сохранить цвет для замены (даже если у него нет ограничителя или чего-то еще)?У меня есть функция переключения, которая меняет это, и было бы здорово сохранить цвет при замене.

Здесь пример кода, модифицированный для соответствия новому условию (теперь двойным щелчком вы можете изменить (переключить) элементтекст:

import random
from PySide2 import QtCore, QtGui, QtWidgets

words = '''Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
Mauris euismod cursus mi sit amet pellentesque. 
Proin sed lectus sed augue scelerisque congue eget quis leo. 
Curabitur ultrices nisi nisi, placerat gravida urna sagittis et. 
Nullam vitae urna tortor. Curabitur a lobortis metus, et laoreet arcu. 
Quisque a mi in purus molestie porta non sit amet purus. 
Sed porta non purus et suscipit.'''.split()

class HighlightDelegate(QtWidgets.QStyledItemDelegate):
    def __init__(self, parent=None):
        super(HighlightDelegate, self).__init__(parent)
        self.doc = QtGui.QTextDocument(self)
        self._regex = QtCore.QRegularExpression()
        self._highlight_format = QtGui.QTextCharFormat()

    def paint(self, painter, option, index):
        painter.save()
        options = QtWidgets.QStyleOptionViewItem(option)
        self.initStyleOption(options, index)
        self.doc.setPlainText(options.text)
        self.apply_highlight()
        options.text = ""
        style = QtWidgets.QApplication.style() if options.widget is None \
            else options.widget.style()
        style.drawControl(QtWidgets.QStyle.CE_ItemViewItem, options, painter)

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

        textRect = style.subElementRect(
            QtWidgets.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 apply_highlight(self):
        cursor = QtGui.QTextCursor(self.doc)
        cursor.beginEditBlock()
        highlightCursor = QtGui.QTextCursor(self.doc)
        while not highlightCursor.isNull() and not highlightCursor.atEnd():
            highlightCursor = self.doc.find(self.regex, highlightCursor)
            if not highlightCursor.isNull():
                highlightCursor.mergeCharFormat(self.highlightFormat)
        cursor.endEditBlock()

    @property
    def regex(self):
        return self._regex

    @regex.setter
    def regex(self, regex):
        if self._regex == regex: return
        self._regex = regex

    @property
    def highlightFormat(self):
        return self._highlight_format

    @highlightFormat.setter
    def highlightFormat(self, fmt):
        self._highlight_format = fmt

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.table = QtWidgets.QTableView()

        self._delegate = HighlightDelegate(self.table)
        self._delegate.regex = QtCore.QRegularExpression(r"\(.*?\)")
        fmt = QtGui.QTextCharFormat()
        fmt.setForeground(QtCore.Qt.green)
        fmt.setFontWeight(QtGui.QFont.Bold)
        self._delegate.highlightFormat = fmt
        self.table.setItemDelegate(self._delegate)
        self.table.doubleClicked.connect(self.handleDoubleClickTV)

        r = 10
        c = 4
        self.model = QtGui.QStandardItemModel(r, c)
        self.str_items = [["" for i in range(c)] for j in range(r)]
        self.idx_items = [[0 for i in range(c)] for j in range(r)]
        self.setModel()
        self.setCentralWidget(self.table)

    def setModel(self):
        r = self.model.rowCount()
        c = self.model.columnCount()


        for i in range(r):
            for j in range(c):
                random_words = random.sample(words,4)
                str_item1 = "{}({}){}".format(*random_words[:-1]) # words 1, 2, 3
                str_item2 = "{}{}{}".format(*[random_words[0],random_words[3],random_words[2]]) #words 1,4,3
                item = QtGui.QStandardItem(str_item1)
                item.setEditable(False)
                self.str_items[i][j] = [str_item1, str_item2, item]
                self.model.setItem(i, j, item)
        self.table.setModel(self.model)

    def toggleText(self):
        model_index = self.table.selectedIndexes()[0]
        row = model_index.row()
        col = model_index.column()
        index = int(not self.idx_items[row][col])
        # toggle the str
        new_str_item = self.str_items[row][col][index]
        # get item
        item = self.str_items[row][col][2]
        item.setText(new_str_item)
        self.idx_items[row][col] = index

    def handleDoubleClickTV(self):
        self.toggleText()

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())
...