Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QSyntaxHighlighter does not create QTextFragments



  • Hi,

    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 !



  • 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();
    

Log in to reply