Window Manager Usage Guide
Overview
WindowManager provides singleton window management with navigation support for inheritance tracking.
Key features:
One window per
scope_id(prevents duplicates).Auto-cleanup on close (no manual unregistration).
Navigation API for focusing and scrolling to fields.
Fail-loud on stale references.
Basic Usage
Show or focus a window via a factory callback:
from pyqt_reactive.services.window_manager import WindowManager
# Define factory function that creates the window
def create_config_window():
return ConfigWindow(
config_class=PipelineConfig,
initial_config=current_config,
parent=self,
on_save_callback=self._on_config_saved,
scope_id="plate1",
)
# Show window (creates new or focuses existing)
window = WindowManager.show_or_focus("plate1", create_config_window)
Before/after behavior:
config_window = ConfigWindow(...)
config_window.show()
WindowManager.show_or_focus(scope_id, lambda: ConfigWindow(...))
Migration Examples
Future: Inheritance Tracking
Show the source window and scroll to it when the user clicks an inherited field:
class InheritanceTreeWidget(QTreeWidget):
"""Tree widget showing field inheritance."""
def on_field_clicked(self, field_path: str, source_scope: str):
"""User clicked field - show source window and scroll to it.
Args:
field_path: Field that was clicked
source_scope: Scope where field is defined (not inherited)
"""
from pyqt_reactive.services.window_manager import WindowManager
# Try to focus existing window and navigate
if WindowManager.focus_and_navigate(source_scope, field_path=field_path):
return # Window exists and navigated
# Window not open - create it and navigate
def create_window():
return ConfigWindow(
config_class=self._get_config_class(source_scope),
initial_config=self._get_config(source_scope),
scope_id=source_scope,
)
window = WindowManager.show_or_focus(source_scope, create_window)
# Navigate after window is shown (give Qt time to render)
QTimer.singleShot(100, lambda: window.select_and_scroll_to_field(field_path))
Utility Methods
# Check if window is open
if WindowManager.is_open("plate1"):
print("Config window already open for plate1")
# Get all open window scopes
open_scopes = WindowManager.get_open_scopes()
print(f"Open windows: {open_scopes}")
# Programmatically close window
WindowManager.close_window("plate1")
Architecture Notes
Auto-cleanup
Windows are automatically unregistered when closed (no manual cleanup needed):
# WindowManager hooks into closeEvent
window.closeEvent = lambda event: (
unregister_from_registry(),
call_original_closeEvent(event),
)
Fail-Loud on Stale References
If a window is deleted but still in the registry, a RuntimeError is raised and the stale reference is cleaned up:
try:
window.isVisible() # Test if still valid
except RuntimeError:
# Window deleted - clean up stale reference
del WindowManager._scoped_windows[scope_id]
Benefits
Prevents duplicate windows: only one config window per plate.
Better UX: focusing brings existing window to front.
Auto-cleanup: no memory leaks from forgotten references.
Extensible: navigation API ready for inheritance tracking.
Fail-loud: catches deleted windows early.
Fits pyqt-reactive patterns: similar to
ObjectStateRegistryfor states.