spacr.qt.tooltip_policy

One rule for every tooltip in spaCR: when it appears and when it goes.

Qt’s own answer is a style hint, SH_ToolTip_WakeUpDelay, which most styles set to about 700 ms and which nothing in spaCR was choosing. Tooltips therefore arrived while the pointer was still travelling, and left the instant it moved off the widget – too fast to read, and impossible to reach if the text ran long.

This module installs ONE event filter on QApplication and takes the decision away from the style:

  • a tooltip appears after the Tooltip delay preference of hovering, not before (SHOW_DELAY_MS when nothing is stored);

  • it stays while the pointer is on the widget OR on the tooltip itself;

  • it leaves LINGER_MS after the pointer leaves both.

Because the filter sits on the application object, a widget written later obeys the rule without anyone remembering to ask for it: its ToolTip event travels to the application like every other one.

The filter shows the text itself, with QToolTip.showText and no owning widget, rather than letting Qt show it. Handing Qt the widget hands Qt the hiding as well – Qt hides on the widget’s Leave event, immediately, which is the one behaviour this module exists to change.

Two things follow from taking the event, and both are handled rather than accepted:

  • Qt PROPAGATES a tooltip event to the parent widget when the widget under the pointer has no tooltip of its own, which is how a card explains itself while the pointer is on the label written on it. The text is therefore resolved with tooltip_text_for(), up the parent chain, exactly as Qt would have.

  • A table, a header or a list answers from Qt::ToolTipRole inside its own event, not from a toolTip() any filter can read. When nothing in the parent chain has a tooltip, the event is SENT AGAIN after the wait, with the filter standing aside, so those still appear – and appear on the same two-second rule as everything else.

tooltips_enabled() is the preference switch, on by default. Cleared, the ToolTip event is swallowed and no tooltip is shown anywhere.

Classes

HoverDelay

Schedule custom hover help using the global delay in seconds.

Functions

install_tooltip_policy(→ bool)

Install the application-wide tooltip filter. Idempotent.

invalidate_tooltip_policy(→ None)

Forget the cached preference, and hide anything already up.

tooltip_policy(→ Optional[_TooltipFilter])

The installed filter, or None. For tests and for diagnostics.

tooltip_text_for(→ str)

The tooltip a hover on widget would raise, parents included.

tooltips_enabled(→ bool)

Whether tooltips are shown at all. Cached; True by default.

uninstall_tooltip_policy(→ bool)

Remove the filter. True if there was one.

Module Contents

class spacr.qt.tooltip_policy.HoverDelay(parent=None)[source]

Bases: PySide6.QtCore.QObject

Schedule custom hover help using the global delay in seconds.

Parameters:

parent – QObject owning this hover surface and its timer.

Create an idle timer owned by parent.

Parameters:

parent – QObject whose lifetime owns this timer.

cancel() → None[source]

Cancel pending help and release its target and callback.

cancel_for(anchor) → None[source]

Cancel only the target that left, allowing late neighbouring leaves.

Parameters:

anchor – widget sending the leave event.

eventFilter(obj, event)[source]

Cancel when the target leaves or its window is hidden/closed.

Parameters:
  • obj – anchor or its top-level window.

  • event – event observed without consuming it.

schedule(anchor, callback) → None[source]

Wait a full continuous hover before invoking callback.

Parameters:
  • anchor – widget being hovered; leaving or hiding cancels.

  • callback – zero-argument callable that presents the help.

spacr.qt.tooltip_policy.install_tooltip_policy(app=None) → bool[source]

Install the application-wide tooltip filter. Idempotent.

Parameters:

app – the QApplication; defaults to the running instance.

Returns:

True if a filter was installed by this call.

spacr.qt.tooltip_policy.invalidate_tooltip_policy() → None[source]

Forget the cached preference, and hide anything already up.

spacr.qt.tooltip_policy.tooltip_policy() → _TooltipFilter | None[source]

The installed filter, or None. For tests and for diagnostics.

spacr.qt.tooltip_policy.tooltip_text_for(widget) → str[source]

The tooltip a hover on widget would raise, parents included.

This is not a convenience: it is the behaviour being preserved. Qt PROPAGATES a tooltip event up the parent chain, so a label with no tooltip of its own inside a card that has one shows the card’s. A filter that read widget.toolTip() alone and then swallowed the event would break every one of those – a card explains itself until the pointer lands on the text written on it, and then it stops.

Parameters:

widget – the hovered widget, or None; its toolTip() is read, then each parent’s up to and including its window (at most 64 levels).

Returns:

the first non-empty tooltip from the widget outwards, or "" if neither it nor any parent up to its window has one.

spacr.qt.tooltip_policy.tooltips_enabled() → bool[source]

Whether tooltips are shown at all. Cached; True by default.

Read on every ToolTip event, which is why the answer is cached rather than re-read from QSettings each time. invalidate_tooltip_policy() drops the cache, and spacr.qt.preferences.set_tooltips_enabled() calls it, so the switch and the screen can never disagree.

spacr.qt.tooltip_policy.uninstall_tooltip_policy(app=None) → bool[source]

Remove the filter. True if there was one.