API Reference

This section contains the complete API documentation for pyqt-reactive.

Core Modules

pyqt_reactive.core

Core PyQt6 utilities.

pyqt_reactive.protocols

Widget protocol definitions and adapters.

pyqt_reactive.services

Service package for pyqt-reactive.

pyqt_reactive.forms

Form generation and management package.

pyqt_reactive.widgets

Extended widget implementations.

pyqt_reactive.theming

Theming and styling system.

pyqt_reactive.windows

pyqt_reactive.dialogs

Reusable dialogs for PyQt FormGen.

Module Documentation

pyqt_reactive.core

Core PyQt6 utilities with zero external dependencies.

Core PyQt6 utilities.

Pure PyQt6 utility components with zero external dependencies. Foundational widgets and helpers with no domain-specific logic.

class pyqt_reactive.core.DebounceTimer(delay_ms: int, handler: Callable[[], None])[source]

Bases: object

Reusable trailing debounce timer.

Restarts timer on each call. Handler fires only after delay_ms of inactivity.

Usage:

self._debounce = DebounceTimer(delay_ms=200, handler=self._do_update)

def on_text_changed(self):

self._debounce.trigger() # Restarts timer

__init__(delay_ms: int, handler: Callable[[], None])[source]
trigger()[source]

Trigger debounce — restarts timer.

cancel()[source]

Cancel pending trigger.

force()[source]

Cancel timer and fire handler immediately.

class pyqt_reactive.core.ReorderableListWidget(parent=None)[source]

Bases: QListWidget

Custom QListWidget that properly handles drag and drop reordering.

Emits a signal when items are moved so the parent can update the data model. This is a shared implementation used by both PipelineEditor and PlateManager.

items_reordered

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

__init__(parent=None)[source]

Initialize reorderable list widget.

Parameters:

parent – Parent widget

dropEvent(event)[source]

Handle drop event and emit signal with indices.

class pyqt_reactive.core.BackgroundTask(target: Callable[[...], Any], args: Tuple = (), kwargs: dict = None, debounce_ms: int = 0, parent=None)[source]

Bases: QThread

Unified background task with cancellation, debounce, and cleanup.

Usage:

task = BackgroundTask(target=my_func, args=(a, b)) task.result_ready.connect(on_success) task.error_occurred.connect(on_error) # Receives Exception, not str task.start()

# Later: task.cancel() # Safe cancellation

Error handling:
def on_error(e: Exception):

logger.exception(“Failed”, exc_info=e) # Full traceback show_message(str(e)) # User-friendly string if isinstance(e, TimeoutError): … # Type checking

result_ready

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

error_occurred

int = …, arguments: Sequence = …) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal’s arguments.

Type:

