S1005403_RisCC/target_simulator/gui/connection_settings_window.py
VALLONGOL 3b447d7fdb fix save/new/load scenario
minor fix in gui
2025-10-07 14:40:52 +02:00

208 lines
9.0 KiB
Python

# target_simulator/gui/connection_settings_window.py
"""
Toplevel window for configuring Target and LRU connections.
"""
import tkinter as tk
from tkinter import ttk, messagebox
class ConnectionSettingsWindow(tk.Toplevel):
"""A dialog for configuring connection settings."""
def __init__(self, master, config_manager, connection_config):
super().__init__(master)
self.master_view = master
self.config_manager = config_manager
self.connection_config = connection_config
self.title("Connection Settings")
self.transient(master)
self.grab_set()
self.resizable(False, False)
self._create_widgets()
self._load_settings()
self.protocol("WM_DELETE_WINDOW", self._on_cancel)
# Center the window on the main view
self.update_idletasks()
main_x = master.winfo_rootx()
main_y = master.winfo_rooty()
main_w = master.winfo_width()
main_h = master.winfo_height()
win_w = self.winfo_width()
win_h = self.winfo_height()
x = main_x + (main_w // 2) - (win_w // 2)
y = main_y + (main_h // 2) - (win_h // 2)
self.geometry(f"{win_w}x{win_h}+{x}+{y}")
def _load_settings(self):
# --- Load Target Settings ---
target_cfg = self.connection_config.get('target', {})
self.target_vars['conn_type'].set("Serial" if target_cfg.get('type', 'TFTP').lower() == "serial" else "TFTP")
self.target_vars['tftp_ip'].set(target_cfg.get('tftp', {}).get('ip', '127.0.0.1'))
self.target_vars['tftp_port'].set(target_cfg.get('tftp', {}).get('port', 69))
self.target_vars['serial_port'].set(target_cfg.get('serial', {}).get('port', 'COM1'))
self.target_vars['serial_baud'].set(target_cfg.get('serial', {}).get('baudrate', 9600))
self._switch_view(self.target_vars)
# --- Load LRU Settings ---
lru_cfg = self.connection_config.get('lru', {})
self.lru_vars['conn_type'].set("Serial" if lru_cfg.get('type', 'TFTP').lower() == "serial" else "TFTP")
self.lru_vars['tftp_ip'].set(lru_cfg.get('tftp', {}).get('ip', '127.0.0.1'))
self.lru_vars['tftp_port'].set(lru_cfg.get('tftp', {}).get('port', 69))
self.lru_vars['serial_port'].set(lru_cfg.get('serial', {}).get('port', 'COM1'))
self.lru_vars['serial_baud'].set(lru_cfg.get('serial', {}).get('baudrate', 9600))
self._switch_view(self.lru_vars)
def _create_widgets(self):
main_frame = ttk.Frame(self, padding="10")
main_frame.pack(fill=tk.BOTH, expand=True)
# --- Target Connection Frame ---
target_frame = ttk.LabelFrame(main_frame, text="Target Connection")
target_frame.pack(fill=tk.X, expand=True, pady=5, padx=5)
self.target_vars = self._create_connection_panel(target_frame, "Target")
# --- LRU Connection Frame ---
lru_frame = ttk.LabelFrame(main_frame, text="LRU Connection")
lru_frame.pack(fill=tk.X, expand=True, pady=5, padx=5)
self.lru_vars = self._create_connection_panel(lru_frame, "LRU")
# --- Buttons ---
button_frame = ttk.Frame(main_frame)
button_frame.pack(pady=10, fill=tk.X, side=tk.BOTTOM)
ttk.Button(button_frame, text="Save", command=self._on_save).pack(side=tk.RIGHT, padx=5)
ttk.Button(button_frame, text="Cancel", command=self._on_cancel).pack(side=tk.RIGHT, padx=5)
def _create_connection_panel(self, parent_frame, name):
vars = {}
# --- Connection Type Selection ---
conn_type_frame = ttk.Frame(parent_frame)
conn_type_frame.pack(fill=tk.X, padx=5, pady=(5,10))
vars['conn_type'] = tk.StringVar()
ttk.Label(conn_type_frame, text="Type:").pack(side=tk.LEFT)
ttk.Radiobutton(conn_type_frame, text="TFTP", variable=vars['conn_type'], value="TFTP", command=lambda: self._switch_view(vars)).pack(side=tk.LEFT, padx=5)
ttk.Radiobutton(conn_type_frame, text="Serial", variable=vars['conn_type'], value="Serial", command=lambda: self._switch_view(vars)).pack(side=tk.LEFT, padx=5)
# --- Configuration Frames (TFTP and Serial) ---
vars['tftp_frame'] = ttk.Frame(parent_frame, padding=5)
vars['serial_frame'] = ttk.Frame(parent_frame, padding=5)
# --- TFTP Widgets ---
tftp_grid = vars['tftp_frame']
ttk.Label(tftp_grid, text="IP Address:").grid(row=0, column=0, sticky=tk.W, pady=2)
vars['tftp_ip'] = tk.StringVar()
ttk.Entry(tftp_grid, textvariable=vars['tftp_ip']).grid(row=0, column=1, sticky=tk.EW, padx=5)
ttk.Label(tftp_grid, text="Port:").grid(row=1, column=0, sticky=tk.W, pady=2)
vars['tftp_port'] = tk.IntVar()
ttk.Spinbox(tftp_grid, from_=1, to=65535, textvariable=vars['tftp_port'], width=7).grid(row=1, column=1, sticky=tk.W, padx=5)
tftp_grid.columnconfigure(1, weight=1)
# --- Serial Widgets ---
serial_grid = vars['serial_frame']
ttk.Label(serial_grid, text="COM Port:").grid(row=0, column=0, sticky=tk.W, pady=2)
vars['serial_port'] = tk.StringVar()
# In a real app, you might want to auto-detect available ports
ttk.Combobox(serial_grid, textvariable=vars['serial_port'], values=[f"COM{i}" for i in range(1, 17)]).grid(row=0, column=1, sticky=tk.EW, padx=5)
ttk.Label(serial_grid, text="Baud Rate:").grid(row=1, column=0, sticky=tk.W, pady=2)
vars['serial_baud'] = tk.IntVar()
baud_rates = [9600, 19200, 38400, 57600, 115200]
ttk.Combobox(serial_grid, textvariable=vars['serial_baud'], values=baud_rates, width=7).grid(row=1, column=1, sticky=tk.W, padx=5)
serial_grid.columnconfigure(1, weight=1)
# --- Test Button ---
test_button = ttk.Button(parent_frame, text="Test Connection", command=lambda: self._test_connection(name, vars))
test_button.pack(pady=5, padx=5, anchor=tk.E)
# Initial view setup is now done in _load_settings
# self._switch_view(vars)
return vars
def _switch_view(self, vars):
conn_type = vars['conn_type'].get()
if conn_type == "TFTP":
vars['serial_frame'].pack_forget()
vars['tftp_frame'].pack(fill=tk.X, expand=True, padx=5, pady=5)
else: # Serial
vars['tftp_frame'].pack_forget()
vars['serial_frame'].pack(fill=tk.X, expand=True, padx=5, pady=5)
def _test_connection(self, name, vars):
conn_type = vars['conn_type'].get()
result = False
error = None
if conn_type == "TFTP":
ip = vars['tftp_ip'].get()
port = vars['tftp_port'].get()
try:
port = int(port)
from core.tftp_communicator import TFTPCommunicator
comm = TFTPCommunicator()
result = comm.connect({'ip': ip, 'port': port})
except Exception as e:
error = str(e)
else: # Serial
serial_port = vars['serial_port'].get()
baudrate = vars['serial_baud'].get()
try:
baudrate = int(baudrate)
from core.serial_communicator import SerialCommunicator
comm = SerialCommunicator()
result = comm.connect({'port': serial_port, 'baudrate': baudrate})
except Exception as e:
error = str(e)
if result:
messagebox.showinfo("Connection Test", f"{name} connection successful!", parent=self)
else:
msg = f"{name} connection failed."
if error:
msg += f"\nError: {error}"
messagebox.showerror("Connection Test", msg, parent=self)
def _on_save(self):
# Save Target and LRU connection configs in a consistent structure
new_config = {
'target': {
'type': self.target_vars['conn_type'].get().lower(),
'tftp': {
'ip': self.target_vars['tftp_ip'].get(),
'port': self.target_vars['tftp_port'].get()
},
'serial': {
'port': self.target_vars['serial_port'].get(),
'baudrate': self.target_vars['serial_baud'].get()
}
},
'lru': {
'type': self.lru_vars['conn_type'].get().lower(),
'tftp': {
'ip': self.lru_vars['tftp_ip'].get(),
'port': self.lru_vars['tftp_port'].get()
},
'serial': {
'port': self.lru_vars['serial_port'].get(),
'baudrate': self.lru_vars['serial_baud'].get()
}
}
}
self.master_view.update_connection_settings(new_config)
print("Settings saved and applied.")
self.destroy()
def _on_cancel(self):
self.destroy()
if __name__ == '__main__':
# Example usage for testing
root = tk.Tk()
root.withdraw() # Hide the root window
app = ConnectionSettingsWindow(root)
root.wait_window(app)
root.destroy()