240 lines
11 KiB
Python
240 lines
11 KiB
Python
# LauncherTool/gui/dialogs/parameter_dialogs.py
|
|
"""
|
|
Dialogs for adding and editing application parameters.
|
|
"""
|
|
import tkinter as tk
|
|
from tkinter import ttk, messagebox
|
|
import logging
|
|
from typing import Optional, Dict, Any, Callable # Aggiunto Callable
|
|
|
|
from ..utils_gui import GuiUtils
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class BaseParameterDialog(tk.Toplevel):
|
|
"""
|
|
Base class for Add and Edit Parameter dialogs.
|
|
"""
|
|
def __init__(self, parent: tk.Widget, title: str, load_data_method: Optional[Callable[[], None]] = None): # Aggiunto load_data_method
|
|
logger.debug(f"BaseParameterDialog __init__ - START - Title: '{title}'")
|
|
super().__init__(parent)
|
|
self.transient(parent)
|
|
self.title(title)
|
|
self.parent_widget = parent
|
|
self.result: Optional[Dict[str, Any]] = None
|
|
|
|
self._parameter_types = ["string", "integer", "boolean", "float", "file", "folder"]
|
|
|
|
logger.debug("BaseParameterDialog: Calling _setup_widgets()")
|
|
self._setup_widgets()
|
|
logger.debug("BaseParameterDialog: _setup_widgets() completed.")
|
|
|
|
# === MODIFICA CHIAVE ===
|
|
if load_data_method:
|
|
logger.debug("BaseParameterDialog: Calling provided load_data_method.")
|
|
load_data_method()
|
|
logger.debug("BaseParameterDialog: load_data_method completed.")
|
|
else:
|
|
logger.debug("BaseParameterDialog: No load_data_method provided.")
|
|
# =======================
|
|
|
|
GuiUtils.center_window(self, parent)
|
|
self.protocol("WM_DELETE_WINDOW", self._on_cancel)
|
|
|
|
self.grab_set()
|
|
self.focus_set()
|
|
logger.debug(f"BaseParameterDialog __init__ for '{title}': Now calling wait_window().")
|
|
self.wait_window(self)
|
|
logger.debug(f"BaseParameterDialog __init__ - END - Title: '{title}' (after wait_window)")
|
|
|
|
def _setup_widgets(self):
|
|
main_frame = ttk.Frame(self, padding="10")
|
|
main_frame.pack(expand=True, fill=tk.BOTH)
|
|
|
|
# --- Parameter Name ---
|
|
name_frame = ttk.Frame(main_frame)
|
|
name_frame.pack(fill=tk.X, pady=(0, 5))
|
|
ttk.Label(name_frame, text="Name:").grid(row=0, column=0, sticky=tk.W, padx=(0,5))
|
|
self.name_entry_var = tk.StringVar()
|
|
self.name_entry = ttk.Entry(name_frame, textvariable=self.name_entry_var, width=40)
|
|
self.name_entry.grid(row=0, column=1, sticky=tk.EW)
|
|
name_frame.columnconfigure(1, weight=1)
|
|
|
|
# --- Description ---
|
|
desc_frame = ttk.Frame(main_frame)
|
|
desc_frame.pack(fill=tk.X, pady=(0, 5))
|
|
ttk.Label(desc_frame, text="Description:").grid(row=0, column=0, sticky=tk.NW, padx=(0,5))
|
|
# Assicurati che self.description_text sia creato correttamente
|
|
self.description_text = tk.Text(desc_frame, width=40, height=4, wrap=tk.WORD)
|
|
self.description_text.grid(row=0, column=1, sticky=tk.EW)
|
|
desc_scrollbar = ttk.Scrollbar(desc_frame, orient=tk.VERTICAL, command=self.description_text.yview)
|
|
desc_scrollbar.grid(row=0, column=2, sticky=tk.NS)
|
|
self.description_text.config(yscrollcommand=desc_scrollbar.set)
|
|
desc_frame.columnconfigure(1, weight=1)
|
|
|
|
# --- Default Value ---
|
|
def_val_frame = ttk.Frame(main_frame)
|
|
def_val_frame.pack(fill=tk.X, pady=(0, 5))
|
|
ttk.Label(def_val_frame, text="Default Value:").grid(row=0, column=0, sticky=tk.W, padx=(0,5))
|
|
self.default_value_entry_var = tk.StringVar()
|
|
self.default_value_entry = ttk.Entry(def_val_frame, textvariable=self.default_value_entry_var, width=40)
|
|
self.default_value_entry.grid(row=0, column=1, sticky=tk.EW)
|
|
def_val_frame.columnconfigure(1, weight=1)
|
|
|
|
# --- Parameter Type ---
|
|
type_frame = ttk.Frame(main_frame)
|
|
type_frame.pack(fill=tk.X, pady=(0, 10))
|
|
ttk.Label(type_frame, text="Type:").grid(row=0, column=0, sticky=tk.W, padx=(0,5))
|
|
self.type_combo_var = tk.StringVar()
|
|
self.type_combo = ttk.Combobox(
|
|
type_frame,
|
|
textvariable=self.type_combo_var,
|
|
values=self._parameter_types,
|
|
state="readonly",
|
|
width=38
|
|
)
|
|
self.type_combo.grid(row=0, column=1, sticky=tk.EW)
|
|
self.type_combo.set("string")
|
|
type_frame.columnconfigure(1, weight=1)
|
|
|
|
|
|
# --- Dialog Buttons (Save, Cancel) ---
|
|
dialog_buttons_frame = ttk.Frame(main_frame)
|
|
dialog_buttons_frame.pack(fill=tk.X, pady=(10, 0))
|
|
ttk.Frame(dialog_buttons_frame).pack(side=tk.LEFT, expand=True)
|
|
|
|
self.save_button = ttk.Button(dialog_buttons_frame, text="Save", command=self._on_save)
|
|
self.save_button.pack(side=tk.LEFT, padx=(0,5))
|
|
self.cancel_button = ttk.Button(dialog_buttons_frame, text="Cancel", command=self._on_cancel)
|
|
self.cancel_button.pack(side=tk.LEFT)
|
|
|
|
|
|
def _validate_inputs(self) -> bool:
|
|
name = self.name_entry_var.get().strip()
|
|
if not name:
|
|
messagebox.showerror("Validation Error", "Parameter Name cannot be empty.", parent=self)
|
|
self.name_entry.focus_set()
|
|
return False
|
|
return True
|
|
|
|
def _on_save(self):
|
|
raise NotImplementedError("Subclasses must implement _on_save")
|
|
|
|
def _on_cancel(self):
|
|
logger.debug(f"BaseParameterDialog: '{self.title()}' cancelled or closed by user.")
|
|
self.result = None
|
|
self.destroy()
|
|
|
|
|
|
class AddParameterDialog(BaseParameterDialog):
|
|
"""Dialog for adding a new application parameter."""
|
|
def __init__(self, parent: tk.Widget):
|
|
# Non serve caricare dati
|
|
super().__init__(parent, title="Add New Parameter", load_data_method=None)
|
|
logger.debug("AddParameterDialog __init__ completed.")
|
|
|
|
|
|
def _on_save(self):
|
|
if not self._validate_inputs():
|
|
return
|
|
|
|
param_name = self.name_entry_var.get().strip()
|
|
param_description = self.description_text.get("1.0", tk.END).strip()
|
|
param_default_value = self.default_value_entry_var.get()
|
|
param_type = self.type_combo_var.get()
|
|
|
|
self.result = {
|
|
"name": param_name,
|
|
"description": param_description,
|
|
"default_value": param_default_value,
|
|
"type": param_type
|
|
}
|
|
logger.info(f"AddParameterDialog: Parameter '{param_name}' data prepared.")
|
|
self.destroy()
|
|
|
|
|
|
class EditParameterDialog(BaseParameterDialog):
|
|
"""Dialog for editing an existing application parameter."""
|
|
def __init__(self, parent: tk.Widget, parameter_data_to_edit: Dict[str, Any]):
|
|
logger.debug(f"EditParameterDialog __init__ - START - Parameter to edit: {parameter_data_to_edit.get('name', 'N/A')}")
|
|
self.parameter_data_to_edit = parameter_data_to_edit # Imposta PRIMA di super()
|
|
|
|
# Passa il metodo _load_initial_data a super()
|
|
param_name_for_title = parameter_data_to_edit.get('name', 'Unknown')
|
|
super().__init__(parent, title=f"Edit Parameter: {param_name_for_title}", load_data_method=self._load_initial_data)
|
|
|
|
# Il codice qui viene eseguito solo dopo la chiusura del dialogo (wait_window)
|
|
logger.debug(f"EditParameterDialog __init__ - END - for '{param_name_for_title}' (after super call completed)")
|
|
|
|
def _load_initial_data(self):
|
|
# Chiamato da BaseParameterDialog.__init__
|
|
if not self.parameter_data_to_edit:
|
|
logger.error("EditParameterDialog _load_initial_data: parameter_data_to_edit is missing.")
|
|
if self.parent_widget:
|
|
messagebox.showerror("Initialization Error",
|
|
"Cannot edit parameter: Initial data is missing.",
|
|
parent=self.parent_widget) # Mostra su ApplicationDialog
|
|
self.after_idle(self.destroy)
|
|
return
|
|
|
|
param_name = self.parameter_data_to_edit.get("name", "")
|
|
logger.debug(f"EditParameterDialog _load_initial_data: Loading data for parameter '{param_name}'")
|
|
try:
|
|
self.name_entry_var.set(param_name)
|
|
|
|
# Pulisci e inserisci nella Textbox
|
|
self.description_text.delete("1.0", tk.END) # Tenta di pulire
|
|
self.description_text.insert("1.0", self.parameter_data_to_edit.get("description", "")) # Tenta di inserire
|
|
logger.debug(f"EditParameterDialog _load_initial_data: Description set in Text widget.")
|
|
|
|
self.default_value_entry_var.set(self.parameter_data_to_edit.get("default_value", ""))
|
|
|
|
param_type = self.parameter_data_to_edit.get("type", "string")
|
|
if param_type in self._parameter_types:
|
|
self.type_combo_var.set(param_type)
|
|
else:
|
|
logger.warning(f"EditParameterDialog: Unknown type '{param_type}' for param '{param_name}'. Defaulting to 'string'.")
|
|
self.type_combo_var.set("string")
|
|
|
|
logger.info(f"EditParameterDialog _load_initial_data: Data loaded successfully for '{param_name}'.")
|
|
|
|
except tk.TclError as e: # Cattura specificamente l'errore TclError
|
|
logger.error(f"EditParameterDialog _load_initial_data: TclError operating on widget (likely description_text): {e}", exc_info=True)
|
|
if self.parent_widget:
|
|
messagebox.showerror("Widget Error",
|
|
f"Error loading data into the description field for '{param_name}'.\n"
|
|
"The dialog might not have initialized correctly.",
|
|
parent=self.parent_widget)
|
|
self.after_idle(self.destroy) # Chiudi se il widget non è utilizzabile
|
|
except Exception as e: # Cattura altri errori
|
|
logger.error(f"EditParameterDialog _load_initial_data: Unexpected error loading data for '{param_name}': {e}", exc_info=True)
|
|
if self.parent_widget:
|
|
messagebox.showerror("Load Error",
|
|
f"Could not load data for parameter '{param_name}':\n{e}",
|
|
parent=self.parent_widget)
|
|
self.after_idle(self.destroy)
|
|
|
|
|
|
def _on_save(self):
|
|
if not self.parameter_data_to_edit: # Sicurezza se _load fallisce
|
|
messagebox.showerror("Save Error", "Cannot save: Initial parameter data was not loaded correctly.", parent=self)
|
|
logger.error("EditParameterDialog _on_save: Attempted to save without valid initial data.")
|
|
return
|
|
|
|
if not self._validate_inputs():
|
|
return
|
|
|
|
new_param_name = self.name_entry_var.get().strip()
|
|
new_param_description = self.description_text.get("1.0", tk.END).strip()
|
|
new_param_default_value = self.default_value_entry_var.get()
|
|
new_param_type = self.type_combo_var.get()
|
|
|
|
self.result = {
|
|
"name": new_param_name,
|
|
"description": new_param_description,
|
|
"default_value": new_param_default_value,
|
|
"type": new_param_type
|
|
}
|
|
original_param_name = self.parameter_data_to_edit.get('name', 'N/A')
|
|
logger.info(f"EditParameterDialog: Parameter data for '{new_param_name}' (original: '{original_param_name}') prepared.")
|
|
self.destroy() |