Search code examples
c++qtsyntaxtooltip

Add a ToolTip with a QSyntaxHighlighter and a QTextCharFormat


I'm trying to create a little syntax highlighter in Qt, and i want to show a tooltip with the description of the error when the user hoover it.

(I'm subclassing QSyntaxHighlighter)

I've tried the QTextCharFormat::setToolTip function, but it didn't work :/ The text is red-underlined as expected, but no tooltip are shown when I hover over it.

Did i miss something ? Or should i use another method ?

void CodeHighlighter::highlightBlock(const QString &text)
{
    _errorFormat.setProperty(QTextFormat::TextUnderlineStyle, QTextCharFormat::SpellCheckUnderline);
    _errorFormat.setProperty(QTextFormat::TextUnderlineColor, QColor(Qt::red));
    if (!isLineValid(text.toStdString())) {

        // The following line does not work !
        _errorFormat.setToolTip(QString::fromStdString(getLastError()));

        setFormat(0, text.length(), _errorFormat);
    }
    for (const HighlightingRule &rule : qAsConst(_highlightingRules)) {
        QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
        while (matchIterator.hasNext()) {
            QRegularExpressionMatch match = matchIterator.next();
            QTextCharFormat format = this->format(match.capturedStart());
            format.merge(rule.format);
            setFormat(match.capturedStart(), match.capturedLength(), format);
        }
    }
}

Solution

  • You can make it work by overriding handling of the QEvent::ToolTip and doing the lookup yourself.

    I don't have time to rewrite my complete answer in C++, but:

    • This SO answer has C++ code for doing the override but not the lookup. (Basically, on the QTextEdit or QPlainTextEdit, you setMouseTracking(True), override the event method, and hand off to the default implementation unless event->type() == QEvent::ToolTip. The other answer to that question points out that you'll also need to correct for margins if you're using them.)
    • This QtCenter post has C++ code to look up the highlighter-applied format in C++... though it does use one deprecated method. (The gist of it is that, in modern Qt, you need to use cursorForPosition, then .block().layout()->formats() and iterate through, comparing offsets to the cursor's position(). additionalFormats() being the deprecated method and formats() being the modern one.)
    • This SO answer I wrote is a complete, runnable example which demonstrates exposing grammar-checking information as tooltips... it's just written in Python against PyQt.