Asset-Frameworker/gui/delegates.py
2025-05-01 15:44:40 +02:00

186 lines
8.3 KiB
Python

# gui/delegates.py
from PySide6.QtWidgets import QStyledItemDelegate, QLineEdit, QComboBox
from PySide6.QtCore import Qt, QModelIndex
# Import the new config dictionaries
from config import ASSET_TYPE_DEFINITIONS, FILE_TYPE_DEFINITIONS
class LineEditDelegate(QStyledItemDelegate):
"""Delegate for editing string values using a QLineEdit."""
def createEditor(self, parent, option, index):
# Creates the QLineEdit editor widget used for editing.
editor = QLineEdit(parent)
return editor
def setEditorData(self, editor: QLineEdit, index: QModelIndex):
# Sets the editor's initial data based on the model's data.
# Use EditRole to get the raw data suitable for editing.
value = index.model().data(index, Qt.EditRole)
editor.setText(str(value) if value is not None else "")
def setModelData(self, editor: QLineEdit, model, index: QModelIndex):
# Commits the editor's data back to the model.
value = editor.text()
# Pass the potentially modified text back to the model's setData.
model.setData(index, value, Qt.EditRole)
def updateEditorGeometry(self, editor, option, index):
# Ensures the editor widget is placed correctly within the cell.
editor.setGeometry(option.rect)
class ComboBoxDelegate(QStyledItemDelegate):
"""
Delegate for editing string values from a predefined list using a QComboBox.
Determines the list source based on column index.
"""
def createEditor(self, parent, option, index: QModelIndex):
# Creates the QComboBox editor widget.
editor = QComboBox(parent)
column = index.column()
model = index.model() # Get the model instance
# Add a "clear" option first, associating None with it.
editor.addItem("---", None) # UserData = None
# Populate based on column using keys from config dictionaries
items_keys = None
if column == 2: # Asset-Type Override (AssetRule)
items_keys = list(ASSET_TYPE_DEFINITIONS.keys())
elif column == 4: # Item-Type Override (FileRule)
items_keys = list(FILE_TYPE_DEFINITIONS.keys())
if items_keys:
for item_key in sorted(items_keys): # Sort keys alphabetically for consistency
# Add item with the key string itself as text and UserData
editor.addItem(item_key, item_key)
else:
# If the delegate is incorrectly applied to another column,
# it will just have the "---" option.
pass
return editor
def setEditorData(self, editor: QComboBox, index: QModelIndex):
# Sets the combo box's current item based on the model's string data.
# Get the current string value (or None) from the model via EditRole.
value = index.model().data(index, Qt.EditRole) # This should be a string or None
idx = -1
if value is not None:
# Find the index corresponding to the string value.
idx = editor.findText(value)
else:
# If the model value is None, find the "---" item.
idx = editor.findData(None) # Find the item with UserData == None
# Set the current index, defaulting to 0 ("---") if not found.
editor.setCurrentIndex(idx if idx != -1 else 0)
def setModelData(self, editor: QComboBox, model, index: QModelIndex):
# Commits the selected combo box data (string or None) back to the model.
# Get the UserData associated with the currently selected item.
# This will be the string value or None (for the "---" option).
value = editor.currentData() # This is either the string or None
# Pass this string value or None back to the model's setData.
model.setData(index, value, Qt.EditRole)
def updateEditorGeometry(self, editor, option, index):
# Ensures the editor widget is placed correctly within the cell.
editor.setGeometry(option.rect)
# gui/delegates.py - New content to insert
import json
import logging
import os # Added for path manipulation if needed, though json.dump handles creation
from PySide6.QtWidgets import QCompleter # Added QCompleter
# Configure logging
log = logging.getLogger(__name__)
SUPPLIERS_CONFIG_PATH = "config/suppliers.json"
class SupplierSearchDelegate(QStyledItemDelegate):
"""
Delegate for editing supplier names using a QLineEdit with auto-completion.
Loads known suppliers from config/suppliers.json and allows adding new ones.
"""
def __init__(self, parent=None):
super().__init__(parent)
self.known_suppliers = self._load_suppliers()
def _load_suppliers(self):
"""Loads the list of known suppliers from the JSON config file."""
try:
with open(SUPPLIERS_CONFIG_PATH, 'r') as f:
suppliers = json.load(f)
if isinstance(suppliers, list):
# Ensure all items are strings
return sorted([str(s) for s in suppliers if isinstance(s, str)])
else:
log.warning(f"'{SUPPLIERS_CONFIG_PATH}' does not contain a valid list. Starting fresh.")
return []
except FileNotFoundError:
log.info(f"'{SUPPLIERS_CONFIG_PATH}' not found. Starting with an empty supplier list.")
return []
except json.JSONDecodeError:
log.error(f"Error decoding JSON from '{SUPPLIERS_CONFIG_PATH}'. Starting fresh.", exc_info=True)
return []
except Exception as e:
log.error(f"An unexpected error occurred loading '{SUPPLIERS_CONFIG_PATH}': {e}", exc_info=True)
return []
def _save_suppliers(self):
"""Saves the current list of known suppliers back to the JSON config file."""
try:
# Ensure the directory exists (though write_to_file handled initial creation)
os.makedirs(os.path.dirname(SUPPLIERS_CONFIG_PATH), exist_ok=True)
with open(SUPPLIERS_CONFIG_PATH, 'w') as f:
json.dump(self.known_suppliers, f, indent=4) # Save sorted list with indentation
log.debug(f"Successfully saved updated supplier list to '{SUPPLIERS_CONFIG_PATH}'.")
except IOError as e:
log.error(f"Could not write to '{SUPPLIERS_CONFIG_PATH}': {e}", exc_info=True)
except Exception as e:
log.error(f"An unexpected error occurred saving '{SUPPLIERS_CONFIG_PATH}': {e}", exc_info=True)
def createEditor(self, parent, option, index):
"""Creates the QLineEdit editor with a QCompleter."""
editor = QLineEdit(parent)
completer = QCompleter(self.known_suppliers, editor)
completer.setCaseSensitivity(Qt.CaseInsensitive)
completer.setFilterMode(Qt.MatchContains) # More flexible matching
completer.setCompletionMode(QCompleter.PopupCompletion) # Standard popup
editor.setCompleter(completer)
return editor
def setEditorData(self, editor: QLineEdit, index: QModelIndex):
"""Sets the editor's initial data from the model."""
# Use EditRole as defined in the model's data() method for supplier
value = index.model().data(index, Qt.EditRole)
editor.setText(str(value) if value is not None else "")
def setModelData(self, editor: QLineEdit, model, index: QModelIndex):
"""Commits the editor's data back to the model and handles new suppliers."""
final_text = editor.text().strip()
value_to_set = final_text if final_text else None # Set None if empty after stripping
# Set data in the model first
model.setData(index, value_to_set, Qt.EditRole)
# Add new supplier if necessary
if final_text and final_text not in self.known_suppliers:
log.info(f"Adding new supplier '{final_text}' to known list.")
self.known_suppliers.append(final_text)
self.known_suppliers.sort() # Keep the list sorted
# Update the completer's model immediately
completer = editor.completer()
if completer:
completer.model().setStringList(self.known_suppliers)
# Save the updated list back to the file
self._save_suppliers()
def updateEditorGeometry(self, editor, option, index):
"""Ensures the editor widget is placed correctly."""
editor.setGeometry(option.rect)