Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 412
Ribtoks Avatar asked Nov 29 '15 11:11

Ribtoks


People also ask

How do I change TextEdit Preferences on Mac?

In the TextEdit app, you can set preferences for all new TextEdit documents, and for opening and saving documents. To change these preferences in the TextEdit app on your Mac, choose TextEdit > Preferences, then click New Document or Open and Save.

How do I change my default TextEdit to Word?

Depending on your version of TextEdit you should be able to open the file, then use File> Save As & pick Word 2007 Format (. docx) from the File Format: list before you click Save. Alternatively: Assuming that the file is saved in TextEdit's default format (.


2 Answers

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);
like image 165
Twisted89 Avatar answered Oct 07 '22 02:10

Twisted89


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

like image 24
Simon Warta Avatar answered Oct 07 '22 01:10

Simon Warta