Asset-Frameworker/Project Notes/GUI_FEATURE_PLAN.md
2025-04-29 18:26:13 +02:00

103 lines
7.0 KiB
Markdown

# GUI Feature Enhancement Plan
**Overall Goal:** Modify the GUI (`gui/main_window.py`, `gui/prediction_handler.py`) to make the output path configurable, improve UI responsiveness during preview generation, and add a toggle to switch between detailed file preview and a simple input path list.
**Detailed Plan:**
1. **Feature: Configurable Output Path**
* **File:** `gui/main_window.py`
* **Changes:**
* **UI Addition:**
* Below the `preset_combo` layout, add a new `QHBoxLayout`.
* Inside this layout, add:
* A `QLabel` with text "Output Directory:".
* A `QLineEdit` (e.g., `self.output_path_edit`) to display/edit the path. Make it read-only initially if preferred, or editable.
* A `QPushButton` (e.g., `self.browse_output_button`) with text "Browse...".
* **Initialization (`__init__` or `setup_main_panel_ui`):**
* Read the default `OUTPUT_BASE_DIR` from `core_config`.
* Resolve this path relative to the project root (`project_root / output_base_dir_config`).
* Set the initial text of `self.output_path_edit` to this resolved default path.
* **Browse Button Logic:**
* Connect the `clicked` signal of `self.browse_output_button` to a new method (e.g., `_browse_for_output_directory`).
* Implement `_browse_for_output_directory`:
* Use `QFileDialog.getExistingDirectory` to let the user select a folder.
* If a directory is selected, update the text of `self.output_path_edit`.
* **Processing Logic (`start_processing`):**
* Instead of reading/resolving the path from `core_config`, get the path string directly from `self.output_path_edit.text()`.
* Convert this string to a `Path` object.
* **Add Validation:** Before passing the path to the handler, check if the directory exists. If not, attempt to create it using `output_dir.mkdir(parents=True, exist_ok=True)`. Handle potential `OSError` exceptions during creation and show an error message if it fails. Also, consider adding a basic writability check if possible.
* Pass the validated `output_dir_str` to `self.processing_handler.run_processing`.
2. **Feature: Responsive UI (Address Prediction Bottleneck)**
* **File:** `gui/prediction_handler.py`
* **Changes:**
* **Import:** Add `from concurrent.futures import ThreadPoolExecutor, as_completed`.
* **Modify `run_prediction`:**
* Inside the `try` block (after loading `config`), create a `ThreadPoolExecutor` (e.g., `with ThreadPoolExecutor(max_workers=...) as executor:`). Determine a reasonable `max_workers` count (e.g., `os.cpu_count() // 2` or a fixed number like 4 or 8).
* Instead of iterating through `input_paths` sequentially, submit a task to the executor for each `input_path_str`.
* The task submitted should be a helper method (e.g., `_predict_single_asset`) that takes `input_path_str` and the loaded `config` object as arguments.
* `_predict_single_asset` will contain the logic currently inside the loop: instantiate `AssetProcessor`, call `get_detailed_file_predictions`, handle exceptions, and return the list of prediction dictionaries for that *single* asset (or an error dictionary).
* Store the `Future` objects returned by `executor.submit`.
* Use `as_completed(futures)` to process results as they become available.
* Append the results from each completed future to the `all_file_results` list.
* Emit `prediction_results_ready` once at the very end with the complete `all_file_results` list.
* **File:** `gui/main_window.py`
* **Changes:**
* No changes needed in the `on_prediction_results_ready` slot itself, as the handler will still emit the full list at the end.
3. **Feature: Preview Toggle**
* **File:** `gui/main_window.py`
* **Changes:**
* **UI Addition:**
* Add a `QCheckBox` (e.g., `self.disable_preview_checkbox`) with text "Disable Detailed Preview". Place it logically, perhaps near the `overwrite_checkbox` or above the `preview_table`. Set its default state to unchecked.
* **Modify `update_preview`:**
* At the beginning of the method, check `self.disable_preview_checkbox.isChecked()`.
* **If Checked (Simple View):**
* Clear the `preview_table`.
* Set simplified table headers (e.g., `self.preview_table.setColumnCount(1); self.preview_table.setHorizontalHeaderLabels(["Input Path"])`). Adjust column resize modes.
* Iterate through `self.current_asset_paths`. For each path, add a row to the table containing just the path string.
* Set status bar message (e.g., "Preview disabled. Showing input list.").
* **Crucially:** `return` from the method here to prevent the `PredictionHandler` from being started.
* **If Unchecked (Detailed View):**
* Ensure the table headers and column count are set back to the detailed view configuration (Status, Original Path, Predicted Name, Details).
* Continue with the rest of the existing `update_preview` logic to start the `PredictionHandler`.
* **Connect Signal:** In `__init__` or `setup_main_panel_ui`, connect the `toggled` signal of `self.disable_preview_checkbox` to the `self.update_preview` slot.
* **Initial State:** Ensure the first call to `update_preview` (if any) respects the initial unchecked state of the checkbox.
**Mermaid Diagram:**
```mermaid
graph TD
subgraph MainWindow
A[User Action: Add Asset / Change Preset / Toggle Preview] --> B{Update Preview Triggered};
B --> C{Is 'Disable Preview' Checked?};
C -- Yes --> D[Show Simple List View in Table];
C -- No --> E[Set Detailed Table Headers];
E --> F[Start PredictionHandler Thread];
F --> G[PredictionHandler Runs];
G --> H[Slot: Populate Table with Detailed Results];
I[User Clicks Start Processing] --> J{Get Output Path from UI LineEdit};
J --> K[Validate/Create Output Path];
K -- Path OK --> L[Start ProcessingHandler Thread];
K -- Path Error --> M[Show Error Message];
L --> N[ProcessingHandler Runs];
N --> O[Update UI (Progress, Status)];
P[User Clicks Browse...] --> Q[Show QFileDialog];
Q --> R[Update Output Path LineEdit];
end
subgraph PredictionHandler [Background Thread]
style PredictionHandler fill:#f9f,stroke:#333,stroke-width:2px
F --> S{Use ThreadPoolExecutor};
S --> T[Run _predict_single_asset Concurrently];
T --> U[Collect Results];
U --> V[Emit prediction_results_ready (Full List)];
V --> H;
end
subgraph ProcessingHandler [Background Thread]
style ProcessingHandler fill:#ccf,stroke:#333,stroke-width:2px
L --> N;
end