pyqtSignal(*types, name

Type:

str = …, revision

__init__(target: Callable[[...], Any], args: Tuple = (), kwargs: dict = None, debounce_ms: int = 0, parent=None)[source]
run()[source]

Execute target in background, respecting cancellation.

cancel()[source]

Cancel task — signals won’t emit after this.

class pyqt_reactive.core.BackgroundTaskManager[source]

Bases: object

Manages background task lifecycle for a widget.

Handles: - Cancelling previous task before starting new one - Cleanup on widget close - Debounce across rapid calls - Button state management (disable during operation, auto-restore)

Usage in widget:

self._task_manager = BackgroundTaskManager()

def refresh_data(self):
self._task_manager.run(

target=self.service.fetch_data, args=(self.query,), button=self.refresh_button, button_loading_text=”Loading…”, on_success=self._on_data_ready, on_error=self._on_error, debounce_ms=200

)

def closeEvent(self, event):

self._task_manager.cleanup() super().closeEvent(event)

__init__()[source]
run(target: Callable[[...], Any], args: Tuple = (), kwargs: dict = None, on_success: Callable[[Any], None] = None, on_error: Callable[[Exception], None] = None, debounce_ms: int = 0, button: QPushButton = None, button_loading_text: str = None) BackgroundTask | None[source]

Run a background task, cancelling any previous one.

Parameters:
  • target – Function to execute in background

  • args – Positional arguments for target

  • kwargs – Keyword arguments for target

  • on_success – Callback for successful result

  • on_error – Callback for error (receives Exception, not str)

  • debounce_ms – Minimum time between runs (skip if too soon)

  • button – Button to disable during operation (auto-restored on complete)

  • button_loading_text – Text while loading (default: original + “…”)

Returns:

BackgroundTask if started, None if debounced out

cleanup()[source]

Cancel and wait for current task. Call from closeEvent.

class pyqt_reactive.core.CollapsibleSplitterHelper(splitter: QSplitter, left_panel_index: int = 0)[source]

Bases: object

Helper for adding double-click toggle to splitter handles.

__init__(splitter: QSplitter, left_panel_index: int = 0)[source]

Initialize the collapsible splitter helper.

Parameters:
  • splitter – The QSplitter to make collapsible

  • left_panel_index – Index of the left panel (default 0)

toggle_visibility()[source]

Toggle left panel visibility by collapsing/expanding.

set_initial_size(size: int)[source]

Set the initial size to remember when collapsed.

class pyqt_reactive.core.RichTextAppender(text_edit: QTextEdit, color_scheme: ColorScheme = None)[source]

Bases: object

Utility for appending HTML content to QTextEdit with proper cursor/scroll handling.

Usage:

appender = RichTextAppender(self.chat_history, color_scheme=self.color_scheme) appender.append_html(“<b>User:</b> Hello”) appender.append_code(“def foo(): pass”) appender.append_error(“Something went wrong”)

__init__(text_edit: QTextEdit, color_scheme: ColorScheme = None)[source]
append_html(html_content: str, add_spacing: bool = True)[source]

Append HTML content at end, scroll to bottom.

Parameters:
  • html_content – HTML string to append

  • add_spacing – Whether to add blank line after

append_text(text: str, bold: bool = False, color: str | None = None)[source]

Append plain text (escaped) with optional styling.

Parameters:
  • text – Plain text to append

  • bold – Whether to make text bold

  • color – Optional text color (hex)

append_code(code: str, language: str = None)[source]

Append code block with border styling.

Parameters:
  • code – Code string to display

  • language – Optional language hint (for future syntax highlighting)

append_error(message: str)[source]

Append error message in red.

append_success(message: str)[source]

Append success message in green.

clear()[source]

Clear all content.

pyqt_reactive.protocols

Widget protocol definitions and adapters for type-safe widget contracts.

Widget protocol definitions and adapters.

ABC-based widget contracts that eliminate duck typing in favor of explicit, fail-loud inheritance-based architecture.

class pyqt_reactive.protocols.ValueGettable[source]

Bases: ABC

ABC for widgets that can return a value.

All input widgets must implement this to participate in form value extraction.

abstractmethod get_value() Any[source]

Get the current value from the widget.

Returns:

The widget’s current value. None if no value set.

class pyqt_reactive.protocols.ValueSettable[source]

Bases: ABC

ABC for widgets that can accept a value.

All input widgets must implement this to participate in form value updates.

abstractmethod set_value(value: Any) None[source]

Set the widget’s value.

Parameters:

value – The value to set. None clears the widget.

class pyqt_reactive.protocols.ResolvedValuePreviewSettable[source]

Bases: ABC

ABC for widgets that render inherited/resolved values separately from raw edits.

Lazy dataclass container widgets may keep raw None child fields while previewing the resolved inherited dataclass. This contract lets form chrome refresh that preview without replacing the raw editable value.

abstractmethod set_resolved_value_preview(value: Any) None[source]

Set the resolved value used for display/preview only.

Parameters:

value – Resolved value for the same logical field.

class pyqt_reactive.protocols.RawResolvedValueSettable[source]

Bases: ABC

ABC for widgets that can atomically apply a raw value and resolved preview.

Lazy dataclass widgets can avoid rendering a raw intermediate state when a form refresh already has both ObjectState values available.

abstractmethod set_raw_value_with_resolved_preview(raw_value: Any, resolved_value: Any) None[source]

Set the editable raw value and resolved display preview in one pass.

Parameters:
  • raw_value – Raw ObjectState value for editing.

  • resolved_value – Resolved ObjectState value for inherited preview.

class pyqt_reactive.protocols.ChildFieldChromeRefreshable[source]

Bases: ABC

ABC for compound widgets that render chrome for their own child fields.

Inline dataclass widgets can own section labels/reset controls internally while still being edited as one form value. This contract lets the form manager refresh those child markers after ObjectState dirty/signature state changes without knowing widget-specific field names.

abstractmethod refresh_child_field_chrome(owner_field_paths: tuple['DottedFieldPath', ...] | None = None) None[source]

Refresh dirty/signature/reset chrome for child fields.

class pyqt_reactive.protocols.ChildFieldSemanticChromeRefreshable[source]

Bases: ABC

ABC for compound widgets that render semantic chrome for child leaves.

abstractmethod child_field_semantic_owner_paths() tuple['DottedFieldPath', ...][source]

Return ObjectState owner paths for structural child semantics.

abstractmethod refresh_child_field_semantics(owner_field_path: DottedFieldPath, semantic_index: ObjectStateSubfieldSemanticIndex) None[source]

Refresh dirty/default/inherited chrome for an ObjectState owner field.

class pyqt_reactive.protocols.ChildFieldIdentityProvider[source]

Bases: ABC

ABC for compound widgets that expose nominal child ObjectState identity.

abstractmethod child_field_identity(field_name: str) InlineDataclassChildFieldIdentity[source]

Return the nominal identity for one direct child field.

class pyqt_reactive.protocols.ChildFieldNavigationTargetProvider[source]

Bases: ABC

ABC for compound widgets that expose concrete widgets for child fields.

Inline dataclass widgets may render their own child sections internally instead of creating nested ParameterFormManager instances. This contract lets generic form navigation scroll to the concrete child section while keeping the widget-specific layout private to the inline editor.

abstractmethod child_field_navigation_target(field_name: str) QWidget | None[source]

Return the widget that visually represents a child field, if present.

Parameters:

field_name – Direct child field name inside the compound widget.

class pyqt_reactive.protocols.ChildSubfieldNavigationTargetProvider[source]

Bases: ABC

ABC for compound widgets that expose structural descendant targets.

abstractmethod child_subfield_navigation_target(child_identity: InlineDataclassChildFieldIdentity, relative_path: StructuralValuePath) StructuralFlashTarget | None[source]

Return a concrete visual target for a child structural path.

An empty relative_path represents the child structural owner itself.

class pyqt_reactive.protocols.InlineDataclassGroupBoxChromeProvider[source]

Bases: ABC

ABC for inline dataclass value widgets that contribute container title chrome.

Regular nested dataclasses can move child widgets such as enableable checkboxes into the groupbox title row. Inline dataclass widgets do not have a nested ParameterFormManager, so they expose the same chrome through this contract while the container remains generic.

abstractmethod configure_inline_dataclass_groupbox(groupbox: Any) None[source]

Attach any inline title chrome to the owning groupbox.

Parameters:

groupbox – The InlineDataclassGroupBox hosting this value widget.

class pyqt_reactive.protocols.InlineDataclassRootResettable[source]

Bases: ABC

ABC for inline dataclass widgets that can reset their child fields.

abstractmethod reset_inline_dataclass_fields() None[source]

Reset the inline dataclass child fields to their signature defaults.

class pyqt_reactive.protocols.PlaceholderCapable[source]

Bases: ABC

ABC for widgets that can display placeholder text.

Placeholders show inherited/default values without setting actual values.

abstractmethod set_placeholder(text: str) None[source]

Set placeholder text for the widget.

Parameters:

text – Placeholder text to display (e.g., “Pipeline default: 42”)

class pyqt_reactive.protocols.PlaceholderStateTrackable[source]

Bases: WidgetCapabilityTagged

ABC for widgets that own placeholder chrome/cache state.

widget_capabilities: ClassVar[frozenset[WidgetCapability]] = frozenset({WidgetCapability.PLACEHOLDER_STATE})
abstractmethod has_placeholder_state() bool[source]

Return whether placeholder chrome or cached placeholder data is present.

abstractmethod mark_placeholder_state() None[source]

Mark the widget as currently displaying placeholder chrome.

abstractmethod clear_placeholder_state() None[source]

Mark the widget as no longer displaying placeholder chrome.

abstractmethod cached_placeholder_text() str | None[source]

Return cached placeholder text, if any.

abstractmethod set_cached_placeholder_text(placeholder_text: str) None[source]

Cache placeholder text after a successful render.

abstractmethod cached_placeholder_resolved_value() Any[source]

Return cached placeholder resolved value, if any.

abstractmethod set_cached_placeholder_resolved_value(value: Any) None[source]

Cache the resolved value after a successful preview render.

abstractmethod clear_placeholder_cache() None[source]

Clear cached placeholder text and resolved value.

class pyqt_reactive.protocols.WidgetCapability(*values)[source]

Bases: str, Enum

Nominal widget capability tags for generic service-level queries.

PLACEHOLDER_STATE = 'placeholder_state'
class pyqt_reactive.protocols.WidgetCapabilityTagged[source]

Bases: ABC

Base for widget contracts that advertise generic capability tags.

widget_capabilities: ClassVar[frozenset[WidgetCapability]] = frozenset({})
pyqt_reactive.protocols.widget_capability_tags(widget_or_type: Any) frozenset[WidgetCapability][source]

Return all capability tags declared by a widget class and its bases.

pyqt_reactive.protocols.widget_supports_capability(widget_or_type: Any, capability: WidgetCapability) bool[source]

Return whether a widget class declares a nominal capability tag.

class pyqt_reactive.protocols.RangeConfigurable[source]

Bases: ABC

ABC for widgets that support numeric range configuration.

Typically implemented by numeric input widgets (spinboxes, sliders).

abstractmethod configure_range(minimum: float, maximum: float) None[source]

Configure the valid range for numeric input.

Parameters:
  • minimum – Minimum allowed value

  • maximum – Maximum allowed value

class pyqt_reactive.protocols.EnumSelectable[source]

Bases: ABC

ABC for widgets that can select from enum values.

Typically implemented by dropdowns and radio button groups.

abstractmethod set_enum_options(enum_type: type) None[source]

Configure widget with enum options.

Parameters:

enum_type – The Enum class to populate options from

abstractmethod get_selected_enum() Any[source]

Get the currently selected enum value.

Returns:

The selected enum member, or None if no selection

class pyqt_reactive.protocols.ChangeSignalEmitter[source]

Bases: ABC

ABC for widgets that emit change signals.

Provides explicit contract for signal connection, eliminating duck typing of signal names (textChanged vs valueChanged vs currentIndexChanged).

abstractmethod connect_change_signal(callback: Callable[[Any], None]) None[source]

Connect callback to widget’s change signal.

The callback will be invoked whenever the widget’s value changes, receiving the new value as its argument.

Parameters:

callback – Function to call when widget value changes. Signature: callback(new_value: Any) -> None

abstractmethod disconnect_change_signal(callback: Callable[[Any], None]) None[source]

Disconnect callback from widget’s change signal.

Parameters:

callback – The callback function to disconnect

class pyqt_reactive.protocols.LineEditAdapter(*args, **kwargs)[source]

Bases: PlaceholderStateMixin, QLineEdit, ValueGettable, ValueSettable, PlaceholderCapable, ChangeSignalEmitter

Adapter for QLineEdit implementing OpenHCS ABCs.

Normalizes Qt API to OpenHCS contracts: - .text() → .get_value() - .setText() → .set_value() - .setPlaceholderText() → .set_placeholder() - .textChanged → .connect_change_signal()

get_value() Any[source]

Implement ValueGettable ABC.

set_value(value: Any) None[source]

Implement ValueSettable ABC.

set_placeholder(text: str) None[source]

Implement PlaceholderCapable ABC.

connect_change_signal(callback: Callable[[Any], None]) None[source]

Implement ChangeSignalEmitter ABC.

disconnect_change_signal(callback: Callable[[Any], None]) None[source]

Implement ChangeSignalEmitter ABC.

class pyqt_reactive.protocols.SpinBoxAdapter(parent=None)[source]

Bases: PlaceholderStateMixin, QSpinBox, ValueGettable, ValueSettable, PlaceholderCapable, RangeConfigurable, ChangeSignalEmitter

Adapter for QSpinBox implementing OpenHCS ABCs.

Handles None values using special value text mechanism. When value is None, displays placeholder text at minimum value.

__init__(parent=None)[source]
get_value() Any[source]

Implement ValueGettable ABC.

set_value(value: Any) None[source]

Implement ValueSettable ABC.

set_placeholder(text: str) None[source]

Implement PlaceholderCapable ABC.

configure_range(minimum: float, maximum: float) None[source]

Implement RangeConfigurable ABC.

connect_change_signal(callback: Callable[[Any], None]) None[source]

Implement ChangeSignalEmitter ABC.

disconnect_change_signal(callback: Callable[[Any], None]) None[source]

Implement ChangeSignalEmitter ABC.

class pyqt_reactive.protocols.DoubleSpinBoxAdapter(parent=None)[source]

Bases: PlaceholderStateMixin, QDoubleSpinBox, ValueGettable, ValueSettable, PlaceholderCapable, RangeConfigurable, ChangeSignalEmitter

Adapter for QDoubleSpinBox implementing OpenHCS ABCs.

Handles None values and floating-point ranges.

__init__(parent=None)[source]
get_value() Any[source]

Implement ValueGettable ABC.

set_value(value: Any) None[source]

Implement ValueSettable ABC.

set_placeholder(text: str) None[source]

Implement PlaceholderCapable ABC.

configure_range(minimum: float, maximum: float) None[source]

Implement RangeConfigurable ABC.

connect_change_signal(callback: Callable[[Any], None]) None[source]

Implement ChangeSignalEmitter ABC.

disconnect_change_signal(callback: Callable[[Any], None]) None[source]

Implement ChangeSignalEmitter ABC.

class pyqt_reactive.protocols.ComboBoxAdapter(*args, **kwargs)[source]

Bases: PlaceholderStateMixin, QComboBox, ValueGettable, ValueSettable, PlaceholderCapable, ChangeSignalEmitter

Adapter for QComboBox implementing OpenHCS ABCs.

Stores actual values in itemData, not just display text. Supports enum population and selection.

get_value() Any[source]

Implement ValueGettable ABC.

set_value(value: Any) None[source]

Implement ValueSettable ABC.

set_placeholder(text: str) None[source]

Implement PlaceholderCapable ABC.

populate_enum(enum_type: type) None[source]

Populate combobox with enum values.

Parameters:

enum_type – The Enum class to populate from

connect_change_signal(callback: Callable[[Any], None]) None[source]

Implement ChangeSignalEmitter ABC.

disconnect_change_signal(callback: Callable[[Any], None]) None[source]

Implement ChangeSignalEmitter ABC.

class pyqt_reactive.protocols.CheckBoxAdapter(*args, **kwargs)[source]

Bases: PlaceholderStateMixin, QCheckBox, ValueGettable, ValueSettable, ChangeSignalEmitter

Adapter for QCheckBox implementing OpenHCS ABCs.

Returns bool values, treats None as False.

get_value() Any[source]

Implement ValueGettable ABC.

set_value(value: Any) None[source]

Implement ValueSettable ABC.

connect_change_signal(callback: Callable[[Any], None]) None[source]

Implement ChangeSignalEmitter ABC.

disconnect_change_signal(callback: Callable[[Any], None]) None[source]

Implement ChangeSignalEmitter ABC.

class pyqt_reactive.protocols.PlaceholderStateMixin(*args, **kwargs)[source]

Bases: PlaceholderStateTrackable

Nominal placeholder-state storage for Qt widget adapters.

widget_capabilities: ClassVar[frozenset[WidgetCapability]] = frozenset({WidgetCapability.PLACEHOLDER_STATE})
__init__(*args, **kwargs)[source]
has_placeholder_state() bool[source]

Return whether placeholder chrome or cached placeholder data is present.

mark_placeholder_state() None[source]

Mark the widget as currently displaying placeholder chrome.

clear_placeholder_state() None[source]

Mark the widget as no longer displaying placeholder chrome.

cached_placeholder_text() str | None[source]

Return cached placeholder text, if any.

set_cached_placeholder_text(placeholder_text: str) None[source]

Cache placeholder text after a successful render.

cached_placeholder_resolved_value() Any[source]

Return cached placeholder resolved value, if any.

set_cached_placeholder_resolved_value(value: Any) None[source]

Cache the resolved value after a successful preview render.

clear_placeholder_cache() None[source]

Clear cached placeholder text and resolved value.

class pyqt_reactive.protocols.PyQtWidgetMeta(name, bases, namespace, /, **kwargs)[source]

Bases: wrappertype, ABCMeta

Metaclass for PyQt widgets that need ABC support.

class pyqt_reactive.protocols.FunctionRegistryProtocol(*args, **kwargs)[source]

Bases: Protocol

Protocol for function registries that provide function lookup and metadata.

Applications can implement this protocol to provide their own function registry.

Example

from pyqt_reactive.protocols import register_function_registry from myapp.registry import MyFunctionRegistry

register_function_registry(MyFunctionRegistry())

get_function_by_name(name: str) Callable | None[source]

Get function by name.

Parameters:

name – Function name to lookup

Returns:

Function callable if found, None otherwise

get_all_functions() Dict[str, Callable][source]

Get all registered functions.

Returns:

Dictionary mapping function names to callables

get_function_metadata(name: str) Dict[str, Any] | None[source]

Get metadata for a function.

Parameters:

name – Function name

Returns:

Metadata dict if available, None otherwise

__init__(*args, **kwargs)
pyqt_reactive.protocols.register_function_registry(registry: FunctionRegistryProtocol) None[source]

Register a function registry implementation.

Parameters:

registry – Object implementing FunctionRegistryProtocol

pyqt_reactive.protocols.get_function_registry() FunctionRegistryProtocol | None[source]

Get the registered function registry.

Returns:

Registered registry or None if not registered

class pyqt_reactive.protocols.PreviewFormatterRegistry[source]

Bases: object

Registry for preview formatters by config type.

Applications can register formatters for specific config types to customize how fields are displayed in list item previews.

Example

from pyqt_reactive.protocols import PreviewFormatterRegistry

def format_zarr_config(config, field_name):
if field_name == ‘compression’:

return f”comp={config.compression[:3]}” # Abbreviate

return str(getattr(config, field_name))

PreviewFormatterRegistry.register(ZarrConfig, format_zarr_config)

classmethod register(config_type: Type, formatter: Callable[[Any, str], str]) None[source]

Register a formatter for a config type.

Parameters:
  • config_type – Config class to format

  • formatter – Formatter function taking (config, field_name) -> str

classmethod get_formatter(config_type: Type) Callable[[Any, str], str] | None[source]

Get formatter for a config type.

Parameters:

config_type – Config class

Returns:

Formatter function if registered, None otherwise

classmethod format_field(config: Any, field_name: str) str | None[source]

Format a field using registered formatter if available.

Parameters:
  • config – Config instance

  • field_name – Field name to format

Returns:

Formatted string if formatter available, None otherwise

pyqt_reactive.protocols.register_preview_formatter(config_type: Type, formatter: Callable[[Any, str], str]) None[source]

Register a preview formatter for a config type.

Parameters:
  • config_type – Config class

  • formatter – Formatter function

class pyqt_reactive.protocols.FormGenConfig(enable_placeholder_styling: bool = True, enable_help_buttons: bool = True, enable_inheritance_tracking: bool = True, custom_widget_factories: Type, ~typing.Any]=<factory>, jedi_project_paths: List[str] = <factory>, log_dir: str | None = None, log_prefixes: List[str] = <factory>, log_root_logger_name: str | None = None, performance_logger_name: str = 'pyqt_reactive.performance', performance_log_filename: str = 'performance.log', path_cache_file: str | None = None)[source]

