fix: Advanced settings not saving and UI update issues

This commit addresses several bugs related to the Advanced Settings functionality:

- **Fix:** Ensure saved default settings (e.g., force encryption) are correctly applied to the main UI on application startup.
- **Fix:** Prevent the UI from automatically switching away from the Advanced Settings view after clicking "Apply". Settings are now saved in the background, and a temporary success message is displayed in the header.
- **Fix:** Ensure settings are correctly reloaded and displayed when switching between tabs within the Advanced Settings view, resolving inconsistencies after a reset operation.
This commit is contained in:
2025-09-13 23:56:39 +02:00
parent 9b9b0743a8
commit ff08c9b646
4 changed files with 51 additions and 18 deletions

View File

@@ -53,6 +53,18 @@ class MainApplication(tk.Tk):
self.style.configure("Green.Sidebar.TButton", foreground="green") self.style.configure("Green.Sidebar.TButton", foreground="green")
# Custom button styles for BackupContentFrame
self.style.configure("Success.TButton", foreground="#2E7D32") # Darker Green
self.style.configure("Danger.TButton", foreground="#C62828") # Darker Red
# Custom LabelFrame style for Mount frame
self.style.configure("Mount.TLabelFrame", bordercolor="#0078D7")
self.style.configure("Mount.TLabelFrame.Label", foreground="#0078D7")
# Custom button styles for BackupContentFrame
self.style.configure("Success.TButton", foreground="#2E7D32") # Darker Green
self.style.configure("Danger.TButton", foreground="#C62828") # Darker Red
self.style.configure("Switch2.TCheckbutton", self.style.configure("Switch2.TCheckbutton",
background="#2b3e4f", foreground="white") background="#2b3e4f", foreground="white")
self.style.map("Switch2.TCheckbutton", self.style.map("Switch2.TCheckbutton",
@@ -423,6 +435,7 @@ class MainApplication(tk.Tk):
restore_dest_folder) restore_dest_folder)
self._process_queue() self._process_queue()
self._update_sync_mode_display() # Call after loading state self._update_sync_mode_display() # Call after loading state
self.update_backup_options_from_config() # Apply defaults on startup
def _setup_log_window(self): def _setup_log_window(self):
self.log_frame = ttk.Frame(self.content_frame) self.log_frame = ttk.Frame(self.content_frame)

View File

