From 50c144d00cb9e9ef366e8f2f913e241f95b99afb Mon Sep 17 00:00:00 2001 From: CrunchyBanana1 Date: Sun, 5 Jul 2026 13:08:51 +0200 Subject: [PATCH] Show current preset/config name on the Load Preset button The "Load Preset" button now shows the loaded preset or config name, and falls back to "Load Preset" when nothing is loaded. The name is set when a preset or config is loaded or saved. The Ctk top bar is unaffected: the display hooks are no-ops there. Co-Authored-By: Claude Opus 4.8 --- modules/ui/BaseTopBarView.py | 46 ++++++++++++++++++++++++++++++--- modules/ui/PySide6TopBarView.py | 9 +++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/modules/ui/BaseTopBarView.py b/modules/ui/BaseTopBarView.py index fec0372ca..c9af32808 100644 --- a/modules/ui/BaseTopBarView.py +++ b/modules/ui/BaseTopBarView.py @@ -1,3 +1,4 @@ +import os from abc import abstractmethod from collections.abc import Callable @@ -7,6 +8,16 @@ from modules.util.optimizer_util import change_optimizer +def preset_name_from_filename(filename: str) -> str | None: + # The name we show in the top bar. A preset or config is shown by its file + # name without the ".json" ending. "#.json" is the auto-saved "last session" + # file, not a real preset, so we show nothing for it. + basename = os.path.basename(filename) + if basename == "#.json": + return None + return os.path.splitext(basename)[0] + + class BaseTopBarView: def __init__(self, components): self.components = components @@ -27,6 +38,17 @@ def _show_save_dialog(self, initial_dir: str, callback): def _show_open_dialog(self, initial_dir: str, callback): pass + # --- preset-name display hooks ----------------------------------------- + # No-ops by default. The PySide6 top bar overrides them to show the loaded + # preset/config name on the "Load Preset" button; the Ctk top bar leaves + # the button showing its static text. + + def _init_preset_display(self): + pass + + def _set_preset_text(self, text: str): + pass + def build( self, frame, @@ -53,13 +75,18 @@ def build( self.training_method = None + # name of the preset/config currently loaded (None = nothing to show) + self.current_preset_name = None + # title self.components.app_title(self.frame, 0, 0) - # preset picker: model type -> presets for that type - self.components.preset_menu_button( + # preset picker: the button shows the loaded preset/config name and + # opens the "model type -> presets" menu when clicked + self.preset_button = self.components.preset_menu_button( self.frame, 0, 1, "Load Preset", self.preset_tree, self.__load_current_config, sticky="vew", ) + self._init_preset_display() # load config button self.components.button(self.frame, 0, 2, "Load config", self.__load_config, @@ -115,7 +142,13 @@ def __load_config(self): self._show_open_dialog("training_configs", self.__load_current_config) def __save_config(self): - self._show_save_dialog("training_configs", self.controller.save_config_to_path) + # after the file is written, remember it as the current preset so the + # name shows in the top bar and the "changed" marker clears + def save_and_remember(path): + self.controller.save_config_to_path(path) + self.__set_current_preset(path) + + self._show_save_dialog("training_configs", save_and_remember) def __load_current_config(self, filename): loaded_config = self.controller.load_config_from_file(filename) @@ -127,8 +160,15 @@ def __load_current_config(self, filename): optimizer_config = change_optimizer(self.controller.train_config) self.ui_state.get_var("optimizer").update(optimizer_config) + self.__set_current_preset(filename) + self.load_preset_callback() + def __set_current_preset(self, filename): + # record which preset/config is now loaded, then update the label + self.current_preset_name = preset_name_from_filename(filename) + self._set_preset_text(self.current_preset_name or "") + def __remove_config(self): # TODO pass diff --git a/modules/ui/PySide6TopBarView.py b/modules/ui/PySide6TopBarView.py index 68037fb73..257a165d6 100644 --- a/modules/ui/PySide6TopBarView.py +++ b/modules/ui/PySide6TopBarView.py @@ -36,6 +36,15 @@ def __init__( def _setup_frame_column_weight(self): pyside6_components._layout(self.frame).setColumnStretch(5, 1) + def _init_preset_display(self): + # the "Load Preset" button doubles as the display; a tooltip keeps it + # obvious that it opens the preset menu even when it shows a preset name + self.preset_button.setToolTip("Load a preset") + + def _set_preset_text(self, text: str): + # empty means nothing is loaded: fall back to the button's default label + self.preset_button.setText(text or "Load Preset") + def _forget_dropdown(self, widget): lo = pyside6_components._layout(self.frame) lo.removeWidget(widget)