Bases: object

Base configuration for form generation behavior.

Applications can subclass this to provide custom configuration.

enable_placeholder_styling

Whether to apply special styling to placeholder values

Type:

bool

enable_help_buttons

Whether to show help buttons for fields with docstrings

Type:

bool

enable_inheritance_tracking

Whether to show inheritance source indicators

Type:

bool

custom_widget_factories

Custom widget factories by type

Type:

Dict[Type, Any]

enable_placeholder_styling: bool = True
enable_help_buttons: bool = True
enable_inheritance_tracking: bool = True
custom_widget_factories: Dict[Type, Any]
jedi_project_paths: List[str]
log_dir: str | None = None
log_prefixes: List[str]
log_root_logger_name: str | None = None
performance_logger_name: str = 'pyqt_reactive.performance'
performance_log_filename: str = 'performance.log'
path_cache_file: str | None = None
__init__(enable_placeholder_styling: bool = True, enable_help_buttons: bool = True, enable_inheritance_tracking: bool = True, custom_widget_factories: Type, ~typing.Any]=<factory>, jedi_project_paths: List[str] = <factory>, log_dir: str | None = None, log_prefixes: List[str] = <factory>, log_root_logger_name: str | None = None, performance_logger_name: str = 'pyqt_reactive.performance', performance_log_filename: str = 'performance.log', path_cache_file: str | None = None) None
pyqt_reactive.protocols.set_form_config(config: FormGenConfig) None[source]

