0

It is related to the previous question. If now a text between the parenthesis (and parenthesis included) were replaced for another text, is it complicated to keep the colour on the replacement (even it doesn't have any limiter or whatever)? I have a toggle function which changes that, and would be great to keep the colour on the replacement.

Here the code example modified to satisfy the new condition (now with double click you can change (toggle) the item text:

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_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
eddy2k
  • 119
  • 1
  • 12
  • Of course, I tried!! It took me even a lot of time even to change the example (to look as a super simplified problem of my program) – eddy2k Jan 25 '19 at 03:30
  • exactly!! the part that was changed keep it green too as Curabitur, I tried to do it, but I don't find a way to do it as a regex or something... and put a secondary delegate... – eddy2k Jan 25 '19 at 03:37
  • Yes, let's say that we have this: aaa(bbb)ccc(ddd)eee() and it change to aaafffcccgggeee, (bbb),(ddd) and () are green, and fff and ggg should be green too, if there is nothing between the parenthesis, nothing will be green when replace – eddy2k Jan 25 '19 at 03:39
  • I mean what is not green initially will always remain, am I right? – eyllanesc Jan 25 '19 at 03:41
  • Yes, you are right – eddy2k Jan 25 '19 at 03:42
  • I have a system of strings with replacements variables in parenthesis. What I want is to see the variables to replace, and when replace, what is the content of them, and both in the same color, as it is easier to follow up... These are my needs. This is not an XY problem, sir. – eddy2k Jan 25 '19 at 03:52
  • No, the code replace them... the user doesn't input anything, just look at it. Just I need to do what I already explain perfectly. It is a super simplified version of a tiny part of app, which here could think that doesn't make sense, but it makes completely sense in the program I have. I am software engineer but don't know too much about QT, just trying to survive with this task... – eddy2k Jan 25 '19 at 03:57
  • You can assume, as in the code, that you have both strings, (the original one, and the replaced one -without parenthesis and with the new strings-) stored in a data structure (like in the example str_item1 and str_item2 stored in self.str_items), so maybe an string comparison can do the trick... Just solving the code I provide, as is, I am sure it would be ok – eddy2k Jan 25 '19 at 04:06
  • complete string, first case – eddy2k Jan 25 '19 at 05:15
  • We can fulfil, but with operations from the previous strings, I told you. I don't have context to get it natively from parsing time. But we have both strings, and from them we can build that list of substrings... Is it not OK? Is what I said all this time. Can we build this substrings from the these ones? I guess, right? – eddy2k Jan 25 '19 at 20:10
  • Fair enough, gotcha. No sé porque no hablamos en español, seguro que nos entendemos mejor. – eddy2k Jan 25 '19 at 20:15
  • *The inputs you propose, I didn't* and you accepted them. – eyllanesc Jan 27 '19 at 04:38

0 Answers0