From 05500f0303f95d2cc574bed5c0fd59115e1feca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9sir=C3=A9=20Werner=20Menrath?= Date: Mon, 1 Sep 2025 20:36:24 +0200 Subject: [PATCH] feat(ui): Refactor backup and advanced settings navigation - Update button styles in Backup Content and Advanced Settings to match the main application navigation. - Implement a progress bar indicator for the active tab. - Realign buttons in Advanced Settings to the left. - Add a dynamic informational label for the "Manual Excludes" section. --- pyimage_ui/advanced_settings_frame.py | 75 +++++++++++++++++++------ pyimage_ui/backup_content_frame.py | 80 +++++++++++++++++++-------- 2 files changed, 115 insertions(+), 40 deletions(-) diff --git a/pyimage_ui/advanced_settings_frame.py b/pyimage_ui/advanced_settings_frame.py index 7820a05..553d90f 100644 --- a/pyimage_ui/advanced_settings_frame.py +++ b/pyimage_ui/advanced_settings_frame.py @@ -15,23 +15,43 @@ class AdvancedSettingsFrame(tk.Toplevel): self.title(Msg.STR["advanced_settings_title"]) self.config_manager = config_manager self.app_instance = app_instance + self.current_view_index = 0 # --- Warning Label --- - warning_label = ttk.Label( - self, text=Msg.STR["advanced_settings_warning"], wraplength=780, justify="center") - warning_label.pack(pady=10, fill=tk.X, padx=10) + self.info_label = ttk.Label( + self, text=Msg.STR["advanced_settings_warning"], wraplength=780, justify="left") + self.info_label.pack(pady=10, fill=tk.X, padx=10) - # --- View Toggle Buttons --- - toggle_frame = ttk.Frame(self) - toggle_frame.pack(pady=5) + # --- Navigation --- + nav_frame = ttk.Frame(self) + nav_frame.pack(fill=tk.X, padx=10, pady=5) - self.system_excludes_button = ttk.Button( - toggle_frame, text=Msg.STR["system_excludes"], command=lambda: self._toggle_views("system")) - self.system_excludes_button.pack(side=tk.LEFT, padx=5) + top_nav_frame = ttk.Frame(nav_frame) + top_nav_frame.pack(side=tk.LEFT) - self.manual_excludes_button = ttk.Button( - toggle_frame, text=Msg.STR["manual_excludes"], command=lambda: self._toggle_views("manual")) - self.manual_excludes_button.pack(side=tk.LEFT, padx=5) + self.nav_buttons_defs = [ + (Msg.STR["system_excludes"], lambda: self._switch_view(0)), + (Msg.STR["manual_excludes"], lambda: self._switch_view(1)), + ] + + self.nav_buttons = [] + self.nav_progress_bars = [] + + for i, (text, command) in enumerate(self.nav_buttons_defs): + button_frame = ttk.Frame(top_nav_frame) + button_frame.pack(side=tk.LEFT, padx=5) + button = ttk.Button(button_frame, text=text, + command=command, style="TButton.Borderless.Round") + button.pack(side=tk.TOP) + self.nav_buttons.append(button) + progress_bar = ttk.Progressbar( + button_frame, orient="horizontal", length=50, mode="determinate", style="Small.Horizontal.TProgressbar") + progress_bar.pack_forget() + self.nav_progress_bars.append(progress_bar) + + if i < len(self.nav_buttons_defs) - 1: + ttk.Separator(top_nav_frame, orient=tk.VERTICAL).pack( + side=tk.LEFT, fill=tk.Y, padx=2) # --- Container for the two views --- view_container = ttk.Frame(self) @@ -60,10 +80,13 @@ class AdvancedSettingsFrame(tk.Toplevel): self.manual_excludes_frame = ttk.LabelFrame( view_container, text=Msg.STR["manual_excludes"], padding=10) - self.manual_excludes_listbox = tk.Listbox(self.manual_excludes_frame, selectmode=tk.MULTIPLE) - self.manual_excludes_listbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) + self.manual_excludes_listbox = tk.Listbox( + self.manual_excludes_frame, selectmode=tk.MULTIPLE) + self.manual_excludes_listbox.pack( + fill=tk.BOTH, expand=True, padx=5, pady=5) - delete_button = ttk.Button(self.manual_excludes_frame, text=Msg.STR["delete"], command=self._delete_manual_exclude) + delete_button = ttk.Button( + self.manual_excludes_frame, text=Msg.STR["delete"], command=self._delete_manual_exclude) delete_button.pack(pady=5) # --- Animation Settings --- @@ -133,15 +156,31 @@ class AdvancedSettingsFrame(tk.Toplevel): self._load_backup_defaults() self._load_manual_excludes() - self._toggle_views("system") + self._switch_view(self.current_view_index) - def _toggle_views(self, view): - if view == "system": + def _switch_view(self, index): + self.current_view_index = index + self.update_nav_buttons(index) + + if index == 0: self.manual_excludes_frame.pack_forget() self.tree_frame.pack(fill=tk.BOTH, expand=True) + self.info_label.config( + text=Msg.STR["advanced_settings_warning"]) else: self.tree_frame.pack_forget() self.manual_excludes_frame.pack(fill=tk.BOTH, expand=True) + self.info_label.config(text=Msg.STR["manual_excludes_info"]) + + def update_nav_buttons(self, active_index): + for i, button in enumerate(self.nav_buttons): + if i == active_index: + button.configure(style="Toolbutton") + self.nav_progress_bars[i].pack(side=tk.BOTTOM, fill=tk.X) + self.nav_progress_bars[i]['value'] = 100 + else: + button.configure(style="Gray.Toolbutton") + self.nav_progress_bars[i].pack_forget() def _load_manual_excludes(self): self.manual_excludes_listbox.delete(0, tk.END) diff --git a/pyimage_ui/backup_content_frame.py b/pyimage_ui/backup_content_frame.py index 79eaf81..3f966b6 100644 --- a/pyimage_ui/backup_content_frame.py +++ b/pyimage_ui/backup_content_frame.py @@ -12,26 +12,45 @@ class BackupContentFrame(ttk.Frame): def __init__(self, master, backup_manager, actions, **kwargs): super().__init__(master, **kwargs) self.backup_manager = backup_manager - self.actions = actions # Store actions object - self.master = master # Reference to MainApplication + self.actions = actions + self.master = master self.backup_path = None + self.current_view_index = 0 - # --- Header with buttons --- header_frame = ttk.Frame(self) header_frame.grid(row=0, column=0, sticky=tk.NSEW) - self.grid_rowconfigure(1, weight=1) # Row for content frames - self.grid_columnconfigure(0, weight=1) # Column for content frames + self.grid_rowconfigure(1, weight=1) + self.grid_columnconfigure(0, weight=1) - self.system_button = ttk.Button( - header_frame, text=Msg.STR["system_backup_info"], command=self.show_system_backups) - self.system_button.pack(side=tk.LEFT, padx=5) + top_nav_frame = ttk.Frame(header_frame) + top_nav_frame.pack(side=tk.LEFT) - self.user_button = ttk.Button( - header_frame, text=Msg.STR["user_backup_info"], command=self.show_user_backups) - self.user_button.pack(side=tk.LEFT, padx=5) + self.nav_buttons_defs = [ + (Msg.STR["system_backup_info"], lambda: self._switch_view(0)), + (Msg.STR["user_backup_info"], lambda: self._switch_view(1)), + ] - # Deletion Status UI (initially hidden) + self.nav_buttons = [] + self.nav_progress_bars = [] + + for i, (text, command) in enumerate(self.nav_buttons_defs): + button_frame = ttk.Frame(top_nav_frame) + button_frame.pack(side=tk.LEFT, padx=5) + button = ttk.Button(button_frame, text=text, + command=command, style="TButton.Borderless.Round") + button.pack(side=tk.TOP) + self.nav_buttons.append(button) + progress_bar = ttk.Progressbar( + button_frame, orient="horizontal", length=50, mode="determinate", style="Small.Horizontal.TProgressbar") + progress_bar.pack_forget() + self.nav_progress_bars.append(progress_bar) + + if i < len(self.nav_buttons_defs) - 1: + ttk.Separator(top_nav_frame, orient=tk.VERTICAL).pack( + side=tk.LEFT, fill=tk.Y, padx=2) + + # Deletion Status UI self.deletion_status_frame = ttk.Frame(header_frame) self.deletion_status_frame.pack(side=tk.LEFT, padx=15) @@ -53,7 +72,28 @@ class BackupContentFrame(ttk.Frame): self.system_backups_frame.grid(row=1, column=0, sticky=tk.NSEW) self.user_backups_frame.grid(row=1, column=0, sticky=tk.NSEW) - self.show_system_backups() # Show system backups by default + self._switch_view(self.current_view_index) + + def _switch_view(self, index): + self.current_view_index = index + self.update_nav_buttons(index) + + if index == 0: + self.system_backups_frame.grid() + self.user_backups_frame.grid_remove() + else: + self.user_backups_frame.grid() + self.system_backups_frame.grid_remove() + + def update_nav_buttons(self, active_index): + for i, button in enumerate(self.nav_buttons): + if i == active_index: + button.configure(style="Toolbutton") + self.nav_progress_bars[i].pack(side=tk.BOTTOM, fill=tk.X) + self.nav_progress_bars[i]['value'] = 100 + else: + button.configure(style="Gray.Toolbutton") + self.nav_progress_bars[i].pack_forget() def show(self, backup_path): self.grid(row=2, column=0, sticky="nsew") @@ -61,18 +101,14 @@ class BackupContentFrame(ttk.Frame): self.backup_path = backup_path self.system_backups_frame.show(backup_path) self.user_backups_frame.show(backup_path) + + # Ensure the correct view is shown upon revealing the frame + self._switch_view(self.current_view_index) + def hide(self): self.grid_remove() - def show_system_backups(self): - self.system_backups_frame.grid() - self.user_backups_frame.grid_remove() - - def show_user_backups(self): - self.user_backups_frame.grid() - self.system_backups_frame.grid_remove() - def show_deletion_status(self, text: str): app_logger.log(f"Showing deletion status: {text}") self.deletion_status_label.config(text=text) @@ -82,4 +118,4 @@ class BackupContentFrame(ttk.Frame): def hide_deletion_status(self): app_logger.log("Hiding deletion status.") self.deletion_animated_icon.stop("DISABLE") - self.deletion_status_frame.pack_forget() \ No newline at end of file + self.deletion_status_frame.pack_forget()