spacr.qt.preview_registry

Which modules get a Live Preview, and how one is attached from outside.

Four modules have a preview: Mask, Measure, Timelapse and Motility. Each one costs a thirteen-line arm in AppScreen._build_runtime_panel, two attribute names in a null-out block, and a row in a toggle table two hundred lines further down.

A fifth would cost the same, which is why there has never been one. The two modules that would benefit most are the ones whose entire job is “did the mask come out right”, Cellpose Masks and Plaque Assay, and neither was worth touching the shared screen for.

This module is the seam that makes the fifth free. A module declares a preview here; the strip above the settings form grows a toggle for it; the card is inserted above the Run row through the same _runtime_wrap / _actions_row anchors spacr.qt.prerun uses. Nothing inside AppScreen changes, and the four previews it already builds are left alone — a module the shared screen has already served is skipped here rather than given a second card.

A module that has been FOLDED into a host reaches the same machinery from the other end. Its own screen is not built any more, so install – which answers for the screen’s own key – can never attach its panel; attach_folded() lets the host ask for it by name and keeps it hidden behind whatever the host uses to reveal the rest of that module. Mask Generation’s tracking switch is the case it was written for.

The sampling contract is inherited, not reimplemented. The panels reached through this registry are the shipped ones, which group a plate into image sets from file names alone and open a bounded, reproducible random sample of it. Nothing here enumerates, opens or lists a directory, so nothing here can regress that. A new panel registered through this seam must keep the same promise — see spacr.qt.widgets.preview_controls.

Classes

PreviewSpec

One module's preview declaration.

Functions

attach_folded(→ Optional[_PreviewHost])

Attach ANOTHER module's declared preview to screen.

install(→ Optional[_PreviewHost])

Attach screen's declared preview, if it has one to attach.

install_window_hooks(→ Optional[_StackWatcher])

Follow window's screen stack, attaching declared previews.

preview_app_keys(→ Tuple[str, ...])

Every module with a preview, however it is attached.

register_preview(→ PreviewSpec)

Declare a preview for app_key.

unregister_preview(→ bool)

Drop a declaration. True if there was one.

Module Contents

class spacr.qt.preview_registry.PreviewSpec[source]

One module’s preview declaration.

Variables:
  • builder – "module:function" returning (panel, card), the shape every existing build_*_preview_card already has. Named rather than imported so declaring a preview costs no import at launch — a preview panel drags in the imaging stack.

  • title – the toggle’s label.

  • tooltip – what the toggle promises.

  • propagation – rename map applied to whatever the panel hands back through set_propagate_callback, so a panel written for one module’s setting names can serve another’s.

  • owned_by_screen – True for the ones AppScreen already builds. They are declared here so this registry is the single answer to “which modules have a preview”, and skipped at install time so they do not get a second card.

  • fill – "module:function" taking (host, card) and building the panel into the card, returning it. Given, a preview ATTACHED through this registry builds only its card at install – builder is called with panel_later=True – and the panel the first time the card is shown or the panel is asked for, so a hidden preview costs a module’s open nothing.

spacr.qt.preview_registry.attach_folded(screen: PySide6.QtWidgets.QWidget, app_key: str) → _PreviewHost | None[source]

Attach ANOTHER module’s declared preview to screen.

A module folded into a host as settings categories brings its panel with it. Mask Generation has the Cellpose live preview and no track preview; Timelapse’s whole preview is the tracking one, built by the screen the fold means nobody opens any more. Without this the switch would reveal the tracking settings and nothing that shows what they do – a capability the tile had and the button did not, which is the one thing a fold must not cost.

owned_by_screen is deliberately ignored: it means “AppScreen builds this one for its own key”, and the point here is that the key is somebody else’s. The card and its toggle both start hidden; the host reveals them when the fold is switched on.

Parameters:
  • screen – the HOST screen.

  • app_key – the folded module’s key.

Returns:

the host, or None when there is nothing to attach.

spacr.qt.preview_registry.install(screen: PySide6.QtWidgets.QWidget) → _PreviewHost | None[source]

Attach screen’s declared preview, if it has one to attach.

Returns None when the module declares no preview, when AppScreen already built one for it, when the screen has no runtime panel to insert into, or when one is already installed. Never raises: a missing preview must not cost anyone a module.

Parameters:

screen – app screen widget; its app_key attribute selects the declared preview, and the installed host is remembered on it so a second call returns the same one.

spacr.qt.preview_registry.install_window_hooks(window: PySide6.QtWidgets.QMainWindow) → _StackWatcher | None[source]

Follow window’s screen stack, attaching declared previews.

Called once from spacr.qt.shortcuts.install(), after the settings strip’s own hook so the toggle has somewhere to go.

Parameters:

window – main window whose _stack screen stack is followed; without one nothing is installed, and a watcher already stored on it is returned instead of a new one.

spacr.qt.preview_registry.preview_app_keys() → Tuple[str, ...][source]

Every module with a preview, however it is attached.

spacr.qt.preview_registry.register_preview(app_key: str, spec: PreviewSpec, *, replace: bool = False) → PreviewSpec[source]

Declare a preview for app_key.

Parameters:
  • app_key – the module’s app key.

  • spec – its declaration.

  • replace – overwrite an existing declaration instead of raising.

Raises:

ValueError – on a second declaration without replace — two modules quietly claiming one key is the failure a registry exists to make loud.

spacr.qt.preview_registry.unregister_preview(app_key: str) → bool[source]

Drop a declaration. True if there was one.

Parameters:

app_key – app key whose preview declaration is removed; converted with str() first.