# Developer Guide: GUI Internals This document provides technical details about the implementation of the Graphical User Interface (GUI) for developers. ## Framework The GUI is built using `PySide6`, which provides Python bindings for the Qt framework. ## Main Window (`gui/main_window.py`) The `MainWindow` class acts as the central **coordinator** for the GUI application. It is responsible for: * Setting up the main application window structure and menu bar. * Instantiating and arranging the major GUI widgets: * `MainPanelWidget` (`gui/main_panel_widget.py`): Contains the core controls, preset selection, and the rule editor. * `PresetEditorWidget` (`gui/preset_editor_widget.py`): Handles preset loading, saving, and editing. * `LogConsoleWidget` (`gui/log_console_widget.py`): Displays application logs. * Instantiating key models and handlers: * `UnifiedViewModel` (`gui/unified_view_model.py`): The model for the rule hierarchy view. * `LLMInteractionHandler` (`gui/llm_interaction_handler.py`): Manages communication with the LLM service. * Connecting signals and slots between these components to orchestrate the application flow. * Handling top-level user interactions like drag-and-drop for loading sources (`add_input_paths`). This method now handles the "placeholder" state (no preset selected) by scanning directories or inspecting archives (ZIP) and creating placeholder `SourceRule`/`AssetRule`/`FileRule` objects to immediately populate the `UnifiedViewModel` with the file structure. * Initiating predictions based on the selected preset mode (Rule-Based or LLM) when presets change or sources are added. * Starting the processing task (`_on_process_requested`): This slot now filters the `SourceRule` list obtained from the `UnifiedViewModel`, excluding sources where no asset has a `Target Asset` name assigned, before emitting the `start_backend_processing` signal. It also manages enabling/disabling controls. * Managing the `QThreadPool` for running background prediction tasks (`RuleBasedPredictionHandler`, `LLMPredictionHandler`). * Implementing slots to handle results from background tasks: * `_handle_prediction_completion(source_id, source_rule_list)`: Receives results from either prediction handler via the `prediction_signal`. It calls `self.unified_view_model.update_rules_for_sources()` to update the view model, preserving user overrides where possible. For LLM predictions, it also triggers processing the next item in the queue. * Slots to handle status updates from the LLM handler. ## Threading and Background Tasks To keep the UI responsive, prediction tasks run in background threads managed by a `QThreadPool`. * **`BasePredictionHandler` (`gui/base_prediction_handler.py`):** An abstract `QRunnable` base class defining the common interface and signals (`prediction_signal`, `status_signal`) for prediction tasks. * **`RuleBasedPredictionHandler` (`gui/prediction_handler.py`):** Inherits from `BasePredictionHandler`. Runs as a `QRunnable` in the thread pool when a rule-based preset is selected. Generates the `SourceRule` hierarchy based on preset rules and emits `prediction_signal`. * **`LLMPredictionHandler` (`gui/llm_prediction_handler.py`):** Inherits from `BasePredictionHandler`. Runs as a `QRunnable` in the thread pool when "- LLM Interpretation -" is selected. Interacts with `LLMInteractionHandler`, parses the response, generates the `SourceRule` hierarchy for a *single* input item, and emits `prediction_signal` and `status_signal`. * **`LLMInteractionHandler` (`gui/llm_interaction_handler.py`):** Manages the communication with the LLM service. This handler itself may perform network operations but typically runs synchronously within the `LLMPredictionHandler`'s thread. *(Note: The actual processing via `ProcessingEngine` is now handled by `main.ProcessingTask`, which runs in a separate process managed outside the GUI's direct threading model, though the GUI initiates it).* ## Communication (Signals and Slots) Communication between the `MainWindow` (main UI thread) and the background prediction tasks relies on Qt's signals and slots. * Prediction handlers (`RuleBasedPredictionHandler`, `LLMPredictionHandler`) emit signals from the `BasePredictionHandler`: * `prediction_signal(source_id, source_rule_list)`: Indicates prediction for a source is complete. * `status_signal(message)`: Provides status updates (primarily from LLM handler). * The `MainWindow` connects slots to these signals: * `prediction_signal` -> `MainWindow._handle_prediction_completion(source_id, source_rule_list)` * `status_signal` -> `MainWindow._on_status_update(message)` (updates status bar) * Signals from the `UnifiedViewModel` (`dataChanged`, `layoutChanged`) trigger updates in the `QTreeView`. * Signals from the `UnifiedViewModel` (`targetAssetOverrideChanged`) trigger the `AssetRestructureHandler`. ## Preset Editor (`gui/preset_editor_widget.py`) The `PresetEditorWidget` provides a dedicated interface for managing presets. It handles loading, displaying, editing, and saving preset `.json` files. It communicates with the `MainWindow` (e.g., via signals) when a preset is loaded or saved. ## Unified Hierarchical View The core rule editing interface is built around a `QTreeView` managed within the `MainPanelWidget`, using a custom model and delegates. * **`UnifiedViewModel` (`gui/unified_view_model.py`):** Implements `QAbstractItemModel`. * Wraps the `RuleHierarchyModel` to expose the `SourceRule` list (Source -> Asset -> File) to the `QTreeView`. * Provides data for display and flags for editing. * **Handles `setData` requests:** Validates input and updates the underlying `RuleHierarchyModel`. Crucially, it **delegates** complex restructuring (when `target_asset_name_override` changes) to the `AssetRestructureHandler` by emitting the `targetAssetOverrideChanged` signal. * **Row Coloring:** Provides data for `Qt.ForegroundRole` (text color) based on the `item_type` and the colors defined in `config/app_settings.json`. Provides data for `Qt.BackgroundRole` based on calculating a 30% darker shade of the parent asset's background color. * **Caching:** Caches configuration data (`ASSET_TYPE_DEFINITIONS`, `FILE_TYPE_DEFINITIONS`, color maps) in `__init__` for performance. * **`update_rules_for_sources` Method:** Intelligently merges new prediction results or placeholder rules into the existing model data, preserving user overrides where applicable. * *(Note: The previous concept of switching between "simple" and "detailed" display modes has been removed. The model always represents the full detailed structure.)* * **`RuleHierarchyModel` (`gui/rule_hierarchy_model.py`):** A non-Qt model holding the actual list of `SourceRule` objects. Provides methods for accessing and modifying the hierarchy (used by `UnifiedViewModel` and `AssetRestructureHandler`). * **`AssetRestructureHandler` (`gui/asset_restructure_handler.py`):** Contains the logic to modify the `RuleHierarchyModel` when a file's target asset is changed. It listens for the `targetAssetOverrideChanged` signal from the `UnifiedViewModel` and uses methods on the `RuleHierarchyModel` (`moveFileRule`, `createAssetRule`, `removeAssetRule`) to perform the restructuring safely. * **`Delegates` (`gui/delegates.py`):** Custom `QStyledItemDelegate` implementations provide inline editors: * **`ComboBoxDelegate`:** For selecting predefined types (from `Configuration`). * **`LineEditDelegate`:** For free-form text editing. * **`SupplierSearchDelegate`:** For supplier names with auto-completion (using `config/suppliers.json`). **Data Flow Diagram (GUI Rule Management - Refactored):** ```mermaid graph TD subgraph MainWindow [MainWindow Coordinator] direction LR MW_Input[User Input (Drag/Drop, Preset Select)] --> MW(MainWindow); MW -- Initiates --> PredPool{QThreadPool}; MW -- Connects Signals --> VM(UnifiedViewModel); MW -- Connects Signals --> ARH(AssetRestructureHandler); MW -- Owns/Manages --> MPW(MainPanelWidget); MW -- Owns/Manages --> PEW(PresetEditorWidget); MW -- Owns/Manages --> LCW(LogConsoleWidget); MW -- Owns/Manages --> LLMIH(LLMInteractionHandler); end subgraph MainPanel [MainPanelWidget] direction TB MPW_UI[UI Controls (Load, Predict, Process Btns)]; MPW_UI --> MPW; MPW -- Contains --> REW(RuleEditorWidget); end subgraph RuleEditor [RuleEditorWidget] direction TB REW -- Contains --> TV(QTreeView - Rule View); end subgraph Prediction [Background Prediction] direction TB PredPool -- Runs --> RBP(RuleBasedPredictionHandler); PredPool -- Runs --> LLMP(LLMPredictionHandler); LLMP -- Uses --> LLMIH; RBP -- prediction_signal --> MW; LLMP -- prediction_signal --> MW; LLMP -- status_signal --> MW; end subgraph ModelView [Model/View Components] direction TB TV -- Sets Model --> VM; TV -- Displays Data From --> VM; TV -- Uses Delegates --> Del(Delegates); UserEdit[User Edits Rules] --> TV; TV -- setData --> VM; VM -- Wraps --> RHM(RuleHierarchyModel); VM -- dataChanged/layoutChanged --> TV; VM -- targetAssetOverrideChanged --> ARH; ARH -- Modifies --> RHM; Del -- Get/Set Data --> VM; end MW -- _handle_prediction_completion --> VM; MW -- Triggers Processing --> ProcTask(main.ProcessingTask); %% Connections between subgraphs MPW --> MW; PEW --> MW; LCW --> MW; VM --> MW; ARH --> MW; LLMIH --> MW; REW --> MPW; ``` ## Application Styling The application style is explicitly set to 'Fusion' in `gui/main_window.py`. A custom `QPalette` adjusts default colors. ## Logging (`gui/log_console_widget.py`) The `LogConsoleWidget` displays logs captured by a custom `QtLogHandler` from Python's `logging` module. ## Cancellation The GUI provides a "Cancel" button. Cancellation logic for the actual processing is now likely handled within the `main.ProcessingTask` or the code that manages it, as the `ProcessingHandler` has been removed. The GUI button would signal this external task manager. ## GUI Configuration Editor (`gui/config_editor_dialog.py`) A dedicated dialog for editing `config/app_settings.json`. * **Functionality:** Loads `config/app_settings.json`, presents in tabs, allows editing basic fields, definitions tables (with color editing), and merge rules list/detail. * **Limitations:** Editing complex fields like `IMAGE_RESOLUTIONS` or full `MAP_MERGE_RULES` details might still be limited. * **Integration:** Launched by `MainWindow` ("Edit" -> "Preferences..."). * **Persistence:** Saves changes to `config/app_settings.json`. Requires application restart for changes to affect processing logic loaded by the `Configuration` class. The refactored GUI separates concerns into distinct widgets and handlers, coordinated by the `MainWindow`. Background tasks use `QThreadPool` and `QRunnable`. The `UnifiedViewModel` focuses on data presentation and simple edits, delegating complex restructuring to the `AssetRestructureHandler`.