@@ -318,18 +318,23 @@ class AdvancedSettingsFrame(ttk.Frame):
if index == 0: if index == 0:
self.tree_frame.pack(fill=tk.BOTH, expand=True) self.tree_frame.pack(fill=tk.BOTH, expand=True)
self.info_label.config(text=Msg.STR["advanced_settings_warning"]) self.info_label.config(text=Msg.STR["advanced_settings_warning"])
self._load_system_folders()
elif index == 1: elif index == 1:
self.manual_excludes_frame.pack(fill=tk.BOTH, expand=True) self.manual_excludes_frame.pack(fill=tk.BOTH, expand=True)
self.info_label.config(text=Msg.STR["manual_excludes_info"]) self.info_label.config(text=Msg.STR["manual_excludes_info"])
self._load_manual_excludes()
elif index == 2: elif index == 2:
self.keyfile_settings_frame.pack(fill=tk.BOTH, expand=True) self.keyfile_settings_frame.pack(fill=tk.BOTH, expand=True)
self.info_label.config(text="") self.info_label.config(text="")
self._update_key_file_status()
elif index == 3: elif index == 3:
self.animation_settings_frame.pack(fill=tk.BOTH, expand=True) self.animation_settings_frame.pack(fill=tk.BOTH, expand=True)
self.info_label.config(text="") self.info_label.config(text="")
self._load_animation_settings()
elif index == 4: elif index == 4:
self.backup_defaults_frame.pack(fill=tk.BOTH, expand=True) self.backup_defaults_frame.pack(fill=tk.BOTH, expand=True)
self.info_label.config(text="") self.info_label.config(text="")
self._load_backup_defaults()
def update_nav_buttons(self, active_index): def update_nav_buttons(self, active_index):
for i, button in enumerate(self.nav_buttons): for i, button in enumerate(self.nav_buttons):
@@ -360,6 +365,7 @@ class AdvancedSettingsFrame(ttk.Frame):
self.config_manager.remove_setting("backup_animation_type") self.config_manager.remove_setting("backup_animation_type")
self.config_manager.remove_setting("calculation_animation_type") self.config_manager.remove_setting("calculation_animation_type")
self._load_animation_settings() self._load_animation_settings()
self._load_backup_defaults() # Reload other settings too
def _reset_backup_defaults(self): def _reset_backup_defaults(self):
self.config_manager.remove_setting("force_full_backup") self.config_manager.remove_setting("force_full_backup")
@@ -367,6 +373,7 @@ class AdvancedSettingsFrame(ttk.Frame):
self.config_manager.remove_setting("force_compression") self.config_manager.remove_setting("force_compression")
self.config_manager.remove_setting("force_encryption") self.config_manager.remove_setting("force_encryption")
self._load_backup_defaults() self._load_backup_defaults()
self._load_animation_settings() # Reload other settings too
if self.app_instance: if self.app_instance:
self.app_instance.update_backup_options_from_config() self.app_instance.update_backup_options_from_config()
@@ -542,9 +549,8 @@ class AdvancedSettingsFrame(ttk.Frame):
for item in self.manual_excludes_listbox.get(0, tk.END): for item in self.manual_excludes_listbox.get(0, tk.END):
f.write(f"{item}\n") f.write(f"{item}\n")
self.pack_forget() # Show temporary success message in header
if self.show_main_settings_callback: self.app_instance.header_frame.show_temporary_message("Settings saved successfully!")
self.show_main_settings_callback()
if self.app_instance: if self.app_instance:
current_source = self.app_instance.left_canvas_data.get('folder') current_source = self.app_instance.left_canvas_data.get('folder')

View File

@@ -12,9 +12,11 @@ class HeaderFrame(tk.Frame):
self.image_manager = image_manager self.image_manager = image_manager
self.encryption_manager = encryption_manager self.encryption_manager = encryption_manager
self.app = app self.app = app
self.original_subtitle_text = Msg.STR["header_subtitle"]
self._temp_message_after_id = None
# Configure grid weights for internal layout # Configure grid weights for internal layout
self.columnconfigure(1, weight=1) # Make the middle column expand self.columnconfigure(1, weight=1)
# Left side: Icon and Main Title/Subtitle # Left side: Icon and Main Title/Subtitle
left_frame = tk.Frame(self, bg="#455A64") left_frame = tk.Frame(self, bg="#455A64")
@@ -38,14 +40,14 @@ class HeaderFrame(tk.Frame):
title_label.grid(row=0, column=1, sticky="w", title_label.grid(row=0, column=1, sticky="w",
padx=(5, 20), pady=(15, 5)) padx=(5, 20), pady=(15, 5))
subtitle_label = tk.Label( self.subtitle_label = tk.Label(
self, self,
text=Msg.STR["header_subtitle"], text=self.original_subtitle_text,
font=("Helvetica", 10), font=("Helvetica", 10),
fg="#bdc3c7", fg="#bdc3c7",
bg="#455A64", bg="#455A64",
) )
subtitle_label.grid(row=1, column=1, sticky="nw", self.subtitle_label.grid(row=1, column=1, sticky="nw",
padx=(5, 20), pady=(0, 10)) padx=(5, 20), pady=(0, 10))
# Right side: Status labels # Right side: Status labels
@@ -70,6 +72,20 @@ class HeaderFrame(tk.Frame):
self.refresh_status() self.refresh_status()
def show_temporary_message(self, message: str, duration_ms: int = 4000):
"""Displays a temporary message in the subtitle area."""
# Cancel any previous after job to prevent conflicts
if self._temp_message_after_id:
self.after_cancel(self._temp_message_after_id)
self.subtitle_label.config(text=message, fg="#2ECC71") # Green color for success
self._temp_message_after_id = self.after(duration_ms, self._restore_subtitle)
def _restore_subtitle(self):
"""Restores the original subtitle text and color."""
self.subtitle_label.config(text=self.original_subtitle_text, fg="#bdc3c7")
self._temp_message_after_id = None
def refresh_status(self): def refresh_status(self):
"""Checks key and mount status of all encrypted profiles and updates the labels.""" """Checks key and mount status of all encrypted profiles and updates the labels."""
app_logger.log("HeaderFrame: Refreshing status...") app_logger.log("HeaderFrame: Refreshing status...")
@@ -80,10 +96,8 @@ class HeaderFrame(tk.Frame):
return return
# --- Key Status Logic --- # --- Key Status Logic ---
# This checks the key for the destination's root user, as a general indicator.
username = os.path.basename(dest_path.rstrip('/')) username = os.path.basename(dest_path.rstrip('/'))
key_in_keyring = self.encryption_manager.is_key_in_keyring(username) key_in_keyring = self.encryption_manager.is_key_in_keyring(username)
# A keyfile for a specific profile is not checked here, we check the general one.
key_file_exists = os.path.exists( key_file_exists = os.path.exists(
self.encryption_manager.get_key_file_path(dest_path, username)) self.encryption_manager.get_key_file_path(dest_path, username))
@@ -114,12 +128,12 @@ class HeaderFrame(tk.Frame):
if mounted_count == total_count: if mounted_count == total_count:
fg_color = "#6bbbff" # Bright Blue (All Mounted) fg_color = "#6bbbff" # Bright Blue (All Mounted)
elif mounted_count > 0: elif mounted_count > 0:
fg_color = "#FFA500" # Bright Orange (Partially Mounted) fg_color = "#FFD700" # Gold/Yellow (Partially Mounted)
else: else:
fg_color = "#FF4500" # Bright OrangeRed (None Mounted) fg_color = "#FFA500" # Orange (None Mounted)
self.mount_status_label.config( self.mount_status_label.config(
text=mount_status_text, text=mount_status_text,
fg=fg_color fg=fg_color
) )
app_logger.log("HeaderFrame: Status refresh complete.") app_logger.log("HeaderFrame: Status refresh complete.")

