193 lines
8.7 KiB
Python
193 lines
8.7 KiB
Python
# 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("") |