From e2e1fdd2a03e2f49cf69f522c043027b2fb7623b Mon Sep 17 00:00:00 2001 From: Jeremy Shen Date: Fri, 12 Jun 2026 10:20:07 +0800 Subject: [PATCH] fix: tag_config for CTkTextbox + auto-save on file selection - StatusDisplay: use tag_config (not tag_configure) for CTkTextbox - FileSelector callbacks now trigger _auto_save_config() so that file path changes are persisted immediately to config.yaml - This fixes the issue where UI file path changes weren't picked up by subsequent step executions --- src/gui/main_window.py | 31 +++++++++++++++++++++++++++++++ src/gui/widgets.py | 4 ++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/gui/main_window.py b/src/gui/main_window.py index 5748a04..55a0286 100644 --- a/src/gui/main_window.py +++ b/src/gui/main_window.py @@ -247,6 +247,23 @@ class MainWindow(ctk.CTk): setattr(self._config, attr, self._config._relative_path(abs_path)) self._config.erase_all = self._erase_cb_var.get() + def _auto_save_config(self) -> None: + """Auto-save config to disk after UI changes. + + Ensures that changes made in the UI (file paths, IP, etc.) + are persisted immediately so that _reload_config() picks them + up on the next step execution. + """ + if not self._config: + return + self._sync_config_from_ui() + user_config_path = self._get_user_config_path() + self._config._config_path = user_config_path + try: + self._config.save() + except Exception: + pass # Silently fail — user can manually save + def _save_config(self) -> None: """Save current configuration to user config file (config.yaml). @@ -293,6 +310,15 @@ class MainWindow(ctk.CTk): if self._config: self._config.zynq_ip = self._ip_string_var.get() + def _on_file_selected(self, path: str) -> None: + """Handle file selection — sync and auto-save to disk. + + When the user selects a file via the browse dialog, immediately + sync the path to the Config object and persist it to YAML so + that subsequent step executions pick up the new value. + """ + self._auto_save_config() + # ── UI Construction ──────────────────────────────────────── def _build_ui(self) -> None: @@ -558,6 +584,7 @@ class MainWindow(ctk.CTk): panel, label_text="FSBL ELF (.elf):", file_types=[("ELF files", "*.elf"), ("All files", "*")], + callback=self._on_file_selected, ) if self._config.fsbl_elf_path: resolved = self._config.resolve_path(self._config.fsbl_elf_path) @@ -570,6 +597,7 @@ class MainWindow(ctk.CTk): panel, label_text="Bootloader BIT (.bit):", file_types=[("BIT files", "*.bit"), ("All files", "*")], + callback=self._on_file_selected, ) if self._config.bootloader_bit_path: resolved = self._config.resolve_path(self._config.bootloader_bit_path) @@ -582,6 +610,7 @@ class MainWindow(ctk.CTk): panel, label_text="Bootloader ELF (.elf):", file_types=[("ELF files", "*.elf"), ("All files", "*")], + callback=self._on_file_selected, ) if self._config.bootloader_elf_path: resolved = self._config.resolve_path(self._config.bootloader_elf_path) @@ -594,6 +623,7 @@ class MainWindow(ctk.CTk): panel, label_text="Bootloader BIN (.bin):", file_types=[("BIN files", "*.bin"), ("All files", "*")], + callback=self._on_file_selected, ) if self._config.bootloader_bin_path: resolved = self._config.resolve_path(self._config.bootloader_bin_path) @@ -628,6 +658,7 @@ class MainWindow(ctk.CTk): panel, label_text="Firmware BIN (.bin):", file_types=[("BIN files", "*.bin"), ("All files", "*")], + callback=self._on_file_selected, ) if self._config.firmware_bin_path: resolved = self._config.resolve_path(self._config.firmware_bin_path) diff --git a/src/gui/widgets.py b/src/gui/widgets.py index 427d63b..55da265 100644 --- a/src/gui/widgets.py +++ b/src/gui/widgets.py @@ -489,8 +489,8 @@ class StatusDisplay(ctk.CTkFrame): color = colors.get(status, INFO_COLOR) self._status_text.insert("1.0", message) - # Tag the entire text with the color - self._status_text.tag_configure("status", foreground=color) + # Tag the entire text with the color (CTkTextbox uses tag_config) + self._status_text.tag_config("status", foreground=color) self._status_text.tag_add("status", "1.0", "end") self._status_text.configure(state="disabled")