While I was experimenting with adding nlprule-based grammar-checking to my spell-checked QPlainTextEdit subclass (not yet polished enough to share, but there’s a cut-down proof of concept for the nlprule integration on StackOverflow if you want it), I ran into a little problem.
Apparently, there’s an unresolved bug (QTBUG-80524 and duplicates) where QTextEdit and QPlainTextEdit don’t take syntax highlighter-set changes into account when figuring out whether to display a tooltip and what to show.
The solution? Override the lookup behaviour. Here’s how you do it:
class TooltipPlainTextEdit(QPlainTextEdit): def __init__(self, *args): QPlainTextEdit.__init__(self, *args) # Opt in to the events we need to override self.setMouseTracking(True) def event(self, event) -> bool: """Reimplement tooltip lookup to get nlprule messages working""" if event.type() == QEvent.ToolTip: # Get a secondary text cursor, taking margins into account pos = event.pos() pos.setX(pos.x() - self.viewportMargins().left()) pos.setY(pos.y() - self.viewportMargins().top()) cursor = self.cursorForPosition(pos) # QTextCursor doesn't have a quicker way to get # highlighter-applied formats, so find the one that our # cursor is inside for fmt in cursor.block().layout().formats(): if (fmt.start <= cursor.position() and fmt.start + fmt.length >= cursor.position()): # Calculate the bounding box for the text and feed # it as the rectangle for requesting that the # tooltip auto-hide when the cursor exits cursor.setPosition(fmt.start) cursor.setPosition(fmt.start + fmt.length, QTextCursor.KeepAnchor) QToolTip.showText(event.globalPos(), fmt.format.toolTip(), self, self.cursorRect(cursor)) return True # Fall back to the default behaviour return super(TooltipPlainTextEdit, self).event(event)
…and that’s it. Your
QTextCharFormat.setToolTip calls should now Just Work™.
Tooltips for syntax highlights in QTextEdit/QPlainTextEdit by Stephan Sokolow is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
By submitting a comment here you grant this site a perpetual license to reproduce your words and name/web site in attribution under the same terms as the associated post.
All comments are moderated. If your comment is generic enough to apply to any post, it will be assumed to be spam. Borderline comments will have their URL field erased before being approved.