I have been working on adding inline spell check to Sigil recently and ran into a quirk on Qt that isn’t immediately obvious. I ended up having to look though the Qt source code to understand exactly what was happening.
When dealing with a QPlainTextEdit
you can get the QTextCursor
and use the
charFormat()
function to retrieve the QTextCharFormat
for the character before
the cursor. This does not work when the formatting is set by a
QSyntaxHighlighter
!.
charFormat
retrieves the character format that has explicitly been set on the
QPlainTextEdit
. QSyntaxHighlighter
does not directly set the formatting on the
QPlainTextEdit
. Instead QSyntaxHighlighter
sets the format in additionalFormats
as part of the block layout. All formatting for the block the cursor is
currently in can be accessed by using
QPlainTextEdit::textCursor().block().layout()->additionalFormats()
.
QTextLayout::additionalFormats()
returns a list of
FormatRange
objects. A FormatRange
gives the start of the formatting (relative to the block
not the full text in the QPlainTextEdit
), the length and the formatting (as set
by the QSyntaxHighlighter
). Simply loop over all of the FormatRange
objects and
check if the cursor is within a range to determine what formatting is applied
to a particular part of the block’s text. Use QTextCursor::positionInBlock()
to
determine the relative position of the cursor within the block.
Here is an example from Sigil that I use for spell checking. It determines if a particular segment of text has the misspelled word style applied to it. It then selects the text.
QTextCursor c = textCursor();
int pos = c.positionInBlock();
foreach (QTextLayout::FormatRange r, textCursor().block().layout()->additionalFormats()) {
if (pos >= r.start && pos <= r.start + r.length && r.format.underlineStyle() == QTextCharFormat::SpellCheckUnderline) {
c.setPosition(c.block().position() + r.start);
c.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, r.length);
setTextCursor(c);
break;
}
}
Note: QTextEdit
can be substituted any place QPlainTextEdit
is used. This
applies to both not just QPlainTextEdit
.