Set the global form generation configuration.

Parameters:

config – FormGenConfig instance

pyqt_reactive.protocols.get_form_config() FormGenConfig[source]

Get the current form generation configuration.

Returns:

Current FormGenConfig or default if not set

class pyqt_reactive.protocols.LLMServiceProtocol(*args, **kwargs)[source]

Bases: Protocol

Protocol for LLM services used by LLMChatPanel.

api_endpoint: str
model: str | None
test_connection() Tuple[bool, str][source]

Return (is_connected, status_message).

generate_code(request: str, code_type: str | None = None) str[source]

Generate code for a request and optional code type.

__init__(*args, **kwargs)
pyqt_reactive.protocols.register_llm_service(service: LLMServiceProtocol) None[source]

Register a global LLM service implementation.

pyqt_reactive.protocols.get_llm_service() LLMServiceProtocol | None[source]

Get the registered LLM service implementation.

class pyqt_reactive.protocols.CodegenProvider(*args, **kwargs)[source]

Bases: Protocol

Protocol for code generators used by the simple code editor.

generate_complete_orchestrator_code(plate_paths: list[str], pipeline_data: dict, global_config: Any | None = None, per_plate_configs: dict | None = None, pipeline_config: Any | None = None, clean_mode: bool = True) str[source]
generate_complete_pipeline_steps_code(pipeline_steps: list[Any], clean_mode: bool = True) str[source]
generate_complete_function_pattern_code(func_obj: Any, clean_mode: bool = False) str[source]
generate_config_code(config_obj: Any, clean_mode: bool = True, config_class: type | None = None) str[source]
generate_step_code(step_obj: Any, clean_mode: bool = True) str[source]
__init__(*args, **kwargs)
pyqt_reactive.protocols.register_codegen_provider(provider: CodegenProvider) None[source]

Register a global code generation provider.

pyqt_reactive.protocols.get_codegen_provider() CodegenProvider | None[source]

Get the registered code generation provider.

class pyqt_reactive.protocols.LogDiscoveryProvider(*args, **kwargs)[source]

Bases: Protocol

Protocol for discovering log files and current log path.

get_current_log_path() Path[source]

Return current log file path.

discover_logs(base_log_path: str | None = None, include_main_log: bool = True, log_directory: Path | None = None) List[LogFileInfo][source]

Return discovered logs.

__init__(*args, **kwargs)
class pyqt_reactive.protocols.ServerScanProvider(*args, **kwargs)[source]

Bases: Protocol

Protocol for discovering server logs (e.g., via port scans).

scan_for_server_logs() List[LogFileInfo][source]

Return logs discovered from live servers.

__init__(*args, **kwargs)
pyqt_reactive.protocols.register_log_discovery_provider(provider: LogDiscoveryProvider) None[source]

Register a global log discovery provider.

pyqt_reactive.protocols.get_log_discovery_provider() LogDiscoveryProvider | None[source]

Get the registered log discovery provider.

pyqt_reactive.protocols.register_server_scan_provider(provider: ServerScanProvider) None[source]

Register a global server scan provider.

pyqt_reactive.protocols.get_server_scan_provider() ServerScanProvider | None[source]

Get the registered server scan provider.

class pyqt_reactive.protocols.WindowFactoryProtocol(*args, **kwargs)[source]

Bases: Protocol

Protocol for creating windows for a given scope.

Use this for duck-typed checking. For implementation, prefer WindowFactoryABC.

create_window_for_scope(scope_id: str, object_state: ObjectState | None = None) QWidget | None[source]

Create and show a window for the given scope id.

__init__(*args, **kwargs)
class pyqt_reactive.protocols.WindowFactoryABC[source]

Bases: ABC

Abstract base class for window factories.

Subclass this to implement application-specific window creation logic. The factory is responsible for: - Parsing scope_id format to determine window type - Creating the appropriate window class - Showing and activating the window

abstractmethod create_window_for_scope(scope_id: str, object_state: ObjectState | None = None) QWidget | None[source]

Create and show a window for the given scope_id.

Parameters:
  • scope_id – Scope identifier. Format is application-specific, e.g.: - “” (empty string): Global config - “/path/to/item”: Item-level config - “/path/to/item::sub”: Nested scope

  • object_state – Optional ObjectState for time-travel restore

Returns:

The created window, or None if creation failed/skipped

pyqt_reactive.protocols.register_window_factory(factory: WindowFactoryProtocol) None[source]

Register a global window factory.

Parameters:

factory – Factory instance implementing WindowFactoryProtocol or WindowFactoryABC

pyqt_reactive.protocols.get_window_factory() WindowFactoryProtocol | None[source]

Get the registered window factory.

class pyqt_reactive.protocols.ComponentSelectionProvider(*args, **kwargs)[source]

Bases: Protocol

Protocol for component selection and display metadata.

get_groupby_enum() Any[source]

Return the GroupBy enum (or compatible enum) used by the host app.

get_component_keys(group_by: Any) List[str][source]

Return available component keys for a given group_by.

has_components_available(group_by: Any) bool[source]

Check if components are available for the given group_by without fetching them all.

Used to determine if UI elements (like component selection buttons) should be enabled. Should return False if the underlying data source (e.g., orchestrator) is not ready.

