# FlightMonitor/gui/panels/data_logging_panel.py """ Defines the GUI panel for controlling raw data logging functionality. This panel is designed to be shared across different monitoring modes. """ import tkinter as tk from tkinter import ttk, filedialog, font as tkFont from typing import Optional, Any from datetime import datetime, timezone from flightmonitor.utils.logger import get_logger module_logger = get_logger(__name__) class DataLoggingPanel: """ Manages the GUI elements for enabling and configuring raw data logging. """ def __init__(self, parent_frame: ttk.Frame, controller: Any): """ Initializes the DataLoggingPanel. Args: parent_frame: The parent ttk.Frame where this panel will be placed. controller: The application controller instance. """ self.parent_frame = parent_frame self.controller = controller # --- Tkinter Variables --- self.enable_logging_var = tk.BooleanVar(value=False) self.log_directory_var = tk.StringVar(value="") self.last_query_result_var = tk.StringVar(value="Last query result: N/A") # --- Widget References --- self.log_dir_entry: Optional[ttk.Entry] = None self.browse_button: Optional[ttk.Button] = None self.open_folder_button: Optional[ttk.Button] = None # MODIFICATO: Aggiunto riferimento self.summary_table: Optional[ttk.Treeview] = None self._build_ui() module_logger.debug("DataLoggingPanel initialized.") def _build_ui(self): """Builds all the widgets for the panel.""" container = ttk.LabelFrame( self.parent_frame, text="Data Logging Session", padding=10 ) container.pack(fill=tk.X, expand=True, padx=2, pady=5) self.enable_checkbox = ttk.Checkbutton( container, text="Enable Raw Data Logging", variable=self.enable_logging_var, command=self._on_toggle_logging, ) self.enable_checkbox.pack(anchor=tk.W, pady=(0, 5)) dir_frame = ttk.Frame(container) dir_frame.pack(fill=tk.X, expand=True) dir_frame.columnconfigure(1, weight=1) ttk.Label(dir_frame, text="Save to:").grid( row=0, column=0, sticky=tk.W, padx=(0, 5) ) self.log_dir_entry = ttk.Entry( dir_frame, textvariable=self.log_directory_var, state=tk.DISABLED ) self.log_dir_entry.grid(row=0, column=1, sticky=tk.EW) # MODIFICATO: Aggiunto il nuovo pulsante "Open Folder" self.browse_button = ttk.Button( dir_frame, text="Browse...", command=self._on_browse_directory, state=tk.DISABLED, ) self.browse_button.grid(row=0, column=2, sticky=tk.E, padx=(5, 2)) self.open_folder_button = ttk.Button( dir_frame, text="Open Folder", command=self._on_open_folder, state=tk.DISABLED ) self.open_folder_button.grid(row=0, column=3, sticky=tk.E, padx=(2, 0)) # --- FINE MODIFICA --- last_result_font = tkFont.Font(family="Helvetica", size=9, slant="italic") last_result_label = ttk.Label( container, textvariable=self.last_query_result_var, font=last_result_font, foreground="navy" ) last_result_label.pack(anchor=tk.W, pady=(8, 2)) table_frame = ttk.Frame(container) table_frame.pack(fill=tk.BOTH, expand=True, pady=(2, 0)) self.summary_table = ttk.Treeview( table_frame, columns=("timestamp", "count"), show="headings", height=4 ) self.summary_table.heading("timestamp", text="Fetch Timestamp (UTC)") self.summary_table.heading("count", text="Aircraft Count") self.summary_table.column("timestamp", width=160, anchor=tk.W) self.summary_table.column("count", width=100, anchor=tk.CENTER) scrollbar = ttk.Scrollbar( table_frame, orient="vertical", command=self.summary_table.yview ) self.summary_table.configure(yscrollcommand=scrollbar.set) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) self.summary_table.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) def _on_toggle_logging(self): is_enabled = self.enable_logging_var.get() new_state = tk.NORMAL if is_enabled else tk.DISABLED if self.log_dir_entry: self.log_dir_entry.config(state=new_state) if self.browse_button: self.browse_button.config(state=new_state) # MODIFICATO: Abilita/disabilita anche il nuovo pulsante if self.open_folder_button: self.open_folder_button.config(state=new_state) module_logger.info(f"Raw data logging has been {'enabled' if is_enabled else 'disabled'} by user.") def _on_browse_directory(self): directory = filedialog.askdirectory( title="Select Directory to Save Raw Data", parent=self.parent_frame ) if directory: self.log_directory_var.set(directory) module_logger.info(f"User selected new log directory: {directory}") # MODIFICATO: Aggiunto il metodo callback per "Open Folder" def _on_open_folder(self): """Callback for the 'Open Folder' button.""" directory_path = self.get_log_directory() if self.controller and hasattr(self.controller, 'open_log_directory'): self.controller.open_log_directory(directory_path) else: module_logger.error("Controller or 'open_log_directory' method not available.") def is_logging_enabled(self) -> bool: return self.enable_logging_var.get() def get_log_directory(self) -> str: return self.log_directory_var.get() def add_summary_entry(self, timestamp: float, count: int): if not self.summary_table or not self.summary_table.winfo_exists(): return try: dt_object = datetime.fromtimestamp(timestamp, timezone.utc) time_str = dt_object.strftime("%Y-%m-%d %H:%M:%S") self.summary_table.insert("", 0, values=(time_str, count)) except (ValueError, TypeError) as e: module_logger.error(f"Failed to add summary entry to table: {e}") except tk.TclError: module_logger.warning("TclError adding summary to table, widget likely destroyed.") def update_last_query_result(self, timestamp: float, count: int): try: dt_object = datetime.fromtimestamp(timestamp, timezone.utc) time_str = dt_object.strftime("%H:%M:%S") result_text = f"Last query result: {count} aircraft at {time_str} UTC" self.last_query_result_var.set(result_text) except (ValueError, TypeError): self.last_query_result_var.set("Last query result: Invalid timestamp") except tk.TclError: module_logger.warning("TclError updating last query label, widget likely destroyed.") def clear_summary_table(self): if not self.summary_table or not self.summary_table.winfo_exists(): return self.last_query_result_var.set("Last query result: N/A") try: for item in self.summary_table.get_children(): self.summary_table.delete(item) module_logger.info("Data logging summary table cleared.") except tk.TclError: module_logger.warning("TclError clearing summary table, widget likely destroyed.") def update_settings(self, enabled: bool, directory: str): self.enable_logging_var.set(enabled) self.log_directory_var.set(directory) self._on_toggle_logging() module_logger.debug(f"DataLoggingPanel settings updated: enabled={enabled}, dir='{directory}'")