spacr.qt.widgets.field_fade

Fade form-field chrome to the right while keeping text fully opaque.

The fill and outline follow a cubic transparency ramp defined by spacr.qt.theme.field_fade_alpha(): the left edge uses the theme token’s own alpha, the midpoint remains 87.5% opaque, and the right edge is fully transparent. Field chrome is independent of the page-opacity preference and the effect is enabled by default through the field-fade preference.

A registered stylesheet makes each supported editor’s background and border transparent while reserving its one-pixel border geometry. An application- wide paint-event filter then draws the ramped fill and outline before Qt draws the editor’s text, selection, and cursor. Installing one filter on QApplication covers fields created or rebuilt after startup without per-screen registration. Non-paint events pass through without repaint work.

Embedded line editors, item-view cell editors, multiline text widgets, and widgets carrying OPT_OUT_PROPERTY are excluded. Higher-specificity ID-based styles can intentionally keep an opaque fill and hide the ramp.

Functions

ensure_field_fade_qss(→ None)

(Re)register the QSS block. Idempotent, and called by

fades(→ bool)

Whether widget is a field this effect should paint.

field_fade_enabled(→ bool)

Whether fields fade. Cached — this is read on every paint event.

field_fade_qss(→ str)

The registered QSS block. Empty when the preference is off.

install_field_fade(→ bool)

Install the application-wide paint hook. Idempotent.

invalidate_field_fade(→ None)

Forget the cached preference so the next read hits QSettings.

paint_field_fade(→ None)

Draw widget's ramped container and outline with painter.

repaint_fields(→ int)

Schedule a repaint of every live field. Returns how many.

uninstall_field_fade(→ bool)

Remove the paint hook. True if there was one.

Module Contents

spacr.qt.widgets.field_fade.ensure_field_fade_qss() → None[source]

(Re)register the QSS block. Idempotent, and called by install_field_fade() as well as at import.

Both, because importing a module happens once per process while the registry is a mutable global: a test that snapshots and restores it would otherwise switch the effect off for the rest of the session with no way to get it back.

spacr.qt.widgets.field_fade.fades(widget) → bool[source]

Whether widget is a field this effect should paint.

Two exclusions, both of them about what the widget is rather than what class it belongs to:

  • The QLineEdit a spin box or an editable combo box embeds. That inner editor is a field by type but not by appearance: its container already ramps, and a second ramp inside the first would put a seam down the middle of one control.

  • An item view’s in-place cell editor. It is a temporary widget laid over a row of data, not a form field with space to its right, so a transparent trailing half would show the cell it is covering and read as a rendering fault rather than as a design.

Parameters:

widget – the widget to test; only the field types in FIELD_TYPES that have not set the opt-out property can qualify.

spacr.qt.widgets.field_fade.field_fade_enabled() → bool[source]

Whether fields fade. Cached — this is read on every paint event.

Building a QSettings per paint would put a file-format lookup in the middle of the render loop. The cache is dropped by invalidate_field_fade(), which spacr.qt.preferences.set_field_fade_enabled() and spacr.qt.preferences.apply_preferences_to_app() both call, so the two can never disagree about what is on screen.

spacr.qt.widgets.field_fade.field_fade_qss(palette: dict, opacity: float | None = None) → str[source]

The registered QSS block. Empty when the preference is off.

Empty is load-bearing: with nothing emitted, the built-in input rules are untouched and a field looks exactly as it did before this module existed, which is what “turn it off” has to mean.

Signature is spacr.qt.theme.register_widget_qss()’s contract; neither argument is used, and that is the point — a field is exempt from opacity, and its colours come from spacr.qt.theme.field_chrome() at paint time so they survive a theme switch without the stylesheet having baked them in.

Parameters:

palette – the theme palette passed by spacr.qt.theme.register_widget_qss(); unused.

spacr.qt.widgets.field_fade.install_field_fade(app=None) → bool[source]

Install the application-wide paint hook. Idempotent.

Parameters:

app – the QApplication; defaults to the running instance.

Returns:

True if a filter was installed by this call.

spacr.qt.widgets.field_fade.invalidate_field_fade() → None[source]

Forget the cached preference so the next read hits QSettings.

spacr.qt.widgets.field_fade.paint_field_fade(widget, painter: PySide6.QtGui.QPainter, theme: str | None = None) → None[source]

Draw widget’s ramped container and outline with painter.

Separated from the event filter so a test can drive it against a plain image, and so a widget that wants the look inside its own paintEvent can call it directly.

Parameters:
  • widget – the field. Only its rect() and its focus/enabled state are read.

  • painter – an active painter whose coordinates are the widget’s.

  • theme – theme name; None resolves the effective one.

spacr.qt.widgets.field_fade.repaint_fields(app=None) → int[source]

Schedule a repaint of every live field. Returns how many.

The stylesheet swap that follows a preference change already forces a repolish, but a field whose look changed without its style changing — turning the effect off while the QSS block was already empty — has nothing else to trigger it.

spacr.qt.widgets.field_fade.uninstall_field_fade(app=None) → bool[source]

Remove the paint hook. True if there was one.