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
Schedule bounded navigation retries while forms/lists finish building. |
|
|
|
|
|
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]
-
- status: WindowLookupStatus
- __init__(scope_id: str, status: WindowLookupStatus, window: QWidget | None = None) None
Schedule bounded navigation retries while forms/lists finish building.
- 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”
)
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
)
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