Fragile QTextBlock iterator

From qtnode

Jump to: navigation, search

The QTextBlock class acts a read-only iterator, but has a few (currently) undocumented gotchas.

Iterating within a range of blocks

For one thing, you might be tempted to iterate over an open-ended range. So you try while (block < endBlock). However you can run into problems if endBlock.isValid() returns false. However, you could possibly use while (block != endBlock) instead. Just something to keep in mind: testing indicates that a document uses a shared invalid block as a dummy head and tail block, so that one block before the start of the document and one block after the end of the document compare as the same block.

You can see the problem with using < in the following program:

#include <QtGui>

int main(int argc, char *argv[])
{
        QApplication app(argc, argv);
        QTextEdit edit;
        edit.setPlainText(QLatin1String("hi"));
        QTextBlock block = edit.document()->begin();
        QTextBlock endBlock = edit.document()->end();
        qDebug() << block.isValid();
        qDebug() << endBlock.isValid();
        qDebug() << (block < endBlock);
}

which prints the following:

true
false
false

You might expect the comparison to not be well-defined for an invalid block anyway, even if the invalid QTextBlock was the result of QTextBlock::next(). In any case, you can do a closed-end loop something like this:

QTextBlock block = ...;
for(; block.isValid() && !(endBlock < block); block = block.next()) {
        // process block
}

but this time endBlock must be a valid QTextBlock and the variable block is initialized to whatever starting QTextBlock you wanted. The reason for the convoluted comparison is because operator overloading is incomplete and of course !(endBlock < block) is simply (block <= endBlock).

Normally, you might just iterate until isValid() returns false for the current block. But that's not very useful unless you want to iterate until the end of the document.

QTextBlock::isValid() can't tell you that the QTextBlock still exists

If for whatever reason you're caching a QTextBlock (like in QSyntaxHighlighter), then know that if that block gets removed from the document, you'll probably crash the program if you attempt to access it. Using QTextBlock::isValid() won't tell you if that block still exists. Using a QTextCursor instead might be useful, so long as you don't mind that its position will automatically change as the document is edited.

Personal tools