Maluna34
Maluna34

Reputation: 245

QSyntaxHighlighter does not create QTextFragments

I'm working on a syntax highlighter with Qt and I wanted to add unit tests on it to check if formats are well applied. But I don't manage to get the block divided by formats. I use QTextBlock and QTextFragment but it's not working while the doc of QTextFragment says :

A text fragment describes a piece of text that is stored with a single character format.

Here is the code in a runnable main.cpp file :

#include <QApplication>
#include <QTextEdit>
#include <QSyntaxHighlighter>
#include <QRegularExpression>
#include <QDebug>

class Highlighter : public QSyntaxHighlighter
{
public:

    Highlighter(QTextDocument *parent)
        : QSyntaxHighlighter(parent)
    {}

protected:

    void highlightBlock(const QString& text) override
    {
        QTextCharFormat classFormat;
        classFormat.setFontWeight(QFont::Bold);

        QRegularExpression pattern { "\\bclass\\b" };

        QRegularExpressionMatchIterator matchIterator = pattern.globalMatch(text);
        while (matchIterator.hasNext())
        {
            QRegularExpressionMatch match = matchIterator.next();
            setFormat(match.capturedStart(), match.capturedLength(), classFormat);
        }


        // ==== TESTS ==== //

        qDebug() << "--------------------------------";
        QTextDocument *doc = document();

        QTextBlock currentBlock = doc->firstBlock();

        while (currentBlock.isValid()) {
            qDebug() << "BLOCK" << currentBlock.text();

            QTextBlockFormat blockFormat = currentBlock.blockFormat();
            QTextCharFormat charFormat = currentBlock.charFormat();
            QFont font = charFormat.font();

            // each QTextBlock holds multiple fragments of text, so iterate over it:
            QTextBlock::iterator it;
            for (it = currentBlock.begin(); !(it.atEnd()); ++it) {
                QTextFragment currentFragment = it.fragment();
                if (currentFragment.isValid()) {
                    // a text fragment also has a char format with font:
                    QTextCharFormat fragmentCharFormat = currentFragment.charFormat();
                    QFont fragmentFont = fragmentCharFormat.font();

                    qDebug() << "FRAGMENT" << currentFragment.text();
                }
            }

            currentBlock = currentBlock.next();
        }
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    auto *textEdit = new QTextEdit;
    auto *highlighter = new Highlighter(textEdit->document());
    Q_UNUSED(highlighter);

    textEdit->setText("a class for test");

    textEdit->show();

    return a.exec();
}

And it outputs only one block "a class for test" and one format "a class for test" while the class keyword is in bold.

Thanks for your help !

Upvotes: 1

Views: 277

Answers (1)

Maluna34
Maluna34

Reputation: 245

Ok I found this from the documentation of QSyntaxHighlighter::setFormat :

Note that the document itself remains unmodified by the format set through this function.

The formats applied by the syntax highlighter are not stored in QTextBlock::charFormat but in the additional formats :

QVector<QTextLayout::FormatRange> formats = textEdit->textCursor().block().layout()->formats();

Upvotes: 3

Related Questions