get_component_display_name(group_by: Any, component_key: str) str | None[source]

Return a human-readable name for a component key.

select_components(available_components: Iterable[str], selected_components: Iterable[str], group_by: Any, parent: Any | None = None, **context: Any) List[str] | None[source]

Show selection UI and return chosen components (or None if canceled).

__init__(*args, **kwargs)
class pyqt_reactive.protocols.FunctionSelectionProvider(*args, **kwargs)[source]

Bases: Protocol

Protocol for selecting a function in UI.

select_function(parent: Any | None = None, **context: Any) Callable | None[source]

Return a selected function or None.

__init__(*args, **kwargs)
pyqt_reactive.protocols.register_component_selection_provider(provider: ComponentSelectionProvider) None[source]

Register a global component selection provider.

pyqt_reactive.protocols.get_component_selection_provider() ComponentSelectionProvider | None[source]

Get the registered component selection provider.

pyqt_reactive.protocols.register_function_selection_provider(provider: FunctionSelectionProvider) None[source]

Register a global function selection provider.

pyqt_reactive.protocols.get_function_selection_provider() FunctionSelectionProvider | None[source]

Get the registered function selection provider.

pyqt_reactive.services

Service layer for form management and cross-cutting concerns.

Service package for pyqt-reactive.

Import service APIs from their owning submodules. Keeping this package initializer side-effect free prevents service/form import cycles.

pyqt_reactive.forms

Form generation and management from dataclasses.

Form generation and management package.

Import concrete form APIs from their owning submodules. Keeping this package initializer side-effect free prevents form/service import cycles.

pyqt_reactive.widgets

Extended widget implementations with enhanced behavior.

Extended widget implementations.

Specialized widget subclasses that build on the protocol layer with enhanced behavior.

class pyqt_reactive.widgets.NoScrollSpinBox(parent=None)[source]

Bases: IgnoreWheelEventMixin, SpinBoxAdapter

SpinBox that ignores wheel events to prevent accidental value changes.

Inherits from SpinBoxAdapter which already implements ValueGettable/ValueSettable ABCs.

class pyqt_reactive.widgets.NoScrollDoubleSpinBox(parent=None)[source]

Bases: IgnoreWheelEventMixin, DoubleSpinBoxAdapter

DoubleSpinBox that ignores wheel events to prevent accidental value changes.

Inherits from DoubleSpinBoxAdapter which already implements ValueGettable/ValueSettable ABCs.

textFromValue(value: float) str[source]

Convert value to string without trailing zeros for clean display.

Users can still type additional digits when editing - this only affects the display format, not the underlying precision.

Examples

1.5 -> “1.5” 1.0 -> “1” 1.567 -> “1.567” 0.0001 -> “0.0001”

class pyqt_reactive.widgets.NoScrollComboBox(parent=None, placeholder='')[source]

Bases: IgnoreWheelEventMixin, ComboBoxAdapter

ComboBox that ignores wheel events to prevent accidental value changes.

Inherits from ComboBoxAdapter which already implements ValueGettable/ValueSettable ABCs. Supports placeholder text when currentIndex == -1 (for None values).

__init__(parent=None, placeholder='')[source]
setPlaceholder(text: str)[source]

Set the placeholder text shown when currentIndex == -1.

setCurrentIndex(index: int)[source]

Override to track when placeholder should be active.

get_value()[source]

Get current value (item data at current index).

set_value(value)[source]

Set current value by finding matching item data.

paintEvent(event)[source]

Override to draw placeholder text when currentIndex == -1.

class pyqt_reactive.widgets.NoneAwareCheckBox(parent=None)[source]

Bases: PlaceholderStateMixin, QCheckBox, ValueGettable, ValueSettable, ResolvedValuePreviewSettable, ChangeSignalEmitter

QCheckBox that supports None state for lazy dataclass contexts.

Shows inherited value as grayed placeholder when value is None. Clicking converts placeholder to explicit value.

PLACEHOLDER_PAINT_OPACITY = 0.45
__init__(parent=None)[source]
get_value()[source]

Get value, returning None if in placeholder state.

is_placeholder() bool[source]

Return whether the checkbox is currently displaying inherited state.

set_value(value)[source]

Set value, handling None by leaving in placeholder state.

connect_change_signal(callback: Callable[[bool | None], None]) None[source]

Implement ChangeSignalEmitter ABC.

disconnect_change_signal(callback: Callable[[bool | None], None]) None[source]

Implement ChangeSignalEmitter ABC.

set_placeholder_preview(checked: bool) None[source]

Display an inherited checkbox value without making it concrete.

set_resolved_value_preview(value) None[source]

Display an inherited resolved bool while preserving raw None.

convert_placeholder_to_concrete() None[source]

Keep the displayed value but mark it as a user-controlled value.

toggle() None[source]

Toggle as a user action, committing placeholder state first.

mousePressEvent(event)[source]

On click, switch from placeholder to explicit value.

paintEvent(event)[source]

Draw with placeholder styling.

For placeholder state, draw the checkbox with grey text color to make the checkmark appear dimmed.

class pyqt_reactive.widgets.StatusIndicator(check_fn: Callable[[], Tuple[bool, str]] = None, color_scheme: ColorScheme = None, show_refresh: bool = True, debounce_ms: int = 2000, parent=None)[source]

Bases: QWidget

Reusable status indicator with colored dot, label, and refresh button.

Usage:
indicator = StatusIndicator(

check_fn=lambda: my_service.test_connection(), color_scheme=self.color_scheme, parent=self

) layout.addWidget(indicator)

# check_fn returns Tuple[bool, str]: (is_ok, status_message) # True → CONNECTED state, False → DISCONNECTED state

__init__(check_fn: Callable[[], Tuple[bool, str]] = None, color_scheme: ColorScheme = None, show_refresh: bool = True, debounce_ms: int = 2000, parent=None)[source]
set_state(state: StatusState, message: str = None)[source]

Update visual state.

refresh(force: bool = False)[source]

Trigger async status check.

showEvent(event)[source]

Auto-refresh on show (no debounce for initial check).

closeEvent(event)[source]

Cleanup on close.

class pyqt_reactive.widgets.StatusState(*values)[source]

Bases: Enum

Status indicator states — colors resolved from color scheme at runtime.

UNKNOWN = 'Unknown'
CHECKING = 'Checking...'
CONNECTED = 'connected'
DISCONNECTED = 'disconnected'
WARNING = 'warning'
property default_message: str | None
pyqt_reactive.widgets.get_status_color(state: StatusState, color_scheme: ColorScheme) str[source]

Resolve status state to color from scheme.

pyqt_reactive.theming

Color schemes and styling system for dynamic theme switching.

Theming and styling system.

Color schemes, palette management, and stylesheet generation for consistent application-wide theming.

