Compare commits

..

2 Commits

Author SHA1 Message Date
87673507d8 New Definitions editor 2025-05-13 13:08:52 +02:00
344ae078a8 UI Updates - Error with Definitions 2025-05-13 11:54:22 +02:00
15 changed files with 2396 additions and 337 deletions

View File

@ -15,7 +15,7 @@ The `app_settings.json` file is structured into several key sections, including:
### LLM Predictor Settings
For users who wish to utilize the experimental LLM Predictor feature, the following settings are available in `config/app_settings.json`:
For users who wish to utilize the experimental LLM Predictor feature, the following settings are available in `config/llm_settings.json`:
* `llm_endpoint_url`: The URL of the LLM API endpoint. For local LLMs like LM Studio or Ollama, this will typically be `http://localhost:<port>/v1`. Consult your LLM server documentation for the exact endpoint.
* `llm_api_key`: The API key required to access the LLM endpoint. Some local LLM servers may not require a key, in which case this can be left empty.
@ -23,15 +23,39 @@ For users who wish to utilize the experimental LLM Predictor feature, the follow
* `llm_temperature`: Controls the randomness of the LLM's output. Lower values (e.g., 0.1-0.5) make the output more deterministic and focused, while higher values (e.g., 0.6-1.0) make it more creative and varied. For prediction tasks, lower temperatures are generally recommended.
* `llm_request_timeout`: The maximum time (in seconds) to wait for a response from the LLM API. Adjust this based on the performance of your LLM server and the complexity of the requests.
Note that the `llm_predictor_prompt` and `llm_predictor_examples` settings are also present in `app_settings.json`. These define the instructions and examples provided to the LLM for prediction. While they can be viewed here, they are primarily intended for developer reference and tuning the LLM's behavior, and most users will not need to modify them.
Note that the `llm_predictor_prompt` and `llm_predictor_examples` settings are also present in `config/llm_settings.json`. These define the instructions and examples provided to the LLM for prediction. While they can be viewed here, they are primarily intended for developer reference and tuning the LLM's behavior, and most users will not need to modify them directly via the file. These settings are editable via the LLM Editor panel in the main GUI when the LLM interpretation mode is selected.
## GUI Configuration Editor
## Application Preferences (`config/app_settings.json` overrides)
You can modify the `app_settings.json` file using the built-in GUI editor. Access it via the **Edit** -> **Preferences...** menu.
You can modify user-overridable application settings using the built-in GUI editor. These settings are loaded from `config/app_settings.json` and saved as overrides in `config/user_settings.json`. Access it via the **Edit** -> **Preferences...** menu.
This editor provides a tabbed interface (e.g., "General", "Output & Naming") to view and change the core application settings defined in `app_settings.json`. Settings in the editor directly correspond to the structure and values within the JSON file. Note that any changes made through the GUI editor require an application restart to take effect.
This editor provides a tabbed interface to view and change various application behaviors. The tabs include:
* **General:** Basic settings like output base directory and temporary file prefix.
* **Output & Naming:** Settings controlling output directory and filename patterns, and how variants are handled.
* **Image Processing:** Settings related to image resolution definitions, compression levels, and format choices.
* **Map Merging:** Configuration for how multiple input maps are combined into single output maps.
* **Postprocess Scripts:** Paths to default Blender files for post-processing.
*(Ideally, a screenshot of the GUI Configuration Editor would be included here.)*
Note that this editor focuses on user-specific overrides of core application settings. **Asset Type Definitions, File Type Definitions, and Supplier Settings are managed in a separate Definitions Editor.**
Any changes made through the Preferences editor require an application restart to take effect.
*(Ideally, a screenshot of the Application Preferences editor would be included here.)*
## Definitions Editor (`config/asset_type_definitions.json`, `config/file_type_definitions.json`, `config/suppliers.json`)
Core application definitions that are separate from general user preferences are managed in the dedicated Definitions Editor. This includes defining known asset types, file types, and configuring settings specific to different suppliers. Access it via the **Edit** -> **Edit Definitions...** menu.
The editor is organized into three tabs:
* **Asset Type Definitions:** Define the different categories of assets (e.g., Surface, Model, Decal). For each asset type, you can configure its description, a color for UI representation, and example usage strings.
* **File Type Definitions:** Define the specific types of files the tool recognizes (e.g., MAP_COL, MAP_NRM, MODEL). For each file type, you can configure its description, a color, example keywords/patterns, a standard type alias, bit depth handling rules, whether it's grayscale, and an optional keybind for quick assignment in the GUI.
* **Supplier Settings:** Configure settings that are specific to assets originating from different suppliers. Currently, this includes the "Normal Map Type" (OpenGL or DirectX) used for normal maps from that supplier.
Each tab presents a list of the defined items on the left (Asset Types, File Types, or Suppliers). Selecting an item in the list displays its configurable details on the right. Buttons are provided to add new definitions or remove existing ones.
Changes made in the Definitions Editor are saved directly to their respective configuration files (`config/asset_type_definitions.json`, `config/file_type_definitions.json`, and `config/suppliers.json`). Some changes may require an application restart to take full effect in processing logic.
*(Ideally, screenshots of the Definitions Editor tabs would be included here.)*
## Preset Files (`presets/*.json`)

View File

@ -12,7 +12,10 @@ python -m gui.main_window
## Interface Overview
* **Menu Bar:** The "Edit" menu contains the "Preferences..." option to open the GUI Configuration Editor. The "View" menu allows you to toggle the visibility of the Log Console and the Detailed File Preview.
* **Menu Bar:** The "Edit" menu contains options to configure application settings and definitions:
* **Preferences...:** Opens the Application Preferences editor for user-overridable settings (saved to `config/user_settings.json`).
* **Edit Definitions...:** Opens the Definitions Editor for managing Asset Type Definitions, File Type Definitions, and Supplier Settings (saved to their respective files).
The "View" menu allows you to toggle the visibility of the Log Console and the Detailed File Preview.
* **Preset Editor Panel (Left):**
* **Optional Log Console:** Displays application logs (toggle via View menu).
* **Preset List:** Create, delete, load, edit, and save presets. On startup, the "-- Select a Preset --" item is explicitly selected. You must select a specific preset from this list to load it into the editor below, enable the detailed file preview, and enable the "Start Processing" button.

View File

