Ascertaining visible QTextBlocks

From qtnode

Jump to: navigation, search

Note: this is only relevant if the hit test underlying cursorForPosition is any faster than just iterating from the start of the document and checking the layout position.

To perform any custom painting on the document shown in a QTextEdit, it is valuable to know which blocks are currently visible in the QTextEdit's viewport, so as to not waste too much time in the paint event. Such custom painting might involve drawing visible tab stops, or custom underlining of text -- say a squiggly red underline.

To this end, you can make good use the function QTextEdit::cursorForPosition. With left-to-right text, you could call cursorForPosition(QPoint(0, 0)) to get the top visible cursor, and cursorForPosition(QPoint(viewport()->width(), viewport()->height())) to get the bottom-right visible cursor. Conveniently, the function argument is in viewport coordinates, which means, for example, that QPoint(0, 0) means the top-left visible corner of the document and not the top of the entire document. Even if there isn't any text at the bottom-right corner of the document, the function returns the closest cursor to it, almost as if you had clicked there.

Knowing the top-left and bottom-right visible cursor, you can iterate between them, doing any custom painting you want. You can use the function QTextCursor::block() to get the QTextBlock for the cursor. Since Qt 4.1, QTextBlockUserData could be used to store any additional information you might like to use for painting that particular block.

For bidirectional text, a modified approach is probably required. This page will be updated with the results. For getting the top visible cursor, perhaps call QTextEdit::cursorForPosition for the top left and top right position, and then compare each value of QTextCursor::position() to know which QTextCursor actually comes first. Then you do likewise for the bottom visible cursor.

In the end, this might not be the most optimal method, but it seems the easiest and the performance is decent.

Personal tools