class pyqt_reactive.theming.ColorScheme(window_bg: Tuple[int, int, int] = (43, 43, 43), panel_bg: Tuple[int, int, int] = (30, 30, 30), frame_bg: Tuple[int, int, int] = (43, 43, 43), border_color: Tuple[int, int, int] = (85, 85, 85), border_light: Tuple[int, int, int] = (102, 102, 102), separator_color: Tuple[int, int, int] = (51, 51, 51), text_primary: Tuple[int, int, int] = (255, 255, 255), text_secondary: Tuple[int, int, int] = (204, 204, 204), text_accent: Tuple[int, int, int] = (0, 170, 255), text_disabled: Tuple[int, int, int] = (102, 102, 102), button_normal_bg: Tuple[int, int, int] = (64, 64, 64), button_hover_bg: Tuple[int, int, int] = (80, 80, 80), button_pressed_bg: Tuple[int, int, int] = (48, 48, 48), button_disabled_bg: Tuple[int, int, int] = (42, 42, 42), button_text: Tuple[int, int, int] = (255, 255, 255), button_disabled_text: Tuple[int, int, int] = (102, 102, 102), input_bg: Tuple[int, int, int] = (64, 64, 64), input_border: Tuple[int, int, int] = (102, 102, 102), input_text: Tuple[int, int, int] = (255, 255, 255), input_focus_border: Tuple[int, int, int] = (0, 170, 255), selection_bg: Tuple[int, int, int] = (0, 120, 212), selection_text: Tuple[int, int, int] = (255, 255, 255), hover_bg: Tuple[int, int, int] = (51, 51, 51), focus_outline: Tuple[int, int, int] = (0, 170, 255), search_highlight_bg: Tuple[int, int, int, int] = (255, 255, 0, 100), search_highlight_text: Tuple[int, int, int] = (0, 0, 0), status_success: Tuple[int, int, int] = (0, 255, 0), status_warning: Tuple[int, int, int] = (255, 170, 0), status_error: Tuple[int, int, int] = (255, 0, 0), status_info: Tuple[int, int, int] = (0, 170, 255), progress_bg: Tuple[int, int, int] = (30, 30, 30), progress_fill: Tuple[int, int, int] = (0, 120, 212), activity_indicator: Tuple[int, int, int] = (0, 170, 255), log_critical_fg: Tuple[int, int, int] = (255, 255, 255), log_critical_bg: Tuple[int, int, int] = (139, 0, 0), log_error_color: Tuple[int, int, int] = (255, 85, 85), log_warning_color: Tuple[int, int, int] = (255, 140, 0), log_info_color: Tuple[int, int, int] = (100, 160, 210), log_debug_color: Tuple[int, int, int] = (160, 160, 160), timestamp_color: Tuple[int, int, int] = (105, 105, 105), logger_name_color: Tuple[int, int, int] = (147, 112, 219), memory_address_color: Tuple[int, int, int] = (255, 182, 193), file_path_color: Tuple[int, int, int] = (34, 139, 34), python_keyword_color: Tuple[int, int, int] = (86, 156, 214), python_string_color: Tuple[int, int, int] = (206, 145, 120), python_number_color: Tuple[int, int, int] = (181, 206, 168), python_operator_color: Tuple[int, int, int] = (212, 212, 212), python_name_color: Tuple[int, int, int] = (156, 220, 254), python_function_color: Tuple[int, int, int] = (220, 220, 170), python_class_color: Tuple[int, int, int] = (78, 201, 176), python_builtin_color: Tuple[int, int, int] = (86, 156, 214), python_comment_color: Tuple[int, int, int] = (106, 153, 85), exception_color: Tuple[int, int, int] = (255, 69, 0), function_call_color: Tuple[int, int, int] = (255, 215, 0), boolean_color: Tuple[int, int, int] = (86, 156, 214), tuple_parentheses_color: Tuple[int, int, int] = (255, 215, 0), set_braces_color: Tuple[int, int, int] = (255, 140, 0), class_representation_color: Tuple[int, int, int] = (78, 201, 176), function_representation_color: Tuple[int, int, int] = (220, 220, 170), module_path_color: Tuple[int, int, int] = (147, 112, 219), hex_number_color: Tuple[int, int, int] = (181, 206, 168), scientific_notation_color: Tuple[int, int, int] = (181, 206, 168), binary_number_color: Tuple[int, int, int] = (181, 206, 168), octal_number_color: Tuple[int, int, int] = (181, 206, 168), python_special_color: Tuple[int, int, int] = (255, 20, 147), single_quoted_string_color: Tuple[int, int, int] = (206, 145, 120), list_comprehension_color: Tuple[int, int, int] = (156, 220, 254), generator_expression_color: Tuple[int, int, int] = (156, 220, 254))[source]

Bases: object

Comprehensive color scheme for OpenHCS PyQt6 GUI with semantic color names.

Extends the LogColorScheme pattern to cover all GUI components including windows, dialogs, widgets, and interactive elements. Supports light/dark theme variants and ensures WCAG accessibility compliance.

All colors meet minimum 4.5:1 contrast ratio for normal text readability.

window_bg: Tuple[int, int, int] = (43, 43, 43)
panel_bg: Tuple[int, int, int] = (30, 30, 30)
frame_bg: Tuple[int, int, int] = (43, 43, 43)
border_color: Tuple[int, int, int] = (85, 85, 85)
border_light: Tuple[int, int, int] = (102, 102, 102)
separator_color: Tuple[int, int, int] = (51, 51, 51)
text_primary: Tuple[int, int, int] = (255, 255, 255)
text_secondary: Tuple[int, int, int] = (204, 204, 204)
text_accent: Tuple[int, int, int] = (0, 170, 255)
text_disabled: Tuple[int, int, int] = (102, 102, 102)
button_normal_bg: Tuple[int, int, int] = (64, 64, 64)
button_hover_bg: Tuple[int, int, int] = (80, 80, 80)
button_pressed_bg: Tuple[int, int, int] = (48, 48, 48)
button_disabled_bg: Tuple[int, int, int] = (42, 42, 42)
button_text: Tuple[int, int, int] = (255, 255, 255)
button_disabled_text: Tuple[int, int, int] = (102, 102, 102)
input_bg: Tuple[int, int, int] = (64, 64, 64)
input_border: Tuple[int, int, int] = (102, 102, 102)
input_text: Tuple[int, int, int] = (255, 255, 255)
input_focus_border: Tuple[int, int, int] = (0, 170, 255)
selection_bg: Tuple[int, int, int] = (0, 120, 212)
selection_text: Tuple[int, int, int] = (255, 255, 255)
hover_bg: Tuple[int, int, int] = (51, 51, 51)
focus_outline: Tuple[int, int, int] = (0, 170, 255)
search_highlight_bg: Tuple[int, int, int, int] = (255, 255, 0, 100)
search_highlight_text: Tuple[int, int, int] = (0, 0, 0)
status_success: Tuple[int, int, int] = (0, 255, 0)
status_warning: Tuple[int, int, int] = (255, 170, 0)
status_error: Tuple[int, int, int] = (255, 0, 0)
status_info: Tuple[int, int, int] = (0, 170, 255)
progress_bg: Tuple[int, int, int] = (30, 30, 30)
progress_fill: Tuple[int, int, int] = (0, 120, 212)
activity_indicator: Tuple[int, int, int] = (0, 170, 255)
log_critical_fg: Tuple[int, int, int] = (255, 255, 255)
log_critical_bg: Tuple[int, int, int] = (139, 0, 0)
log_error_color: Tuple[int, int, int] = (255, 85, 85)
log_warning_color: Tuple[int, int, int] = (255, 140, 0)
log_info_color: Tuple[int, int, int] = (100, 160, 210)
log_debug_color: Tuple[int, int, int] = (160, 160, 160)
timestamp_color: Tuple[int, int, int] = (105, 105, 105)
logger_name_color: Tuple[int, int, int] = (147, 112, 219)
memory_address_color: Tuple[int, int, int] = (255, 182, 193)
file_path_color: Tuple[int, int, int] = (34, 139, 34)
python_keyword_color: Tuple[int, int, int] = (86, 156, 214)
python_string_color: Tuple[int, int, int] = (206, 145, 120)
python_number_color: Tuple[int, int, int] = (181, 206, 168)
python_operator_color: Tuple[int, int, int] = (212, 212, 212)
python_name_color: Tuple[int, int, int] = (156, 220, 254)
python_function_color: Tuple[int, int, int] = (220, 220, 170)
python_class_color: Tuple[int, int, int] = (78, 201, 176)
python_builtin_color: Tuple[int, int, int] = (86, 156, 214)
python_comment_color: Tuple[int, int, int] = (106, 153, 85)
exception_color: Tuple[int, int, int] = (255, 69, 0)
function_call_color: Tuple[int, int, int] = (255, 215, 0)
boolean_color: Tuple[int, int, int] = (86, 156, 214)
tuple_parentheses_color: Tuple[int, int, int] = (255, 215, 0)
set_braces_color: Tuple[int, int, int] = (255, 140, 0)
class_representation_color: Tuple[int, int, int] = (78, 201, 176)
function_representation_color: Tuple[int, int, int] = (220, 220, 170)
module_path_color: Tuple[int, int, int] = (147, 112, 219)
hex_number_color: Tuple[int, int, int] = (181, 206, 168)
scientific_notation_color: Tuple[int, int, int] = (181, 206, 168)
binary_number_color: Tuple[int, int, int] = (181, 206, 168)
octal_number_color: Tuple[int, int, int] = (181, 206, 168)
python_special_color: Tuple[int, int, int] = (255, 20, 147)
single_quoted_string_color: Tuple[int, int, int] = (206, 145, 120)
list_comprehension_color: Tuple[int, int, int] = (156, 220, 254)
generator_expression_color: Tuple[int, int, int] = (156, 220, 254)
to_qcolor(color_tuple: Tuple[int, int, int]) QColor[source]