View File

@@ -48,9 +48,9 @@ class SettingsFrame(ttk.Frame):
ttk.Separator(self.button_frame, orient=tk.VERTICAL).pack( ttk.Separator(self.button_frame, orient=tk.VERTICAL).pack(
side=tk.LEFT, ipady=15, padx=5) side=tk.LEFT, ipady=15, padx=5)
advanced_button = ttk.Button( reset_button = ttk.Button(
self.button_frame, text=Msg.STR["advanced"], command=self._open_advanced_settings, style="Gray.Toolbutton") self.button_frame, text=Msg.STR["default_settings"], command=self.actions.reset_to_default_settings, style="Gray.Toolbutton")
advanced_button.pack(side=tk.LEFT, padx=5) reset_button.pack(side=tk.LEFT)
ttk.Separator(self.button_frame, orient=tk.VERTICAL).pack( ttk.Separator(self.button_frame, orient=tk.VERTICAL).pack(
side=tk.LEFT, ipady=15, padx=5) side=tk.LEFT, ipady=15, padx=5)
@@ -63,9 +63,9 @@ class SettingsFrame(ttk.Frame):
ttk.Separator(self.button_frame, orient=tk.VERTICAL).pack( ttk.Separator(self.button_frame, orient=tk.VERTICAL).pack(
side=tk.LEFT, ipady=15, padx=5) side=tk.LEFT, ipady=15, padx=5)
reset_button = ttk.Button( advanced_button = ttk.Button(
self.button_frame, text=Msg.STR["default_settings"], command=self.actions.reset_to_default_settings, style="Gray.Toolbutton") self.button_frame, text=Msg.STR["advanced"], command=self._open_advanced_settings, style="Gray.Toolbutton")
reset_button.pack(side=tk.LEFT) advanced_button.pack(side=tk.LEFT, padx=5)
# --- Container for Treeviews --- # --- Container for Treeviews ---
self.trees_container = ttk.Frame(self) self.trees_container = ttk.Frame(self)