pyqt_reactive.services.window_manager

Global window registry for scoped singleton windows with navigation support.

Ensures only one window per scope_id exists at a time and provides navigation API for inheritance tracking (click field → open window + scroll to source).

Architecture: - Centralized registry (like ObjectStateRegistry pattern) - Singleton windows per scope_id - Extensible navigation protocol - Auto-cleanup on window close - Fail-loud if window deleted but still in registry

Example Usage:

# Basic: Show or focus existing window WindowManager.show_or_focus(

scope_id=”plate1”, window_factory=lambda: ConfigWindow(…)

)

# Future: Navigate to specific field for inheritance tracking WindowManager.focus_and_navigate(

scope_id=”plate1”, field_path=”well_filter_config.well_filter” # Scroll to this field

)

Classes

NavigationRetryScheduler()

Schedule bounded navigation retries while forms/lists finish building.

WindowLookupResult(scope_id, status[, window])

WindowLookupStatus(*values)

WindowManager()

Global registry for scoped windows with navigation support.

class pyqt_reactive.services.window_manager.WindowLookupStatus(*values)[source]
PRESENT = 'present'
MISSING = 'missing'
HIDDEN = 'hidden'
STALE = 'stale'
class pyqt_reactive.services.window_manager.WindowLookupResult(scope_id: str, status: pyqt_reactive.services.window_manager.WindowLookupStatus, window: PyQt6.QtWidgets.QWidget | None = None)[source]
scope_id: str
status: WindowLookupStatus
window: QWidget | None = None
property is_present: bool
__init__(scope_id: str, status: WindowLookupStatus, window: QWidget | None = None) None
class pyqt_reactive.services.window_manager.NavigationRetryScheduler[source]

Schedule bounded navigation retries while forms/lists finish building.

MAX_RETRIES = 10
RETRY_DELAY_MS = 50
classmethod schedule(request: RegisteredWindowNavigationRequest, driver: WindowNavigationDriver, retry_counts: Dict[int, int], check_and_navigate: Callable[[], None]) bool[source]
static clear(request: RegisteredWindowNavigationRequest, retry_counts: Dict[int, int]) None[source]
class pyqt_reactive.services.window_manager.WindowManager[source]

Global registry for scoped windows with navigation support.

Ensures only one window per scope_id exists at a time. Provides navigation API for focusing windows and scrolling to items/fields.

Patterns: - Singleton windows per scope (like ObjectStateRegistry for states) - Navigation protocol (optional methods, duck typing) - Auto-cleanup on close (no manual unregistration needed) - Fail-loud on stale references

classmethod position_window_near_cursor(window: QWidget, offset: int = 0, avoid_widgets: Sequence[QWidget] = ()) None[source]

Place window centered on mouse cursor without overlapping floating windows.

classmethod show_or_focus(scope_id: str, window_factory: Callable[[], QWidget], item_id: str | None = None, field_path: str | None = None, navigation_driver: WindowNavigationDriver | None = None, code_document_driver: WindowCodeDocumentDriver | None = None) QWidget[source]

Show window for scope_id. Reuse existing or create new.

If window already exists for this scope_id, brings it to front. Otherwise, creates new window using factory and registers it.

Auto-cleanup: Window is automatically unregistered when closed.

IMPORTANT: Navigation is deferred to handle async widget creation. The scroll/flash only triggers after: 1. Window is shown and painted 2. Target widgets are built (via _on_build_complete_callbacks)

Parameters:
  • scope_id – Unique identifier for the window (e.g., plate path, step scope)

  • window_factory – Callable that creates the window if needed

  • item_id – Optional item to select after showing (e.g., list index)

  • field_path – Optional field to highlight after showing (e.g., “well_filter_config.well_filter”)

Returns:

The window (existing or newly created)

Example

def create_config_window():
return ConfigWindow(

config_class=PipelineConfig, initial_config=current_config, scope_id=”plate1”

)

window = WindowManager.show_or_focus(“plate1”, create_config_window)

# Show and navigate to field WindowManager.show_or_focus(

“plate1”, create_config_window, field_path=”well_filter_config.well_filter”

)

classmethod focus_and_navigate(scope_id: str, item_id: str | None = None, field_path: str | None = None) bool[source]

Focus window and navigate to specific item/field.

Brings window to front and optionally navigates to item/field. Navigation only works if window implements the navigation protocol.

IMPORTANT: Uses deferred navigation to handle async widget creation. The scroll/flash only triggers after: 1. Window is shown and painted 2. Target widgets are built (via _on_build_complete_callbacks)

Parameters:
  • scope_id – Window to focus

  • item_id – Optional item to select (e.g., list index, tab name)

  • field_path – Optional field to highlight (e.g., “well_filter_config.well_filter”)

Returns:

True if window was found and focused, False otherwise

Example

# Focus window and scroll to field (for inheritance tracking) WindowManager.focus_and_navigate(

scope_id=”plate1”, field_path=”well_filter_config.well_filter”

)

# Focus window and select item WindowManager.focus_and_navigate(

scope_id=”plate1::step_3”, item_id=”3” # Select step 3 in list

)

classmethod focus_widget_and_navigate(window: QWidget, item_id: str | None = None, field_path: str | None = None) bool[source]

Focus/navigate the registered scope that owns a concrete Qt window.

classmethod register(scope_id: str, window: QWidget, navigation_driver: WindowNavigationDriver | None = None, code_document_driver: WindowCodeDocumentDriver | None = None) None[source]

Register a window for singleton tracking.

Used by windows that manage their own show() behavior (e.g., BaseFormDialog). The window is responsible for calling this from its show() method.

IMPORTANT: The window must call unregister() in its closeEvent to allow reopening. BaseFormDialog does this automatically.

Parameters:
  • scope_id – Unique identifier for the window

  • window – The window to register

Example

class MyWindow(QDialog):
def show(self):

scope_key = f”{self.scope_id}::{self.__class__.__name__}” if WindowManager.is_open(scope_key):

WindowManager.focus_and_navigate(scope_key) return # Don’t show duplicate

WindowManager.register(scope_key, self) super().show()

def closeEvent(self, event):

WindowManager.unregister(scope_key) super().closeEvent(event)

classmethod unregister(scope_id: str) None[source]

Unregister a window from singleton tracking.

Called by windows in their closeEvent to allow reopening.

Parameters:

scope_id – Scope to unregister

classmethod require_code_document_driver(scope_id: str) WindowCodeDocumentDriver[source]

Return the code-document driver explicitly registered for a scope.

classmethod get_code_document_scopes() list[str][source]

Return open window scopes with registered code-document drivers.

classmethod is_open(scope_id: str) bool[source]

Check if window is currently open and visible for scope_id.

Parameters:

scope_id – Scope to check

Returns:

True if window exists, is valid, AND is visible, False otherwise

classmethod get_window(scope_id: str) QWidget | None[source]

Return the window instance for a scope_id if present.

Parameters:

scope_id – Scope to lookup

Returns:

Window instance or None if not registered

classmethod close_window(scope_id: str) bool[source]

Programmatically close window for scope_id.

Parameters:

scope_id – Scope to close

Returns:

True if window was found and closed, False otherwise

classmethod get_open_scopes() list[str][source]

Get list of all currently open window scopes.

Cleans up stale references as side effect.

Returns:

List of scope_ids for open windows