# radar_data_reader/gui/segment_processor_tab.py """ Defines the GUI layout and widgets for the 'Segment Processor' tab. This tab allows users to perform batch processing on previously exported flight segments. """ import tkinter as tk from tkinter import ttk from typing import List, Dict, Any, Callable class SegmentProcessorTab(ttk.Frame): """ The UI frame for the Segment Processor feature. """ def __init__(self, master: ttk.Notebook, controller: Any): super().__init__(master, padding="10") self.controller = controller self.segments_data_store: List[Dict[str, Any]] = [] # --- Tkinter Variables --- self.output_dir_var = tk.StringVar() self.generate_csv_var = tk.BooleanVar(value=True) self.generate_json_var = tk.BooleanVar(value=False) self.csv_profile_var = tk.StringVar() self.json_profile_var = tk.StringVar() self.create_separate_folders_var = tk.BooleanVar(value=True) self.csv_use_tab_var = tk.BooleanVar(value=False) self.use_full_path_var = tk.BooleanVar(value=False) self._create_widgets() def _create_widgets(self): """Creates and lays out all widgets for the tab.""" self.columnconfigure(0, weight=1) self.rowconfigure(1, weight=1) action_frame = ttk.Frame(self) action_frame.grid(row=0, column=0, sticky="ew", pady=(0, 10)) self.load_segments_button = ttk.Button( action_frame, text="Load Exported Segments from Current Flight", command=self.controller.load_segments_for_processing ) self.load_segments_button.pack(side=tk.LEFT) segments_frame = ttk.LabelFrame(self, text="Available Segments") segments_frame.grid(row=1, column=0, sticky="nsew", pady=10) segments_frame.columnconfigure(0, weight=1) segments_frame.rowconfigure(0, weight=1) self.segments_tree = ttk.Treeview( segments_frame, columns=("status", "details"), show="headings", selectmode="extended" ) self.segments_tree.heading("status", text="Status") self.segments_tree.heading("details", text="Segment Information") self.segments_tree.column("status", width=120, anchor="center", stretch=False) self.segments_tree.column("details", width=500, stretch=True) self.segments_tree.grid(row=0, column=0, sticky="nsew") scrollbar = ttk.Scrollbar(segments_frame, orient="vertical", command=self.segments_tree.yview) self.segments_tree.configure(yscrollcommand=scrollbar.set) scrollbar.grid(row=0, column=1, sticky="ns") self.segments_tree.tag_configure("ready", foreground="green") self.segments_tree.tag_configure("not_exported", foreground="gray") help_label = ttk.Label( segments_frame, text="Tip: Segments in gray are not exported and cannot be selected. Use the 'Flight Analyzer' tab to export them.", wraplength=600, justify=tk.LEFT, style="Italic.TLabel" ) help_label.grid(row=1, column=0, columnspan=2, sticky="w", padx=5, pady=5) self.master.style = ttk.Style() self.master.style.configure("Italic.TLabel", font=("", 9, "italic")) selection_frame = ttk.Frame(self) selection_frame.grid(row=2, column=0, sticky="ew", pady=(5, 10)) ttk.Button(selection_frame, text="Select All Ready", command=self._select_all_ready).pack(side=tk.LEFT) ttk.Button(selection_frame, text="Select None", command=self._select_none).pack(side=tk.LEFT, padx=5) output_config_frame = ttk.LabelFrame(self, text="Batch Processing Output Configuration") output_config_frame.grid(row=3, column=0, sticky="ew", pady=10) output_config_frame.columnconfigure(1, weight=1) # Row 0: Output Directory ttk.Label(output_config_frame, text="Output Directory:").grid(row=0, column=0, padx=5, pady=5, sticky="w") dir_entry = ttk.Entry(output_config_frame, textvariable=self.output_dir_var) dir_entry.grid(row=0, column=1, sticky="ew", padx=5) ttk.Button( output_config_frame, text="Browse...", command=lambda: self.controller.select_output_dir(self.output_dir_var) ).grid(row=0, column=2, padx=5) # Row 1 & 2: Formats and Profiles formats_frame = ttk.Frame(output_config_frame) formats_frame.grid(row=1, column=0, columnspan=3, sticky="ew", padx=10, pady=5) formats_frame.columnconfigure(1, weight=1) ttk.Checkbutton(formats_frame, text="Generate .csv file", variable=self.generate_csv_var).grid(row=0, column=0, sticky="w") self.csv_profile_combobox = ttk.Combobox(formats_frame, textvariable=self.csv_profile_var, state="readonly", width=30) self.csv_profile_combobox.grid(row=0, column=1, sticky="w") ttk.Checkbutton(formats_frame, text="Generate .json file", variable=self.generate_json_var).grid(row=1, column=0, sticky="w") self.json_profile_combobox = ttk.Combobox(formats_frame, textvariable=self.json_profile_var, state="readonly", width=30) self.json_profile_combobox.grid(row=1, column=1, sticky="w") # Row 3: Other Checkbox Options other_options_frame = ttk.Frame(output_config_frame) other_options_frame.grid(row=2, column=0, columnspan=3, sticky='w', padx=10, pady=5) ttk.Checkbutton( other_options_frame, text="Create a separate folder for each segment's analysis", variable=self.create_separate_folders_var ).pack(side=tk.LEFT, anchor="w") ttk.Checkbutton( other_options_frame, text="Use Tab Separator (CSV)", variable=self.csv_use_tab_var ).pack(side=tk.LEFT, anchor="w", padx=(20, 0)) ttk.Checkbutton( other_options_frame, text="Use Full Path for Headers", variable=self.use_full_path_var ).pack(side=tk.LEFT, anchor="w", padx=(20, 0)) self.process_button = ttk.Button( self, text="Process Selected Segments", command=self.controller.start_segment_batch_processing, state=tk.DISABLED ) self.process_button.grid(row=4, column=0, sticky="e", pady=(10, 0)) def _select_all_ready(self): self.segments_tree.selection_remove(self.segments_tree.selection()) ready_items = self.segments_tree.tag_has("ready") if ready_items: self.segments_tree.selection_set(ready_items) def _select_none(self): self.segments_tree.selection_remove(self.segments_tree.selection()) def populate_segments(self, segments_data: List[Dict[str, Any]]): self.segments_data_store = segments_data for i in self.segments_tree.get_children(): self.segments_tree.delete(i) has_selectable_items = False for segment in self.segments_data_store: # Costruisci la stringa dettagliata details = segment.get('Segment (Mode | Scale | WF)', 'Unknown Segment') start_time = segment.get('start_time_str', 'N/A') end_time = segment.get('end_time_str', 'N/A') duration = segment.get('Duration (s)', 0) details_str = f"{details} | Start: {start_time}, End: {end_time}, Duration: {duration:.2f}s" if segment.get('is_exported_and_valid'): status_text, tag = "Ready", "ready" has_selectable_items = True else: status_text, tag = "Not Exported", "not_exported" iid = segment.get('folder_name') self.segments_tree.insert("", "end", iid=iid, values=(status_text, details_str), tags=(tag,)) self.process_button.config(state=tk.NORMAL if has_selectable_items else tk.DISABLED) def get_selected_segments_data(self) -> List[Dict[str, Any]]: selected_iids = self.segments_tree.selection() selected_data = [] for segment in self.segments_data_store: if segment.get('folder_name') in selected_iids and segment.get('is_exported_and_valid'): selected_data.append(segment) return selected_data def update_export_profiles(self, profile_names: List[str], active_profile_name: str): for combo, var in [ (self.csv_profile_combobox, self.csv_profile_var), (self.json_profile_combobox, self.json_profile_var) ]: combo["values"] = profile_names if active_profile_name in profile_names: var.set(active_profile_name) elif profile_names: var.set(profile_names[0]) else: var.set("")