11 KiB
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 is the central component of the GUI application. It is responsible for:
- Defining the main application window structure and layout using PySide6 widgets.
- Arranging the Preset Editor panel (left) and the Processing panel (right).
- Setting up the menu bar, including the "View" menu for toggling the Log Console and Detailed File Preview.
- Connecting user interactions (button clicks, drag-and-drop events, checkbox states, spinbox values) to corresponding methods (slots) within the
MainWindowor other handler classes. - Managing the display of application logs in the UI console using a custom
QtLogHandler. - Interacting with background handlers (
ProcessingHandler,PredictionHandler) via Qt signals and slots to ensure thread-safe updates to the UI during long-running operations. - Integrating the
QTreeView(displaying the rule hierarchy viaRuleHierarchyModel) and theRuleEditorWidgetfor interactive rule editing. - Connecting the selection changes in the
QTreeViewto update theRuleEditorWidgetwith the selected rule object's attributes.
Threading and Background Tasks
To keep the UI responsive during intensive operations like asset processing and file preview generation, the GUI utilizes background threads managed by QThread.
ProcessingHandler(gui/processing_handler.py): This class is designed to run in a separateQThread. It manages the execution of the main asset processing pipeline for multiple assets concurrently usingconcurrent.futures.ProcessPoolExecutor. It submits individual asset processing tasks to the pool and monitors their completion. It uses Qt signals to communicate progress updates, file status changes, and overall processing completion back to theMainWindowon the main UI thread. It also handles the execution of optional Blender scripts via subprocess calls after processing. This handler processes and utilizes data structures received from the core processing engine, such as status summaries. It receives the initialSourceRuleobject generated by thePredictionHandlerand passes it to theAssetProcessorfor processing.PredictionHandler(gui/prediction_handler.py): This class also runs in a separateQThread. It is responsible for generating the detailed file classification previews displayed in the preview table. It calls methods on theAssetProcessor(get_detailed_file_predictions) to perform the analysis in the background. It uses aThreadPoolExecutorfor potentially concurrent prediction tasks. Results are sent back to theMainWindowvia Qt signals to update the preview table data. This handler works with data structures containing file prediction details.
Communication (Signals and Slots)
Communication between the main UI thread (MainWindow) and the background threads (ProcessingHandler, PredictionHandler) relies heavily on Qt's signals and slots mechanism. This is a thread-safe way for objects in different threads to communicate.
- Background handlers emit signals to indicate events (e.g., progress updated, file status changed, task finished).
- The
MainWindowconnects slots (methods) to these signals. When a signal is emitted, the connected slot is invoked on the thread that owns the receiving object (the main UI thread forMainWindow), ensuring UI updates happen safely.
Preset Editor
The GUI includes an integrated preset editor panel. This allows users to interactively create, load, modify, and save preset .json files directly within the application. The editor typically uses standard UI widgets to display and edit the key fields of the preset structure.
Preview Table
The PreviewTableModel receives a list of file prediction dictionaries from the PredictionHandler via the prediction_results_ready signal. This list contains dictionaries for each file with details such as original path, predicted asset name, status, and other relevant information.
The PreviewTableModel is designed to process and display this file prediction data. Instead of directly displaying the flat list, it processes and transforms the data into a structured list of rows (self._table_rows). This transformation involves:
- Grouping: Files are grouped based on their
source_asset. - Separation: Within each asset group, files are separated into
main_files(Mapped, Model, Error) andadditional_files(Ignored, Extra, Unrecognised, Unmatched Extra). - Structuring Rows: Rows are created for
self._table_rowsto represent the grouped data. Each row can contain information about a main file and/or an additional file, allowing for the display of additional files in a separate column aligned with the main files of the same asset. Empty rows are created if there are more additional files than main files for an asset to maintain alignment.
The data() method of the PreviewTableModel then accesses this structured self._table_rows list to provide data to the QTableView for display. It handles different columns and roles (Display, Tooltip, Foreground, and Background).
Qt.ItemDataRole.ForegroundRole: Used to set the text color of individual cells based on the status of the file they represent. Coloring is applied to cells corresponding to a main file based on the main file's status, and to cells in the "Additional Files" column based on the additional file's status.Qt.ItemDataRole.BackgroundRole: Used to provide alternating background colors based on the index of the asset group the row belongs to in a sorted list of unique assets, improving visual separation between different asset groups.
The PreviewSortFilterProxyModel operates on this structured data, implementing a multi-level sort based on source asset, row type (main vs. additional-only), and file paths within those types.
- Calls methods on the
AssetProcessor(specificallyget_detailed_file_predictions) to perform the analysis in the background. It uses aThreadPoolExecutorfor potentially concurrent prediction tasks. Results are sent back to theMainWindowvia Qt signals to update the preview table data. This handler works with data structures containing file prediction details. It is also responsible for generating the initialSourceRulehierarchy based on the input files and the selected preset, and emitting a signal to provide thisSourceRuleobject to theMainWindow.
Rule Hierarchy UI (gui/rule_hierarchy_model.py, gui/rule_editor_widget.py)
The GUI now includes dedicated components for visualizing and editing the hierarchical processing rules:
Rule Hierarchy Model(gui/rule_hierarchy_model.py): This class implementsQAbstractItemModelto expose the structure of aSourceRuleobject (Source -> Asset -> File) to aQTreeView. It allows theQTreeViewto display the hierarchy and enables user selection of individual rule objects (SourceRule, AssetRule, or FileRule).Rule Editor Widget(gui/rule_editor_widget.py): This custom widget provides a dynamic form for editing the attributes of the currently selected rule object from the hierarchy tree. When a rule object is selected in theQTreeView, theMainWindowupdates theRuleEditorWidgetto display and allow modification of that object's specific parameters.
These components are integrated into the MainWindow. The PredictionHandler generates the initial SourceRule hierarchy, which is then set on the RuleHierarchyModel. The QTreeView displays this model, and selection changes in the tree trigger updates to the RuleEditorWidget, allowing users to interactively modify the dynamic rules before processing. Edits made in the RuleEditorWidget directly modify the attributes of the underlying rule objects in the SourceRule hierarchy.
Preview Table Column Configuration
The display and behavior of the columns in the QTableView are configured in gui/main_window.py. The current configuration is as follows:
- Column Order (from left to right):
- Status
- Predicted Asset
- Details
- Original Path
- Additional Files
- Column Resizing:
- Status: Resizes to content.
- Predicted Asset: Resizes to content.
- Details: Resizes to content.
- Original Path: Resizes to content (fixed width behavior).
- Additional Files: Stretches to fill available space.
Data Flow Diagram:
graph LR
A[PredictionHandler] -- prediction_results_ready(flat_list) --> B(PreviewTableModel);
subgraph PreviewTableModel
C[set_data] -- Processes flat_list --> D{Internal Grouping & Transformation};
D -- Creates --> E[_table_rows (Structured List)];
F[data()] -- Reads from --> E;
end
B -- Provides data via data() --> G(QTableView via Proxy);
style B fill:#f9f,stroke:#333,stroke-width:2px
style C fill:#ccf,stroke:#333,stroke-width:1px
style D fill:#lightgrey,stroke:#333,stroke-width:1px
style E fill:#ccf,stroke:#333,stroke-width:1px
style F fill:#ccf,stroke:#333,stroke-width:1px
Application Styling
The application style is explicitly set to 'Fusion' in gui/main_window.py to provide a more consistent look and feel across different operating systems, particularly to address styling inconsistencies observed on Windows 11. A custom QPalette is also applied to the application to adjust default colors within the 'Fusion' style, specifically to change the background color of list-like widgets and potentially other elements from a default dark blue to a more neutral grey.
Logging
A custom QtLogHandler is used to redirect log messages from the standard Python logging module to a text area or console widget within the GUI, allowing users to see detailed application output and errors.
Cancellation
The GUI provides a "Cancel" button to stop ongoing processing. The ProcessingHandler implements logic to handle cancellation requests. This typically involves setting an internal flag and attempting to shut down the ProcessPoolExecutor. However, it's important to note that this does not immediately terminate worker processes that are already executing; it primarily prevents new tasks from starting and stops processing results from completed futures once the cancellation flag is checked.
Note on Data Passing: As mentioned in the Architecture documentation, major changes to the data passing mechanisms between the GUI, Main (CLI orchestration), and AssetProcessor modules are currently being planned. The descriptions of how data is handled and passed within the GUI and its interactions with background handlers reflect the current state and will require review and updates once the plan for these changes is finalized.