Convert RGB tuple to QColor object.

Parameters:

color_tuple – RGB color tuple (r, g, b)

Returns:

Qt color object

Return type:

QColor

to_qcolor_rgba(color_tuple: Tuple[int, int, int, int]) QColor[source]

Convert RGBA tuple to QColor object.

Parameters:

color_tuple – RGBA color tuple (r, g, b, a)

Returns:

Qt color object with alpha

Return type:

QColor

to_hex(color_tuple: Tuple[int, int, int]) str[source]

Convert RGB tuple to hex color string.

Parameters:

color_tuple – RGB color tuple (r, g, b)

Returns:

Hex color string (e.g., “#ff0000”)

Return type:

str

classmethod create_dark_theme() PyQt6ColorScheme[source]

Create a dark theme variant with adjusted colors for dark backgrounds.

This is the default theme, so most colors remain the same with minor adjustments for better contrast on dark backgrounds.

Returns:

Dark theme color scheme with enhanced contrast

Return type:

PyQt6ColorScheme

classmethod create_light_theme() PyQt6ColorScheme[source]

Create a light theme variant with adjusted colors for light backgrounds.

All colors are adjusted to maintain WCAG 4.5:1 contrast ratio on light backgrounds while preserving the semantic meaning and visual hierarchy.

Returns:

Light theme color scheme with appropriate contrast

Return type:

PyQt6ColorScheme

classmethod load_color_scheme_from_config(config_path: str = None) PyQt6ColorScheme[source]

Load color scheme from external configuration file.

Parameters:

config_path – Path to JSON config file (optional)

Returns:

Loaded color scheme or default if file not found

Return type:

PyQt6ColorScheme

validate_wcag_contrast(foreground: Tuple[int, int, int], background: Tuple[int, int, int], min_ratio: float = 4.5) bool[source]

Validate WCAG contrast ratio between foreground and background colors.

Parameters:
  • foreground – Foreground color RGB tuple

  • background – Background color RGB tuple

  • min_ratio – Minimum contrast ratio (default: 4.5 for normal text)

Returns:

True if contrast ratio meets minimum requirement

Return type:

bool

get_color_dict() Dict[str, Tuple[int, int, int]][source]

Get all colors as a dictionary for serialization or inspection.

Returns:

Dictionary of color name to RGB tuple

Return type:

Dict[str, Tuple[int, int, int]]

save_to_json(config_path: str) bool[source]

Save color scheme to JSON configuration file.

Parameters:

config_path – Path to save JSON config file

Returns:

True if save successful, False otherwise

Return type:

bool

__init__(window_bg: Tuple[int, int, int] = (43, 43, 43), panel_bg: Tuple[int, int, int] = (30, 30, 30), frame_bg: Tuple[int, int, int] = (43, 43, 43), border_color: Tuple[int, int, int] = (85, 85, 85), border_light: Tuple[int, int, int] = (102, 102, 102), separator_color: Tuple[int, int, int] = (51, 51, 51), text_primary: Tuple[int, int, int] = (255, 255, 255), text_secondary: Tuple[int, int, int] = (204, 204, 204), text_accent: Tuple[int, int, int] = (0, 170, 255), text_disabled: Tuple[int, int, int] = (102, 102, 102), button_normal_bg: Tuple[int, int, int] = (64, 64, 64), button_hover_bg: Tuple[int, int, int] = (80, 80, 80), button_pressed_bg: Tuple[int, int, int] = (48, 48, 48), button_disabled_bg: Tuple[int, int, int] = (42, 42, 42), button_text: Tuple[int, int, int] = (255, 255, 255), button_disabled_text: Tuple[int, int, int] = (102, 102, 102), input_bg: Tuple[int, int, int] = (64, 64, 64), input_border: Tuple[int, int, int] = (102, 102, 102), input_text: Tuple[int, int, int] = (255, 255, 255), input_focus_border: Tuple[int, int, int] = (0, 170, 255), selection_bg: Tuple[int, int, int] = (0, 120, 212), selection_text: Tuple[int, int, int] = (255, 255, 255), hover_bg: Tuple[int, int, int] = (51, 51, 51), focus_outline: Tuple[int, int, int] = (0, 170, 255), search_highlight_bg: Tuple[int, int, int, int] = (255, 255, 0, 100), search_highlight_text: Tuple[int, int, int] = (0, 0, 0), status_success: Tuple[int, int, int] = (0, 255, 0), status_warning: Tuple[int, int, int] = (255, 170, 0), status_error: Tuple[int, int, int] = (255, 0, 0), status_info: Tuple[int, int, int] = (0, 170, 255), progress_bg: Tuple[int, int, int] = (30, 30, 30), progress_fill: Tuple[int, int, int] = (0, 120, 212), activity_indicator: Tuple[int, int, int] = (0, 170, 255), log_critical_fg: Tuple[int, int, int] = (255, 255, 255), log_critical_bg: Tuple[int, int, int] = (139, 0, 0), log_error_color: Tuple[int, int, int] = (255, 85, 85), log_warning_color: Tuple[int, int, int] = (255, 140, 0), log_info_color: Tuple[int, int, int] = (100, 160, 210), log_debug_color: Tuple[int, int, int] = (160, 160, 160), timestamp_color: Tuple[int, int, int] = (105, 105, 105), logger_name_color: Tuple[int, int, int] = (147, 112, 219), memory_address_color: Tuple[int, int, int] = (255, 182, 193), file_path_color: Tuple[int, int, int] = (34, 139, 34), python_keyword_color: Tuple[int, int, int] = (86, 156, 214), python_string_color: Tuple[int, int, int] = (206, 145, 120), python_number_color: Tuple[int, int, int] = (181, 206, 168), python_operator_color: Tuple[int, int, int] = (212, 212, 212), python_name_color: Tuple[int, int, int] = (156, 220, 254), python_function_color: Tuple[int, int, int] = (220, 220, 170), python_class_color: Tuple[int, int, int] = (78, 201, 176), python_builtin_color: Tuple[int, int, int] = (86, 156, 214), python_comment_color: Tuple[int, int, int] = (106, 153, 85), exception_color: Tuple[int, int, int] = (255, 69, 0), function_call_color: Tuple[int, int, int] = (255, 215, 0), boolean_color: Tuple[int, int, int] = (86, 156, 214), tuple_parentheses_color: Tuple[int, int, int] = (255, 215, 0), set_braces_color: Tuple[int, int, int] = (255, 140, 0), class_representation_color: Tuple[int, int, int] = (78, 201, 176), function_representation_color: Tuple[int, int, int] = (220, 220, 170), module_path_color: Tuple[int, int, int] = (147, 112, 219), hex_number_color: Tuple[int, int, int] = (181, 206, 168), scientific_notation_color: Tuple[int, int, int] = (181, 206, 168), binary_number_color: Tuple[int, int, int] = (181, 206, 168), octal_number_color: Tuple[int, int, int] = (181, 206, 168), python_special_color: Tuple[int, int, int] = (255, 20, 147), single_quoted_string_color: Tuple[int, int, int] = (206, 145, 120), list_comprehension_color: Tuple[int, int, int] = (156, 220, 254), generator_expression_color: Tuple[int, int, int] = (156, 220, 254)) None
class pyqt_reactive.theming.ColorSchemeResolution(provided_scheme: ColorScheme | None)[source]

Bases: object

Resolve an optional caller-provided color scheme into a concrete scheme.

provided_scheme: ColorScheme | None
resolve() ColorScheme[source]
__init__(provided_scheme: ColorScheme | None) None
class pyqt_reactive.theming.WidgetTheme(scheme: ColorScheme, styles: StyleSheetGenerator)[source]

Bases: object

Resolved theme surface for widgets that need colors and stylesheets.

scheme: ColorScheme
styles: StyleSheetGenerator
classmethod from_optional(provided_scheme: ColorScheme | None) WidgetTheme[source]
__init__(scheme: ColorScheme, styles: StyleSheetGenerator) None
class pyqt_reactive.theming.PaletteManager(color_scheme: ColorScheme)[source]

Bases: object

Manages QPalette integration with ColorScheme.

Provides methods to apply color schemes to Qt’s palette system, enabling system-wide theming and consistent color application.

__init__(color_scheme: ColorScheme)[source]

Initialize the palette manager with a color scheme.

Parameters:

color_scheme – ColorScheme instance to use for palette generation

update_color_scheme(color_scheme: ColorScheme)[source]

Update the color scheme used for palette generation.

Parameters:

color_scheme – New ColorScheme instance

create_palette() QPalette[source]

Create a QPalette from the current color scheme.

Returns:

Configured palette with color scheme colors

Return type:

QPalette

apply_palette_to_application(app: QApplication | None = None)[source]

Apply the color scheme palette to the entire application.

Parameters:

app – QApplication instance (uses QApplication.instance() if None)

restore_original_palette(app: QApplication | None = None)[source]

Restore the original application palette.

Parameters:

app – QApplication instance (uses QApplication.instance() if None)

get_palette_info() dict[source]

Get information about the current palette configuration.

Returns:

Dictionary with palette color information

Return type:

dict

class pyqt_reactive.theming.ThemeManager(initial_color_scheme: ColorScheme | None = None)[source]

Bases: object

High-level theme management for the entire application.

Coordinates color scheme, style sheet generation, and palette management to provide seamless theme switching capabilities.

__init__(initial_color_scheme: ColorScheme | None = None)[source]

Initialize the theme manager.

Parameters:

initial_color_scheme – Initial color scheme (defaults to dark theme)

switch_to_dark_theme()[source]

Switch to dark theme variant.

switch_to_light_theme()[source]

Switch to light theme variant.

apply_color_scheme(color_scheme: ColorScheme)[source]

Apply a new color scheme to the entire application.

Parameters:

color_scheme – New ColorScheme to apply

register_theme_change_callback(callback)[source]

Register a callback to be called when theme changes.

Parameters:

callback – Function to call with new color scheme

unregister_theme_change_callback(callback)[source]

Unregister a theme change callback.

Parameters:

callback – Function to remove from callbacks

get_current_style_sheet() str[source]

Get the current complete application style sheet.

Returns:

Complete QStyleSheet for current theme

Return type:

str

load_theme_from_config(config_path: str) bool[source]

Load and apply theme from configuration file.

Parameters:

config_path – Path to JSON configuration file

Returns:

True if successful, False otherwise

Return type:

bool

save_current_theme(config_path: str) bool[source]

Save current theme to configuration file.

Parameters:

config_path – Path to save JSON configuration file

Returns:

True if successful, False otherwise

Return type:

bool

class pyqt_reactive.theming.StyleSheetGenerator(color_scheme: ColorScheme)[source]

Bases: object

Generates QStyleSheet strings from ColorScheme objects.

Provides methods to generate complete stylesheets for different widget types, replacing hardcoded colors with centralized color scheme references.

__init__(color_scheme: ColorScheme)[source]

Initialize the style generator with a color scheme.

Parameters:

color_scheme – ColorScheme instance to use for styling

update_color_scheme(color_scheme: ColorScheme)[source]

Update the color scheme used for style generation.

Parameters:

color_scheme – New ColorScheme instance

generate_dialog_style() str[source]

Generate QStyleSheet for dialog windows.

Returns:

Complete QStyleSheet for dialog styling

Return type:

str

generate_tree_widget_style() str[source]

Generate QStyleSheet for tree widgets and list widgets.

Returns:

Complete QStyleSheet for tree/list widget styling

Return type:

str

generate_list_widget_style() str[source]

Alias for generate_tree_widget_style (includes QListWidget styling).

generate_table_widget_style() str[source]

Generate QStyleSheet for table widgets.

Returns:

Complete QStyleSheet for table widget styling

Return type:

str

generate_button_style() str[source]

Generate QStyleSheet for buttons with all states.

Returns:

Complete QStyleSheet for button styling

Return type:

str

generate_combobox_style() str[source]

Generate QStyleSheet for combo boxes with dropdown styling.

Returns:

Complete QStyleSheet for combo box styling

Return type:

str

generate_progress_bar_style() str[source]

Generate QStyleSheet for progress bars.

Returns:

Complete QStyleSheet for progress bar styling

Return type:

str

generate_frame_style() str[source]

Generate QStyleSheet for frames and panels.

Returns:

Complete QStyleSheet for frame styling

Return type:

str

generate_tab_widget_style() str[source]

Generate QStyleSheet for tab widgets.

Returns:

Complete QStyleSheet for tab widget styling

Return type:

str

generate_system_monitor_style() str[source]

Generate QStyleSheet for system monitor widget.

Returns:

Complete QStyleSheet for system monitor styling

Return type:

str

generate_complete_application_style() str[source]

Generate complete application-wide QStyleSheet.

Returns:

Complete QStyleSheet for entire application

Return type:

str

generate_config_window_style() str[source]

Generate QStyleSheet for configuration windows with button panel.

Returns:

Complete QStyleSheet for config window styling

Return type:

str

generate_config_button_styles() dict[str, str][source]

Generate individual button styles for config window buttons.

Returns:

Dictionary with button styles for generic, reset, cancel, save

Return type:

dict

generate_scope_accent_button_style(accent_color: QColor) str[source]

Generate a scoped accent button style using this theme’s button states.

require_config_button_style(style_name: str) str[source]

Return a named config button style or fail on an undeclared style key.

generate_plate_manager_style() str[source]

Generate QStyleSheet for plate manager widget with all components.

Returns:

Complete QStyleSheet for plate manager styling

Return type:

str

get_status_color_hex(status_type: str) str[source]

Get hex color string for status type.

Parameters:

status_type – Status type (success, warning, error, info)

Returns:

Hex color string for the status type

Return type:

str

pyqt_reactive.animation

Flash animations and visual feedback system.

pyqt_reactive.windows

Window management and scoped window registry.

pyqt_reactive.dialogs

Dialog components and utilities.

Reusable dialogs for PyQt FormGen.