228 lines
8.2 KiB
Python
228 lines
8.2 KiB
Python
# target_simulator/gui/settings_window.py
|
|
|
|
"""
|
|
A Toplevel window for configuring connection settings (Serial or TFTP).
|
|
"""
|
|
|
|
import tkinter as tk
|
|
from tkinter import ttk, messagebox
|
|
from typing import Dict, Any
|
|
|
|
from target_simulator.core.serial_communicator import SerialCommunicator, SERIAL_PARAMS
|
|
from target_simulator.core.tftp_communicator import TFTPCommunicator
|
|
from target_simulator.utils.config_manager import ConfigManager
|
|
|
|
|
|
class SettingsWindow(tk.Toplevel):
|
|
"""A dialog window for connection settings."""
|
|
|
|
def __init__(
|
|
self, master, config_manager: ConfigManager, current_config: Dict[str, Any]
|
|
):
|
|
super().__init__(master)
|
|
self.master_view = master
|
|
self.config_manager = config_manager
|
|
|
|
self.title("Connection Settings")
|
|
self.transient(master)
|
|
self.grab_set()
|
|
self.resizable(False, False)
|
|
|
|
# --- Variables ---
|
|
self.comm_type_var = tk.StringVar(value=current_config.get("type", "serial"))
|
|
self.serial_config_vars = self._setup_serial_vars(
|
|
current_config.get("serial", {})
|
|
)
|
|
self.tftp_config_vars = self._setup_tftp_vars(current_config.get("tftp", {}))
|
|
|
|
# --- UI Creation ---
|
|
main_frame = ttk.Frame(self, padding="10")
|
|
main_frame.pack(fill=tk.BOTH, expand=True)
|
|
|
|
self._create_type_selector(main_frame)
|
|
|
|
# --- Configuration Frames ---
|
|
self.serial_frame = self._create_serial_frame(main_frame)
|
|
self.tftp_frame = self._create_tftp_frame(main_frame)
|
|
|
|
self._create_buttons(main_frame)
|
|
|
|
# --- Initial State ---
|
|
self._on_comm_type_change()
|
|
|
|
self.protocol("WM_DELETE_WINDOW", self.destroy)
|
|
self.wait_window(self)
|
|
|
|
def _setup_serial_vars(self, config: Dict) -> Dict[str, tk.StringVar]:
|
|
return {
|
|
"port": tk.StringVar(value=config.get("port", "")),
|
|
"baudrate": tk.StringVar(value=config.get("baudrate", "115200")),
|
|
"bytesize": tk.StringVar(value=config.get("bytesize", "8")),
|
|
"parity": tk.StringVar(value=config.get("parity", "N")),
|
|
"stopbits": tk.StringVar(value=config.get("stopbits", "1")),
|
|
}
|
|
|
|
def _setup_tftp_vars(self, config: Dict) -> Dict[str, tk.StringVar]:
|
|
return {
|
|
"ip": tk.StringVar(value=config.get("ip", "127.0.0.1")),
|
|
"port": tk.StringVar(value=config.get("port", "69")),
|
|
}
|
|
|
|
def _create_type_selector(self, parent):
|
|
frame = ttk.LabelFrame(parent, text="Communication Type", padding=10)
|
|
frame.pack(fill=tk.X, pady=(0, 10))
|
|
|
|
ttk.Radiobutton(
|
|
frame,
|
|
text="Serial",
|
|
variable=self.comm_type_var,
|
|
value="serial",
|
|
command=self._on_comm_type_change,
|
|
).pack(side=tk.LEFT, padx=10)
|
|
|
|
ttk.Radiobutton(
|
|
frame,
|
|
text="TFTP",
|
|
variable=self.comm_type_var,
|
|
value="tftp",
|
|
command=self._on_comm_type_change,
|
|
).pack(side=tk.LEFT, padx=10)
|
|
|
|
def _create_serial_frame(self, parent) -> ttk.Frame:
|
|
frame = ttk.LabelFrame(parent, text="Serial Port Settings", padding=10)
|
|
|
|
# Grid layout for alignment
|
|
frame.columnconfigure(1, weight=1)
|
|
|
|
# Port
|
|
ttk.Label(frame, text="Port:").grid(row=0, column=0, sticky=tk.W, pady=2)
|
|
port_combo = ttk.Combobox(
|
|
frame, textvariable=self.serial_config_vars["port"], state="readonly"
|
|
)
|
|
port_combo.grid(row=0, column=1, sticky=tk.EW, padx=5, pady=2)
|
|
self._populate_ports(port_combo)
|
|
|
|
# Baudrate
|
|
ttk.Label(frame, text="Baud Rate:").grid(row=1, column=0, sticky=tk.W, pady=2)
|
|
baud_combo = ttk.Combobox(
|
|
frame,
|
|
textvariable=self.serial_config_vars["baudrate"],
|
|
values=SERIAL_PARAMS["baudrates"],
|
|
state="readonly",
|
|
)
|
|
baud_combo.grid(row=1, column=1, sticky=tk.EW, padx=5, pady=2)
|
|
|
|
# Parity
|
|
ttk.Label(frame, text="Parity:").grid(row=2, column=0, sticky=tk.W, pady=2)
|
|
parity_combo = ttk.Combobox(
|
|
frame,
|
|
textvariable=self.serial_config_vars["parity"],
|
|
values=list(SERIAL_PARAMS["parities"]),
|
|
state="readonly",
|
|
)
|
|
parity_combo.grid(row=2, column=1, sticky=tk.EW, padx=5, pady=2)
|
|
|
|
return frame
|
|
|
|
def _create_tftp_frame(self, parent) -> ttk.Frame:
|
|
frame = ttk.LabelFrame(parent, text="TFTP Server Settings", padding=10)
|
|
frame.columnconfigure(1, weight=1)
|
|
|
|
# IP Address
|
|
ttk.Label(frame, text="Server IP:").grid(row=0, column=0, sticky=tk.W, pady=2)
|
|
ttk.Entry(frame, textvariable=self.tftp_config_vars["ip"]).grid(
|
|
row=0, column=1, sticky=tk.EW, padx=5, pady=2
|
|
)
|
|
|
|
# Port
|
|
ttk.Label(frame, text="Server Port:").grid(row=1, column=0, sticky=tk.W, pady=2)
|
|
ttk.Entry(frame, textvariable=self.tftp_config_vars["port"]).grid(
|
|
row=1, column=1, sticky=tk.EW, padx=5, pady=2
|
|
)
|
|
|
|
return frame
|
|
|
|
def _create_buttons(self, parent):
|
|
frame = ttk.Frame(parent, padding=(0, 10, 0, 0))
|
|
frame.pack(fill=tk.X)
|
|
|
|
ttk.Button(
|
|
frame, text="Test Connection", command=self._on_test_connection
|
|
).pack(side=tk.LEFT, padx=(0, 10))
|
|
|
|
# Right-align Save and Cancel
|
|
ttk.Button(frame, text="Cancel", command=self.destroy).pack(side=tk.RIGHT)
|
|
ttk.Button(frame, text="Save", command=self._on_save).pack(
|
|
side=tk.RIGHT, padx=5
|
|
)
|
|
|
|
def _on_comm_type_change(self):
|
|
"""Show/hide frames based on the selected communication type."""
|
|
selected_type = self.comm_type_var.get()
|
|
if selected_type == "serial":
|
|
self.tftp_frame.pack_forget()
|
|
self.serial_frame.pack(fill=tk.X, expand=True)
|
|
elif selected_type == "tftp":
|
|
self.serial_frame.pack_forget()
|
|
self.tftp_frame.pack(fill=tk.X, expand=True)
|
|
|
|
def _populate_ports(self, combobox: ttk.Combobox):
|
|
"""Fetches and displays available serial ports."""
|
|
available_ports = SerialCommunicator.list_available_ports()
|
|
if available_ports:
|
|
combobox["values"] = available_ports
|
|
if not self.serial_config_vars["port"].get():
|
|
self.serial_config_vars["port"].set(available_ports[0])
|
|
else:
|
|
combobox["values"] = ["No ports found"]
|
|
self.serial_config_vars["port"].set("No ports found")
|
|
|
|
def _on_test_connection(self):
|
|
"""Tests the connection for the currently selected mode."""
|
|
comm_type = self.comm_type_var.get()
|
|
is_success = False
|
|
config = {}
|
|
|
|
if comm_type == "serial":
|
|
config = {key: var.get() for key, var in self.serial_config_vars.items()}
|
|
is_success = SerialCommunicator.test_connection(config)
|
|
else: # tftp
|
|
config = {key: var.get() for key, var in self.tftp_config_vars.items()}
|
|
is_success = TFTPCommunicator.test_connection(config)
|
|
|
|
if is_success:
|
|
messagebox.showinfo(
|
|
"Success",
|
|
f"Connection test successful for {comm_type.upper()}.",
|
|
parent=self,
|
|
)
|
|
else:
|
|
messagebox.showerror(
|
|
"Failure",
|
|
f"Failed to connect using {comm_type.upper()} settings.",
|
|
parent=self,
|
|
)
|
|
|
|
def _on_save(self):
|
|
"""Saves the selected settings and closes the window."""
|
|
comm_type = self.comm_type_var.get()
|
|
# Recupera la configurazione corrente
|
|
current = (
|
|
self.master_view.connection_config
|
|
if hasattr(self.master_view, "connection_config")
|
|
else {}
|
|
)
|
|
serial_conf = current.get("serial", {})
|
|
tftp_conf = current.get("tftp", {})
|
|
|
|
if comm_type == "serial":
|
|
serial_conf = {
|
|
key: var.get() for key, var in self.serial_config_vars.items()
|
|
}
|
|
else:
|
|
tftp_conf = {key: var.get() for key, var in self.tftp_config_vars.items()}
|
|
|
|
full_config = {"type": comm_type, "serial": serial_conf, "tftp": tftp_conf}
|
|
self.master_view.update_connection_settings(full_config)
|
|
self.destroy()
|