@ -2,7 +2,7 @@
This document describes the directory structure and contents of the processed assets generated by the Asset Processor Tool.
Processed assets are saved to a location determined by two global settings defined in `config/app_settings.json`:
Processed assets are saved to a location determined by two global settings, `OUTPUT_DIRECTORY_PATTERN` and `OUTPUT_FILENAME_PATTERN`, defined in `config/app_settings.json`. These settings can be overridden by the user via `config/user_settings.json`.
* `OUTPUT_DIRECTORY_PATTERN`: Defines the directory structure *within* the Base Output Directory.
* `OUTPUT_FILENAME_PATTERN`: Defines the naming convention for individual files *within* the directory created by `OUTPUT_DIRECTORY_PATTERN`.
@ -23,7 +23,7 @@ The following tokens can be used in both `OUTPUT_DIRECTORY_PATTERN` and `OUTPUT_
* `[Time]`: Current time (`HHMMSS`).
* `[Sha5]`: The first 5 characters of the SHA-256 hash of the original input source file (e.g., the source zip archive).
* `[ApplicationPath]`: Absolute path to the application directory.
* `[maptype]`: The standardized map type identifier (e.g., `COL` for Color/Albedo, `NRM` for Normal, `RGH` for Roughness). This is derived from the `standard_type` defined in the application's `FILE_TYPE_DEFINITIONS` (see `config/app_settings.json`) and may include a variant suffix if applicable. (Primarily for filename pattern)
* `[maptype]`: The standardized map type identifier (e.g., `COL` for Color/Albedo, `NRM` for Normal, `RGH` for Roughness). This is derived from the `standard_type` defined in the application's `FILE_TYPE_DEFINITIONS` (managed in `config/file_type_definitions.json` via the Definitions Editor) and may include a variant suffix if applicable. (Primarily for filename pattern)
* `[dimensions]`: Pixel dimensions (e.g., `2048x2048`).
* `[bitdepth]`: Output bit depth (e.g., `8bit`, `16bit`).
* `[category]`: Asset category determined by preset rules.
@ -51,7 +51,7 @@ The final output path is constructed by combining the Base Output Directory (set
* `OUTPUT_FILENAME_PATTERN`: `[maptype].[ext]`
* Resulting Path for a Normal map: `Output/Texture/Wood/WoodFloor001/Normal.exr`
The `<output_base_directory>` (the root folder where processing output starts) is configured separately via the GUI (**Edit** -> **Preferences...** -> **Output & Naming** tab -> **Base Output Directory**) or the `--output` CLI argument. The `OUTPUT_DIRECTORY_PATTERN` defines the structure *within* this base directory, and `OUTPUT_FILENAME_PATTERN` defines the filenames within that structure.
The `<output_base_directory>` (the root folder where processing output starts) is configured separately via the GUI (**Edit** -> **Preferences...** -> **General** tab -> **Output Base Directory**) or the `--output` CLI argument. The `OUTPUT_DIRECTORY_PATTERN` defines the structure *within* this base directory, and `OUTPUT_FILENAME_PATTERN` defines the filenames within that structure.
## Contents of Each Asset Directory

View File

@ -8,45 +8,61 @@ The tool's configuration is managed by the `configuration.py` module and loaded
### Configuration Files
1. **Application Settings (`config/app_settings.json`):** This JSON file defines the core global default settings, constants, and rules that apply generally across different asset sources (e.g., the global `OUTPUT_DIRECTORY_PATTERN` and `OUTPUT_FILENAME_PATTERN`, standard image resolutions, map merge rules, output format rules, Blender paths). See the [User Guide: Output Structure](../01_User_Guide/09_Output_Structure.md#available-tokens) for a list of available tokens for these patterns.
The tool's configuration is loaded from several JSON files, providing a layered approach for defaults, user overrides, definitions, and source-specific presets.
1. **Application Settings (`config/app_settings.json`):** This JSON file defines the core global default settings, constants, and rules that apply generally across different asset sources (e.g., the global `OUTPUT_DIRECTORY_PATTERN` and `OUTPUT_FILENAME_PATTERN`, standard image resolutions, map merge rules, output format rules, Blender paths, temporary directory prefix, initial scaling mode, merge dimension mismatch strategy). See the [User Guide: Output Structure](../01_User_Guide/09_Output_Structure.md#available-tokens) for a list of available tokens for these patterns.
* *Note:* `ASSET_TYPE_DEFINITIONS` and `FILE_TYPE_DEFINITIONS` are no longer stored here; they have been moved to dedicated files.
2. **User Settings (`config/user_settings.json`):** This optional JSON file allows users to override specific settings defined in `config/app_settings.json`. If this file exists, its values for corresponding keys will take precedence over the base application settings. This file is primarily managed through the GUI's Configuration Editor.
2. **User Settings (`config/user_settings.json`):** This optional JSON file allows users to override specific settings defined in `config/app_settings.json`. If this file exists, its values for corresponding keys will take precedence over the base application settings. This file is primarily managed through the GUI's Application Preferences Editor.
3. **Asset Type Definitions (`config/asset_type_definitions.json`):** This dedicated JSON file contains the definitions for different asset types (e.g., Surface, Model, Decal), including their descriptions, colors, and examples.
3. **Asset Type Definitions (`config/asset_type_definitions.json`):** This dedicated JSON file contains the definitions for different asset types (e.g., Surface, Model, Decal), including their descriptions, colors for UI representation, and example usage strings.
4. **File Type Definitions (`config/file_type_definitions.json`):** This dedicated JSON file contains the definitions for different file types (specifically texture maps and models), including descriptions, colors, examples, standard aliases, bit depth rules, grayscale flags, and GUI keybinds.
* **`keybind` Property:** Each file type object within `FILE_TYPE_DEFINITIONS` can optionally include a `keybind` property. This property accepts a single character string (e.g., `"C"`, `"R"`) representing the keyboard key. In the GUI, this key (typically combined with `Ctrl`, or standalone like `F2` for asset naming) is used as a shortcut to set or toggle the corresponding file type for selected items in the Preview Table.
4. **File Type Definitions (`config/file_type_definitions.json`):** This dedicated JSON file contains the definitions for different file types (specifically texture maps and models), including descriptions, colors for UI representation, examples of keywords/patterns, a standard alias (`standard_type`), bit depth handling rules (`bit_depth_rule`), a grayscale flag (`is_grayscale`), and an optional GUI keybind (`keybind`).
* **`keybind` Property:** Each file type object within `FILE_TYPE_DEFINITIONS` can optionally include a `keybind` property. This property accepts a single character string (e.g., `"C"`, `"R"`) representing the keyboard key. In the GUI, this key (typically combined with `Ctrl`) is used as a shortcut to set or toggle the corresponding file type for selected items in the Preview Table.
*Example:*
```json
"MAP_COL": {
"description": "Color/Albedo Map",
"color": [200, 200, 200],
"examples": ["albedo", "col", "basecolor"],
"color": "#ffaa00",
"examples": ["_col.", "_basecolor.", "albedo", "diffuse"],
"standard_type": "COL",
"bit_depth_rule": "respect",
"bit_depth_rule": "force_8bit",
"is_grayscale": false,
"keybind": "C"
},
```
* **New File Type `MAP_GLOSS`:** A standard file type, `MAP_GLOSS`, is defined here.
*Example:*
Note: The `bit_depth_rule` property in `FILE_TYPE_DEFINITIONS` is the primary source for determining bit depth handling for a given map type.
5. **Supplier Settings (`config/suppliers.json`):** This JSON file stores settings specific to different asset suppliers. It is now structured as a dictionary where keys are supplier names and values are objects containing supplier-specific configurations.
* **Structure:**
```json
"MAP_GLOSS": {
"description": "Glossiness Map",
"color": [180, 180, 220],
"examples": ["gloss", "gls"],
"standard_type": "GLOSS",
"bit_depth_rule": "respect",
"is_grayscale": true,
"keybind": "R"
{
"SupplierName1": {
"setting_key1": "value",
"setting_key2": "value"
},
"SupplierName2": {
"setting_key1": "value"
}
}
```
* **`normal_map_type` Property:** A key setting within each supplier's object is `normal_map_type`, specifying whether normal maps from this supplier use "OpenGL" or "DirectX" conventions.
*Example:*
```json
{
"Poliigon": {
"normal_map_type": "DirectX"
},
"Dimensiva": {
"normal_map_type": "OpenGL"
}
}
```
Note: The `keybind` "R" for `MAP_GLOSS` is often shared with `MAP_ROUGH` to allow toggling between them.
5. **LLM Settings (`config/llm_settings.json`):** This JSON file contains settings specifically related to the LLM predictor, such as the API endpoint, model name, prompt template, and examples. These settings can be edited through the GUI using the `LLMEditorWidget`.
6. **LLM Settings (`config/llm_settings.json`):** This JSON file contains settings specifically related to the LLM predictor, such as the API endpoint, model name, prompt template, and examples. These settings are managed through the GUI using the `LLMEditorWidget`.
7. **Preset Files (`Presets/*.json`):** These JSON files define source-specific rules and overrides. They contain patterns to interpret filenames, classify map types, handle variants, define naming conventions, and specify other source-specific behaviors. Preset settings override values from `app_settings.json` and `user_settings.json` where applicable.
6. **Preset Files (`Presets/*.json`):** These JSON files define supplier-specific rules and overrides. They contain patterns to interpret filenames, classify map types, handle variants, define naming conventions, and specify other source-specific behaviors. Preset settings override values from `app_settings.json` and `user_settings.json` where applicable.
### Configuration Loading and Access

View File

@ -10,13 +10,13 @@ The GUI is built using `PySide6`, which provides Python bindings for the Qt fram
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.
* Setting up the main application window structure and menu bar, including actions to launch configuration and definition editors.
* **Layout:** Arranging the main GUI components using a `QSplitter`.
* **Left Pane:** Contains the preset selection controls (from `PresetEditorWidget`) permanently displayed at the top. Below this, a `QStackedWidget` switches between the preset JSON editor (also from `PresetEditorWidget`) and the `LLMEditorWidget`.
* **Right Pane:** Contains the `MainPanelWidget`.
* Instantiating and managing the major GUI widgets:
* `PresetEditorWidget` (`gui/preset_editor_widget.py`): Provides the preset selector and the JSON editor parts.
* `LLMEditorWidget` (`gui/llm_editor_widget.py`): Provides the editor for LLM settings.
* `LLMEditorWidget` (`gui/llm_editor_widget.py`): Provides the editor for LLM settings (from `config/llm_settings.json`).
* `MainPanelWidget` (`gui/main_panel_widget.py`): Contains the rule hierarchy view and processing controls.
* `LogConsoleWidget` (`gui/log_console_widget.py`): Displays application logs.
* Instantiating key models and handlers:
@ -198,13 +198,24 @@ The `LogConsoleWidget` displays logs captured by a custom `QtLogHandler` from Py
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`)
## Application Preferences Editor (`gui/config_editor_dialog.py`)
A dedicated dialog for editing `config/app_settings.json`.
A dedicated dialog for editing user-overridable application settings. It loads base settings from `config/app_settings.json` and saves user overrides to `config/user_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.
* **Functionality:** Provides a tabbed interface to edit various application settings, including general paths, output/naming patterns, image processing options (like resolutions and compression), and map merging rules. It no longer includes editors for Asset Type or File Type Definitions.
* **Integration:** Launched by `MainWindow` via the "Edit" -> "Preferences..." menu.
* **Persistence:** Saves changes to `config/user_settings.json`. Changes require an application restart to take effect in processing logic.
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`.
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`.
## Definitions Editor (`gui/definitions_editor_dialog.py`)
A new dedicated dialog for managing core application definitions that are separate from general user preferences.
* **Purpose:** Provides a structured UI for editing Asset Type Definitions, File Type Definitions, and Supplier Settings.
* **Structure:** Uses a `QTabWidget` with three tabs:
* **Asset Type Definitions:** Manages definitions from `config/asset_type_definitions.json`. Presents a list of asset types and allows editing their description, color, and examples.
* **File Type Definitions:** Manages definitions from `config/file_type_definitions.json`. Presents a list of file types and allows editing their description, color, examples, standard type, bit depth rule, grayscale status, and keybind.
* **Supplier Settings:** Manages settings from `config/suppliers.json`. Presents a list of suppliers and allows editing supplier-specific settings (e.g., Normal Map Type).
* **Integration:** Launched by `MainWindow` via the "Edit" -> "Edit Definitions..." menu.
* **Persistence:** Saves changes directly to the respective configuration files (`config/asset_type_definitions.json`, `config/file_type_definitions.json`, `config/suppliers.json`). Some changes may require an application restart.

View File

@ -0,0 +1,62 @@
# Issue: List item selection not working in Definitions Editor
**Date:** 2025-05-13
**Affected File:** [`gui/definitions_editor_dialog.py`](gui/definitions_editor_dialog.py)
**Problem Description:**
User mouse clicks on items within the `QListWidget` instances (for Asset Types, File Types, and Suppliers) in the Definitions Editor dialog do not trigger item selection or the `currentItemChanged` signal. The first item is selected by default and its details are displayed correctly. Programmatic selection of items (e.g., via a diagnostic button) *does* correctly trigger the `currentItemChanged` signal and updates the UI detail views. The issue is specific to user-initiated mouse clicks for selection after the initial load.
**Debugging Steps Taken & Findings:**
1. **Initial Analysis:**
* Reviewed GUI internals documentation ([`Documentation/02_Developer_Guide/06_GUI_Internals.md`](Documentation/02_Developer_Guide/06_GUI_Internals.md)) and [`gui/definitions_editor_dialog.py`](gui/definitions_editor_dialog.py) source code.
* Confirmed signal connections (`currentItemChanged` to display slots) are made.
2. **Logging in Display Slots (`_display_*_details`):**
* Added logging to display slots. Confirmed they are called for the initial (default) item selection.
* No further calls to these slots occur on user clicks, indicating `currentItemChanged` is not firing.
3. **Color Swatch Palette Role:**
* Investigated and corrected `QPalette.ColorRole` for color swatches (reverted from `Background` to `Window`). This fixed an `AttributeError` but did not resolve the selection issue.
4. **Robust Error Handling in Display Slots:**
* Wrapped display slot logic in `try...finally` blocks with detailed logging. Confirmed slots complete without error for initial selection and signals for detail widgets are reconnected.
5. **Diagnostic Lambda for `currentItemChanged`:**
* Added a lambda logger to `currentItemChanged` alongside the main display slot.
* Confirmed both lambda and display slot fire for initial programmatic selection.
* Neither fires for subsequent user clicks. This proved the `QListWidget` itself was not emitting the signal.
6. **Explicit `setEnabled` and `setSelectionMode` on `QListWidget`:**
* Explicitly set these properties. No change in behavior.
7. **Explicit `setEnabled` and `setFocusPolicy(Qt.ClickFocus)` on `tab_page` (parent of `QListWidget` layout):**
* This change **allowed programmatic selection via a diagnostic button to correctly fire `currentItemChanged` and update the UI**.
* However, user mouse clicks still did not work and did not fire the signal.
8. **Event Filter Investigation:**
* **Filter on `QListWidget`:** Did NOT receive mouse press/release events from user clicks.
* **Filter on `tab_page` (parent of `QListWidget`'s layout):** Did NOT receive mouse press/release events.
* **Filter on `self.tab_widget` (QTabWidget):** DID receive mouse press/release events.
* Modified `self.tab_widget`'s event filter to return `False` for events over the current page, attempting to ensure propagation.
* **Result:** With the modified `tab_widget` filter, an event filter re-added to `asset_type_list_widget` *did* start receiving mouse press/release events. **However, `asset_type_list_widget` still did not emit `currentItemChanged` from these user clicks.**
9. **`DebugListWidget` (Subclassing `QListWidget`):**
* Created `DebugListWidget` overriding `mousePressEvent` with logging.
* Used `DebugListWidget` for `asset_type_list_widget`.
* **Initial user report indicated that `DebugListWidget.mousePressEvent` logs were NOT appearing for user clicks.** This means that even with the `QTabWidget` event filter attempting to propagate events, and the `asset_type_list_widget`'s filter (from step 8) confirming it received them, the `mousePressEvent` of the `QListWidget` itself was not being triggered by those propagated events. This is the current mystery.
**Current Status:**
- Programmatic selection works and fires signals.
- User clicks are received by an event filter on `asset_type_list_widget` (after `QTabWidget` filter modification) but do not result in `mousePressEvent` being called on the `QListWidget` (or `DebugListWidget`) itself, and thus no `currentItemChanged` signal is emitted.
- The issue seems to be a very low-level event processing problem specifically for user mouse clicks within the `QListWidget` instances when they are children of the `QTabWidget` pages, even when events appear to reach the list widget via an event filter.
**Next Steps (When Resuming):**
1. Re-verify the logs from the `DebugListWidget.mousePressEvent` test. If it's truly not being called despite its event filter seeing events, this is extremely unusual.
2. Simplify the `_create_tab_pane` method drastically for one tab:
* Remove the right-hand pane.
* Add the `DebugListWidget` directly to the `tab_page`'s layout without the intermediate `left_pane_layout`.
3. Consider if any styles applied to `QListWidget` or its parents via stylesheets could be interfering with hit testing or event processing (unlikely for this specific symptom, but possible).
4. Explore alternative ways to populate/manage the `QListWidget` or its items if a subtle corruption is occurring.
5. If all else fails, consider replacing the `QListWidget` with a `QListView` and a `QStringListModel` as a more fundamental change to see if the issue is specific to `QListWidget` in this context.

View File

@ -1,39 +1,39 @@
{
"ASSET_TYPE_DEFINITIONS": {
"Surface": {
"description": "A single Standard PBR material set for a surface.",
"color": "#1f3e5d",
"description": "A single Standard PBR material set for a surface.",
"examples": [
"Set: Wood01_COL + Wood01_NRM + WOOD01_ROUGH",
"Set: Dif_Concrete + Normal_Concrete + Refl_Concrete"
]
},
"Model": {
"description": "A set that contains models, can include PBR textureset",
"color": "#b67300",
"description": "A set that contains models, can include PBR textureset",
"examples": [
"Single = Chair.fbx",
"Set = Plant02.fbx + Plant02_col + Plant02_SSS"
]
},
"Decal": {
"description": "A alphamasked textureset",
"color": "#68ac68",
"description": "A alphamasked textureset",
"examples": [
"Set = DecalGraffiti01_Col + DecalGraffiti01_Alpha",
"Single = DecalLeakStain03"
]
},
"Atlas": {
"description": "A texture, name usually hints that it's an atlas",
"color": "#955b8b",
"description": "A texture, name usually hints that it's an atlas",
"examples": [
"Set = FoliageAtlas01_col + FoliageAtlas01_nrm"
]
},
"UtilityMap": {
"description": "A useful image-asset consisting of only a single texture. Therefor each Utilitymap can only contain a single item.",
"color": "#706b87",
"description": "A useful image-asset consisting of only a single texture. Therefor each Utilitymap can only contain a single item.",
"examples": [
"Single = imperfection.png",
"Single = smudges.png",

View File

@ -1,149 +1,155 @@
{
"FILE_TYPE_DEFINITIONS": {
"MAP_COL": {
"description": "Color/Albedo Map",
"bit_depth_rule": "force_8bit",
"color": "#ffaa00",
"description": "Color/Albedo Map",
"examples": [
"_col.",
"_basecolor.",
"albedo",
"diffuse"
],
"standard_type": "COL",
"bit_depth_rule": "force_8bit",
"is_grayscale": false,
"keybind": "C"
"keybind": "C",
"standard_type": "COL"
},
"MAP_NRM": {
"description": "Normal Map",
"bit_depth_rule": "respect",
"color": "#cca2f1",
"description": "Normal Map",
"examples": [
"_nrm.",
"_normal."
],
"standard_type": "NRM",
"bit_depth_rule": "respect",
"is_grayscale": false,
"keybind": "N"
"keybind": "N",
"standard_type": "NRM"
},
"MAP_METAL": {
"description": "Metalness Map",
"bit_depth_rule": "force_8bit",
"color": "#dcf4f2",
"description": "Metalness Map",
"examples": [
"_metal.",
"_met."
],
"standard_type": "METAL",
"bit_depth_rule": "force_8bit",
"is_grayscale": true,
"keybind": "M"
"keybind": "M",
"standard_type": "METAL"
},
"MAP_ROUGH": {
"description": "Roughness Map",
"bit_depth_rule": "force_8bit",
"color": "#bfd6bf",
"description": "Roughness Map",
"examples": [
"_rough.",
"_rgh.",
"_gloss"
],
"standard_type": "ROUGH",
"bit_depth_rule": "force_8bit",
"is_grayscale": true,
"keybind": "R"
"keybind": "R",
"standard_type": "ROUGH"
},
"MAP_GLOSS": {
"description": "Glossiness Map",
"bit_depth_rule": "force_8bit",
"color": "#d6bfd6",
"description": "Glossiness Map",
"examples": [
"_gloss.",
"_gls."
],
"standard_type": "GLOSS",
"bit_depth_rule": "force_8bit",
"is_grayscale": true,
"keybind": "R"
"keybind": "R",
"standard_type": "GLOSS"
},
"MAP_AO": {
"description": "Ambient Occlusion Map",
"bit_depth_rule": "force_8bit",
"color": "#e3c7c7",
"description": "Ambient Occlusion Map",
"examples": [
"_ao.",
"_ambientocclusion."
],
"standard_type": "AO",
"bit_depth_rule": "force_8bit",
"is_grayscale": true
"is_grayscale": true,
"keybind": "",
"standard_type": "AO"
},
"MAP_DISP": {
"description": "Displacement/Height Map",
"bit_depth_rule": "respect",
"color": "#c6ddd5",
"description": "Displacement/Height Map",
"examples": [
"_disp.",
"_height."
],
"standard_type": "DISP",
"bit_depth_rule": "respect",
"is_grayscale": true,
"keybind": "D"
"keybind": "D",
"standard_type": "DISP"
},
"MAP_REFL": {
"description": "Reflection/Specular Map",
"bit_depth_rule": "force_8bit",
"color": "#c2c2b9",
"description": "Reflection/Specular Map",
"examples": [
"_refl.",
"_specular."
],
"standard_type": "REFL",
"bit_depth_rule": "force_8bit",
"is_grayscale": true,
"keybind": "M"
"keybind": "M",
"standard_type": "REFL"
},
"MAP_SSS": {
"description": "Subsurface Scattering Map",
"bit_depth_rule": "respect",
"color": "#a0d394",
"description": "Subsurface Scattering Map",
"examples": [
"_sss.",
"_subsurface."
],
"standard_type": "SSS",
"bit_depth_rule": "respect",
"is_grayscale": true
"is_grayscale": true,
"keybind": "",
"standard_type": "SSS"
},
"MAP_FUZZ": {
"description": "Fuzz/Sheen Map",
"bit_depth_rule": "force_8bit",
"color": "#a2d1da",
"description": "Fuzz/Sheen Map",
"examples": [
"_fuzz.",
"_sheen."
],
"standard_type": "FUZZ",
"bit_depth_rule": "force_8bit",
"is_grayscale": true
"is_grayscale": true,
"keybind": "",
"standard_type": "FUZZ"
},
"MAP_IDMAP": {
"description": "ID Map (for masking)",
"bit_depth_rule": "force_8bit",
"color": "#ca8fb4",
"description": "ID Map (for masking)",
"examples": [
"_id.",
"_matid."
],
"standard_type": "IDMAP",
"bit_depth_rule": "force_8bit",
"is_grayscale": false
"is_grayscale": false,
"keybind": "",
"standard_type": "IDMAP"
},
"MAP_MASK": {
"description": "Generic Mask Map",
"bit_depth_rule": "force_8bit",
"color": "#c6e2bf",
"description": "Generic Mask Map",
"examples": [
"_mask."
],
"standard_type": "MASK",
"bit_depth_rule": "force_8bit",
"is_grayscale": true
"is_grayscale": true,
"keybind": "",
"standard_type": "MASK"
},
"MAP_IMPERFECTION": {
"description": "Imperfection Map (scratches, dust)",
"bit_depth_rule": "force_8bit",
"color": "#e6d1a6",
"description": "Imperfection Map (scratches, dust)",
"examples": [
"_imp.",
"_imperfection.",
@ -153,24 +159,26 @@
"hairs",
"fingerprints"
],
"standard_type": "IMPERFECTION",
"bit_depth_rule": "force_8bit",
"is_grayscale": true
"is_grayscale": true,
"keybind": "",
"standard_type": "IMPERFECTION"
},
"MODEL": {
"description": "3D Model File",
"bit_depth_rule": "",
"color": "#3db2bd",
"description": "3D Model File",
"examples": [
".fbx",
".obj"
],
"standard_type": "",
"bit_depth_rule": "",
"is_grayscale": false
"is_grayscale": false,
"keybind": "",
"standard_type": ""
},
"EXTRA": {
"description": "asset previews or metadata",
"bit_depth_rule": "",
"color": "#8c8c8c",
"description": "asset previews or metadata",
"examples": [
".txt",
".zip",
@ -180,22 +188,21 @@
"_Cube.",
"thumb"
],
"standard_type": "",
"bit_depth_rule": "",
"is_grayscale": false,
"keybind": "E"
"keybind": "E",
"standard_type": ""
},
"FILE_IGNORE": {
"description": "File to be ignored",
"bit_depth_rule": "",
"color": "#673d35",
"description": "File to be ignored",
"examples": [
"Thumbs.db",
".DS_Store"
],
"standard_type": "",
"bit_depth_rule": "",
"is_grayscale": false,
"keybind": "X"
"keybind": "X",
"standard_type": ""
}
}
}

View File

@ -1,5 +1,11 @@
[
"Dimensiva",
"Dinesen",
"Poliigon"
]
{
"Dimensiva": {
"normal_map_type": "OpenGL"
},
"Dinesen": {
"normal_map_type": "OpenGL"
},
"Poliigon": {
"normal_map_type": "OpenGL"
}
}

View File

@ -13,6 +13,7 @@ LLM_SETTINGS_PATH = BASE_DIR / "config" / "llm_settings.json"
ASSET_TYPE_DEFINITIONS_PATH = BASE_DIR / "config" / "asset_type_definitions.json"
FILE_TYPE_DEFINITIONS_PATH = BASE_DIR / "config" / "file_type_definitions.json"
USER_SETTINGS_PATH = BASE_DIR / "config" / "user_settings.json" # New path for user settings
SUPPLIERS_CONFIG_PATH = BASE_DIR / "config" / "suppliers.json"
PRESETS_DIR = BASE_DIR / "Presets"
class ConfigurationError(Exception):
@ -801,3 +802,149 @@ def save_base_config(settings_dict: dict):
except Exception as e:
log.error(f"Failed to save base configuration file {APP_SETTINGS_PATH}: {e}")
raise ConfigurationError(f"Failed to save configuration: {e}")
def load_asset_definitions() -> dict:
"""
Reads config/asset_type_definitions.json.
Returns the dictionary under the "ASSET_TYPE_DEFINITIONS" key.
Handles file not found or JSON errors gracefully (e.g., return empty dict, log error).
"""
log.debug(f"Loading asset type definitions from: {ASSET_TYPE_DEFINITIONS_PATH}")
if not ASSET_TYPE_DEFINITIONS_PATH.is_file():
log.error(f"Asset type definitions file not found: {ASSET_TYPE_DEFINITIONS_PATH}")
return {}
try:
with open(ASSET_TYPE_DEFINITIONS_PATH, 'r', encoding='utf-8') as f:
data = json.load(f)
if "ASSET_TYPE_DEFINITIONS" not in data:
log.error(f"Key 'ASSET_TYPE_DEFINITIONS' not found in {ASSET_TYPE_DEFINITIONS_PATH}")
return {}
settings = data["ASSET_TYPE_DEFINITIONS"]
if not isinstance(settings, dict):
log.error(f"'ASSET_TYPE_DEFINITIONS' in {ASSET_TYPE_DEFINITIONS_PATH} must be a dictionary.")
return {}
log.debug(f"Asset type definitions loaded successfully.")
return settings
except json.JSONDecodeError as e:
log.error(f"Failed to parse asset type definitions file {ASSET_TYPE_DEFINITIONS_PATH}: Invalid JSON - {e}")
return {}
except Exception as e:
log.error(f"Failed to read asset type definitions file {ASSET_TYPE_DEFINITIONS_PATH}: {e}")
return {}
def save_asset_definitions(data: dict):
"""
Takes a dictionary (representing the content for the "ASSET_TYPE_DEFINITIONS" key).
Writes it to config/asset_type_definitions.json under the root key "ASSET_TYPE_DEFINITIONS".
Handles potential I/O errors.
"""
log.debug(f"Saving asset type definitions to: {ASSET_TYPE_DEFINITIONS_PATH}")
try:
with open(ASSET_TYPE_DEFINITIONS_PATH, 'w', encoding='utf-8') as f:
json.dump({"ASSET_TYPE_DEFINITIONS": data}, f, indent=4)
log.info(f"Asset type definitions saved successfully to {ASSET_TYPE_DEFINITIONS_PATH}")
except Exception as e:
log.error(f"Failed to save asset type definitions file {ASSET_TYPE_DEFINITIONS_PATH}: {e}")
raise ConfigurationError(f"Failed to save asset type definitions: {e}")
def load_file_type_definitions() -> dict:
"""
Reads config/file_type_definitions.json.
Returns the dictionary under the "FILE_TYPE_DEFINITIONS" key.
Handles errors gracefully.
"""
log.debug(f"Loading file type definitions from: {FILE_TYPE_DEFINITIONS_PATH}")
if not FILE_TYPE_DEFINITIONS_PATH.is_file():
log.error(f"File type definitions file not found: {FILE_TYPE_DEFINITIONS_PATH}")
return {}
try:
with open(FILE_TYPE_DEFINITIONS_PATH, 'r', encoding='utf-8') as f:
data = json.load(f)
if "FILE_TYPE_DEFINITIONS" not in data:
log.error(f"Key 'FILE_TYPE_DEFINITIONS' not found in {FILE_TYPE_DEFINITIONS_PATH}")
return {}
settings = data["FILE_TYPE_DEFINITIONS"]
if not isinstance(settings, dict):
log.error(f"'FILE_TYPE_DEFINITIONS' in {FILE_TYPE_DEFINITIONS_PATH} must be a dictionary.")
return {}
log.debug(f"File type definitions loaded successfully.")
return settings
except json.JSONDecodeError as e:
log.error(f"Failed to parse file type definitions file {FILE_TYPE_DEFINITIONS_PATH}: Invalid JSON - {e}")
return {}
except Exception as e:
log.error(f"Failed to read file type definitions file {FILE_TYPE_DEFINITIONS_PATH}: {e}")
return {}
def save_file_type_definitions(data: dict):
"""
Takes a dictionary (representing content for "FILE_TYPE_DEFINITIONS" key).
Writes it to config/file_type_definitions.json under the root key "FILE_TYPE_DEFINITIONS".
Handles errors.
"""
log.debug(f"Saving file type definitions to: {FILE_TYPE_DEFINITIONS_PATH}")
try:
with open(FILE_TYPE_DEFINITIONS_PATH, 'w', encoding='utf-8') as f:
json.dump({"FILE_TYPE_DEFINITIONS": data}, f, indent=4)
log.info(f"File type definitions saved successfully to {FILE_TYPE_DEFINITIONS_PATH}")
except Exception as e:
log.error(f"Failed to save file type definitions file {FILE_TYPE_DEFINITIONS_PATH}: {e}")
raise ConfigurationError(f"Failed to save file type definitions: {e}")
def load_supplier_settings() -> dict:
"""
Reads config/suppliers.json.
Returns the entire dictionary.
Handles file not found (return empty dict) or JSON errors.
If the loaded data is a list (old format), convert it in memory to the new
dictionary format, defaulting normal_map_type to "OpenGL" for each supplier.
"""
log.debug(f"Loading supplier settings from: {SUPPLIERS_CONFIG_PATH}")
if not SUPPLIERS_CONFIG_PATH.is_file():
log.warning(f"Supplier settings file not found: {SUPPLIERS_CONFIG_PATH}. Returning empty dict.")
return {}
try:
with open(SUPPLIERS_CONFIG_PATH, 'r', encoding='utf-8') as f:
data = json.load(f)
if isinstance(data, list):
log.warning(f"Supplier settings in {SUPPLIERS_CONFIG_PATH} is in the old list format. Converting to new dictionary format.")
new_data = {}
for supplier_name in data:
if isinstance(supplier_name, str):
new_data[supplier_name] = {"normal_map_type": "OpenGL"}
else:
log.warning(f"Skipping non-string item '{supplier_name}' during old format conversion of supplier settings.")
log.info(f"Supplier settings converted to new format: {new_data}")
return new_data
if not isinstance(data, dict):
log.error(f"Supplier settings in {SUPPLIERS_CONFIG_PATH} must be a dictionary. Found {type(data)}. Returning empty dict.")
return {}
log.debug(f"Supplier settings loaded successfully.")
return data
except json.JSONDecodeError as e:
log.error(f"Failed to parse supplier settings file {SUPPLIERS_CONFIG_PATH}: Invalid JSON - {e}. Returning empty dict.")
return {}
except Exception as e:
log.error(f"Failed to read supplier settings file {SUPPLIERS_CONFIG_PATH}: {e}. Returning empty dict.")
return {}
def save_supplier_settings(data: dict):
"""
Takes a dictionary (in the new format).
Writes it directly to config/suppliers.json.
Handles errors.
"""
log.debug(f"Saving supplier settings to: {SUPPLIERS_CONFIG_PATH}")
if not isinstance(data, dict):
log.error(f"Data for save_supplier_settings must be a dictionary. Got {type(data)}.")
raise ConfigurationError(f"Invalid data type for saving supplier settings: {type(data)}")
try:
with open(SUPPLIERS_CONFIG_PATH, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2) # Using indent=2 as per the example for suppliers.json
log.info(f"Supplier settings saved successfully to {SUPPLIERS_CONFIG_PATH}")
except Exception as e:
log.error(f"Failed to save supplier settings file {SUPPLIERS_CONFIG_PATH}: {e}")
raise ConfigurationError(f"Failed to save supplier settings: {e}")

View File

@ -0,0 +1,137 @@
# Plan for New Definitions Editor UI
## 1. Overview
This document outlines the plan to create a new, dedicated UI for managing "Asset Type Definitions", "File Type Definitions", and "Supplier Settings". This editor will provide a more structured and user-friendly way to manage these core application configurations, which are currently stored in separate JSON files.
## 2. General Design Principles
* **Dedicated Dialog:** The editor will be a new `QDialog` (e.g., `DefinitionsEditorDialog`).
* **Access Point:** Launched from the `MainWindow` menu bar (e.g., under a "Definitions" menu or "Edit" -> "Edit Definitions...").
* **Tabbed Interface:** The dialog will use a `QTabWidget` to separate the management of different definition types.
* **List/Details View:** Each tab will generally follow a two-pane layout:
* **Left Pane:** A `QListWidget` displaying the primary keys or names of the definitions (e.g., asset type names, file type IDs, supplier names). Includes "Add" and "Remove" buttons for managing these primary entries.
* **Right Pane:** A details area (e.g., `QGroupBox` with a `QFormLayout`) that shows the specific settings for the item selected in the left-pane list.
* **Data Persistence:** The dialog will load from and save to the respective JSON configuration files:
* Asset Types: `config/asset_type_definitions.json`
* File Types: `config/file_type_definitions.json`
* Supplier Settings: `config/suppliers.json` (This file will be refactored from a simple list to a dictionary of supplier objects).
* **User Experience:** Standard "Save" and "Cancel" buttons, with a check for unsaved changes.
## 3. Tab-Specific Plans
### 3.1. Asset Type Definitions Tab
* **Manages:** `config/asset_type_definitions.json`
* **UI Sketch:**
```mermaid
graph LR
subgraph AssetTypeTab [Asset Type Definitions Tab]
direction LR
AssetList[QListWidget (Asset Type Keys e.g., "Surface")] --> AssetDetailsGroup{Details for Selected Asset Type};
end
subgraph AssetDetailsGroup
direction TB
Desc[Description: QTextEdit]
Color[Color: QPushButton ("Choose Color...") + Color Swatch Display]
Examples[Examples: QListWidget + Add/Remove Example Buttons]
end
AssetActions["Add Asset Type (Prompt for Name)\nRemove Selected Asset Type"] --> AssetList
```
* **Details:**
* **Left Pane:** `QListWidget` for asset type names. "Add Asset Type" (prompts for new key) and "Remove Selected Asset Type" buttons.
* **Right Pane (Details):**
* `description`: `QTextEdit`.
* `color`: `QPushButton` opening `QColorDialog`, with an adjacent `QLabel` to display the color swatch.
* `examples`: `QListWidget` with "Add Example" (`QInputDialog.getText`) and "Remove Selected Example" buttons.
### 3.2. File Type Definitions Tab
* **Manages:** `config/file_type_definitions.json`
* **UI Sketch:**
```mermaid
graph LR
subgraph FileTypeTab [File Type Definitions Tab]
direction LR
FileList[QListWidget (File Type Keys e.g., "MAP_COL")] --> FileDetailsGroup{Details for Selected File Type};
end
subgraph FileDetailsGroup
direction TB
DescF[Description: QTextEdit]
ColorF[Color: QPushButton ("Choose Color...") + Color Swatch Display]
ExamplesF[Examples: QListWidget + Add/Remove Example Buttons]
StdType[Standard Type: QLineEdit]
BitDepth[Bit Depth Rule: QComboBox ("respect", "force_8bit", "force_16bit")]
IsGrayscale[Is Grayscale: QCheckBox]
Keybind[Keybind: QLineEdit (1 char)]
end
FileActions["Add File Type (Prompt for ID)\nRemove Selected File Type"] --> FileList
```
* **Details:**
* **Left Pane:** `QListWidget` for file type IDs. "Add File Type" (prompts for new key) and "Remove Selected File Type" buttons.
* **Right Pane (Details):**
* `description`: `QTextEdit`.
* `color`: `QPushButton` opening `QColorDialog`, with an adjacent `QLabel` for color swatch.
* `examples`: `QListWidget` with "Add Example" and "Remove Selected Example" buttons.
* `standard_type`: `QLineEdit`.
* `bit_depth_rule`: `QComboBox` (options: "respect", "force_8bit", "force_16bit").
* `is_grayscale`: `QCheckBox`.
* `keybind`: `QLineEdit` (validation for single character recommended).
### 3.3. Supplier Settings Tab
* **Manages:** `config/suppliers.json` (This file will be refactored to a dictionary structure, e.g., `{"SupplierName": {"normal_map_type": "OpenGL", ...}}`).
* **UI Sketch:**
```mermaid
graph LR
subgraph SupplierTab [Supplier Settings Tab]
direction LR
SupplierList[QListWidget (Supplier Names)] --> SupplierDetailsGroup{Details for Selected Supplier};
end
subgraph SupplierDetailsGroup
direction TB
NormalMapType[Normal Map Type: QComboBox ("OpenGL", "DirectX")]
%% Future supplier-specific settings can be added here
end
SupplierActions["Add Supplier (Prompt for Name)\nRemove Selected Supplier"] --> SupplierList
```
* **Details:**
* **Left Pane:** `QListWidget` for supplier names. "Add Supplier" (prompts for new name) and "Remove Selected Supplier" buttons.
* **Right Pane (Details):**
* `normal_map_type`: `QComboBox` (options: "OpenGL", "DirectX"). Default for new suppliers: "OpenGL".
* *(Space for future supplier-specific settings).*
* **Data Handling Note for `config/suppliers.json`:**
* The editor will load from and save to `config/suppliers.json` using the new dictionary format (supplier name as key, object of settings as value).
* Initial implementation might require `config/suppliers.json` to be manually updated to this new format if it currently exists as a simple list. Alternatively, the editor could attempt an automatic conversion on first load if the old list format is detected, or prompt the user. For the first pass, assuming the editor works with the new format is simpler.
## 4. Implementation Steps (High-Level)
1. **(Potentially Manual First Step) Refactor `config/suppliers.json`:** If `config/suppliers.json` exists as a list, manually convert it to the new dictionary structure (e.g., `{"SupplierName": {"normal_map_type": "OpenGL"}}`) before starting UI development for this tab, or plan for the editor to handle this conversion.
2. **Create `DefinitionsEditorDialog` Class:** Inherit from `QDialog`.
3. **Implement UI Structure:** Main `QTabWidget`, and for each tab, the two-pane layout with `QListWidget`, `QGroupBox` for details, and relevant input widgets (`QLineEdit`, `QTextEdit`, `QComboBox`, `QCheckBox`, `QPushButton`).
4. **Implement Loading Logic:**
* For each tab, read data from its corresponding JSON file.
* Populate the left-pane `QListWidget` with the primary keys/names.
* Store the full data structure internally (e.g., in dictionaries within the dialog instance).
5. **Implement Display Logic:**
* When an item is selected in a `QListWidget`, populate the right-pane detail fields with the data for that item.
6. **Implement Editing Logic:**
* Ensure that changes made in the detail fields (text edits, combobox selections, checkbox states, color choices, list example modifications) update the corresponding internal data structure for the currently selected item.
7. **Implement Add/Remove Functionality:**
* For each definition type (Asset Type, File Type, Supplier), implement the "Add" and "Remove" buttons.
* "Add": Prompt for a unique key/name, create a new default entry in the internal data, and add it to the `QListWidget`.
* "Remove": Remove the selected item from the `QListWidget` and the internal data.
* For "examples" lists within Asset and File types, implement their "Add Example" and "Remove Selected Example" buttons.
8. **Implement Saving Logic:**
* When the main "Save" button is clicked:
* Write the (potentially modified) Asset Type definitions data structure to `config/asset_type_definitions.json`.
* Write File Type definitions to `config/file_type_definitions.json`.
* Write Supplier settings (in the new dictionary format) to `config/suppliers.json`.
* Consider creating new dedicated save functions in `configuration.py` for each of these files if they don't already exist or if existing ones are not suitable.
9. **Implement Unsaved Changes Check & Cancel Logic.**
10. **Integrate Dialog Launch:** Add a menu action in `MainWindow.py` to open the `DefinitionsEditorDialog`.
This plan provides a comprehensive approach to creating a dedicated editor for these crucial application definitions.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@ from .llm_editor_widget import LLMEditorWidget
from .log_console_widget import LogConsoleWidget
from .main_panel_widget import MainPanelWidget
from .definitions_editor_dialog import DefinitionsEditorDialog
# --- Backend Imports for Data Structures ---
from rule_structure import SourceRule, AssetRule, FileRule
@ -861,6 +862,11 @@ class MainWindow(QMainWindow):
self.preferences_action = QAction("&Preferences...", self)
self.preferences_action.triggered.connect(self._open_config_editor)
edit_menu.addAction(self.preferences_action)
edit_menu.addSeparator()
self.definitions_editor_action = QAction("Edit Definitions...", self)
self.definitions_editor_action.triggered.connect(self._open_definitions_editor)
edit_menu.addAction(self.definitions_editor_action)
view_menu = self.menu_bar.addMenu("&View")
@ -904,6 +910,17 @@ class MainWindow(QMainWindow):
log.exception(f"Error opening configuration editor dialog: {e}")
QMessageBox.critical(self, "Error", f"An error occurred while opening the configuration editor:\n{e}")
@Slot() # PySide6.QtCore.Slot
def _open_definitions_editor(self):
log.debug("Opening Definitions Editor dialog.")
try:
# DefinitionsEditorDialog is imported at the top of the file
dialog = DefinitionsEditorDialog(self)
dialog.exec_() # Use exec_() for modal dialog
log.debug("Definitions Editor dialog closed.")
except Exception as e:
log.exception(f"Error opening Definitions Editor dialog: {e}")
QMessageBox.critical(self, "Error", f"An error occurred while opening the Definitions Editor:\n{e}")
@Slot(bool)
def _toggle_log_console_visibility(self, checked):