Ribtoks
Ribtoks

Reputation: 6922

Unable to get highlighting working on TextEdit

TL;DR: TextEdit paints highlighted text only when I click on it. Nothing helps

I have a ListView with a QAbstractListModel model with string properties. Those string properties are being spellchecked and QSyntaxHighlighter is used to show spell errors. I create QSyntaxHighlighter descendant in Component.onCompleted of TextEdit. I double-checked highlighting get's executed with correct spell errors and setFormat() of Highlighter is executed with correct positions. The problem is that it draws text in red (invalidates) only when I click on the TextEdit itself.

TextEdit lives in a Flickable (to track cursor) and Flickable lives in a Rectangle (to have nice background and border). Binding to some signals and calling update() of TextEdit does not help.

After spellcheck finishes, I emit rehighlight() signal of created SyntaxHighlighter.

Rectangle {
  id: descriptionRect
  height: 30
  border.width: descriptionTextInput.activeFocus ? 1 : 0
  clip: true

  Flickable {
      id: descriptionFlick
      contentWidth: descriptionTextInput.paintedWidth
      contentHeight: descriptionTextInput.paintedHeight
      anchors.fill: parent
      interactive: false
      flickableDirection: Flickable.HorizontalFlick
      height: 30
      clip: true
      focus: false

      function ensureVisible(r) {
          if (contentX >= r.x)
              contentX = r.x;
          else if (contentX+width <= r.x+r.width)
              contentX = r.x+r.width-width;
      }

      TextEdit {
          id: descriptionTextInput
          width: descriptionFlick.width
          height: descriptionFlick.height
          text: description
          onTextChanged: model.editdescription = text

          Component.onCompleted: {
              globalModel.initDescriptionHighlighting(index, descriptionTextInput.textDocument)
          }

          onCursorRectangleChanged: descriptionFlick.ensureVisible(cursorRectangle)
         }
     }
 }

Here is a small sample of project with demonstration of how it does not work until you click on a text https://bitbucket.org/ribtoks/qt-highlighting-issue

Any ideas how I can solve this?

Upvotes: 8

Views: 1168

Answers (2)

Twisted89
Twisted89

Reputation: 446

Just encountered this issue on 5.11.2 and found the following fix which allows updating of individual blocks without having to highlight/deselect the whole text area

rehighlightBlock(newBlock);
Q_EMIT document()->documentLayout()->updateBlock(newBlock);

Upvotes: 1

Simon Warta
Simon Warta

Reputation: 11408

The issue was probably caused by QTBUG-44765, fixed in Qt 5.5.

Given the low level of the bug, I don't think it is practically to work around it.

You can work around that by appending an empty string to the TextEdit when you're done with the syntax highlighting

TextEdit {
    id: captionTextEdit
    width: wrapperFlick.width
    height: wrapperFlick.height
    text: display
    readOnly: true

    Component.onCompleted: {
        itemsModel.initHighlighter(index, captionTextEdit.textDocument)
    }

    Connections {
        target: itemsModel
        onUpdateTextEdit: {
            console.log("Update element at index: " + indexToUpdate)

            if (indexToUpdate == index)
            {
                console.log("Update me!")
                captionTextEdit.append("")
            }
        }
    }

    onCursorRectangleChanged: wrapperFlick.ensureVisible(cursorRectangle)
}

where updateTextEdit(indexToUpdate) is a new signal your itemsModel has to emit.

itemsmodel.h

signals:
    void updateTextEdit(int indexToUpdate);

itemsmodel.cpp

void ItemsModel::initHighlighter(int index, QQuickTextDocument *document) {
    // Signal mapper could be avoided if lamda slot are available (Qt5 and C++11)
    QSignalMapper* signalMapper = new QSignalMapper(this);

    if (0 <= index && index < m_ItemsList.length()) {
        SingleItem *item = m_ItemsList.at(index);
        SpellCheckHighlighter *highlighter = new SpellCheckHighlighter(document->textDocument(), item);
        QObject::connect(item, SIGNAL(spellCheckResultsReady()),
                         highlighter, SLOT(rehighlight()));

        // TODO: Don't connect this slot for Qt 5.5+ to avoid performance overhead
        QObject::connect(item, SIGNAL(spellCheckResultsReady()),
                         signalMapper, SLOT(map()));
        signalMapper->setMapping(item, index);
    }

    connect(signalMapper, SIGNAL(mapped(int)),
            this, SIGNAL(updateTextEdit(int)));
}

Full code is available here: https://bitbucket.org/swarta/rehighlighdemo/branch/workaround#diff

Upvotes: 1

Related Questions