# --- FILE: gitsync_tool/logic/profile_handler.py --- import tkinter as tk from typing import TYPE_CHECKING, List, Optional from gitutility.config.config_manager import DEFAULT_PROFILE, ConfigManager from gitutility.gui.main_frame import MainFrame from gitutility.logging_setup import log_handler # Forward reference for type hinting to avoid circular import if TYPE_CHECKING: from ..app import GitSvnSyncApp class ProfileHandler: """ Handles all logic related to profile management, including loading, saving, adding, and removing configuration profiles. """ def __init__(self, app: "GitSvnSyncApp"): """ Initializes the ProfileHandler. Args: app: The main application instance. """ self.app = app self.config_manager: ConfigManager = app.config_manager self.main_frame: MainFrame = app.main_frame def load_profile_settings(self, profile_name: str) -> None: """Loads settings from a given profile into the GUI.""" func_name: str = "load_profile_settings" log_handler.log_info( f"Loading settings for profile: '{profile_name}'", func_name=func_name ) self.main_frame.update_status_bar( f"Processing: Loading profile '{profile_name}'..." ) if ( not profile_name or profile_name not in self.config_manager.get_profile_sections() ): log_handler.log_warning( f"Profile '{profile_name}' invalid/not found.", func_name=func_name ) self.app._clear_and_disable_fields() if profile_name: self.main_frame.show_error( "Profile Load Error", f"Profile '{profile_name}' not found." ) return # Delegate the actual loading and GUI update to the app/main_frame # to keep the UI logic separate from business logic as much as possible. self.app._apply_profile_to_gui(profile_name) def save_profile_settings(self) -> bool: """Gathers settings from the GUI and saves them to the current profile.""" func_name: str = "save_profile_settings" profile_name = self.main_frame.profile_var.get() if not profile_name: log_handler.log_warning( "Save failed: No profile selected.", func_name=func_name ) self.main_frame.update_status_bar("Save failed: No profile selected.") return False log_handler.log_info( f"Saving settings for profile: '{profile_name}'", func_name=func_name ) try: settings_to_save = self.app._gather_settings_from_gui() log_handler.log_debug( f"Settings gathered from GUI: {settings_to_save}", func_name=func_name ) for key, value in settings_to_save.items(): self.config_manager.set_profile_option(profile_name, key, value) self.config_manager.save_config() log_handler.log_info( f"Settings saved successfully for '{profile_name}'.", func_name=func_name, ) self.main_frame.update_status_bar(f"Profile '{profile_name}' saved.") return True except Exception as e: log_handler.log_exception( f"Error saving profile '{profile_name}': {e}", func_name=func_name ) self.main_frame.show_error( "Save Error", f"Failed to save profile settings:\n{e}" ) self.main_frame.update_status_bar(f"Error saving profile '{profile_name}'.") return False def add_profile(self) -> None: """Handles the creation of a new profile.""" func_name: str = "add_profile" self.main_frame.update_status_bar("Adding new profile...") name = self.main_frame.ask_new_profile_name() if name is None: log_handler.log_info("Add profile cancelled.", func_name=func_name) self.main_frame.update_status_bar("Add profile cancelled.") return name = name.strip() if not name: self.main_frame.show_error("Input Error", "Profile name cannot be empty.") return if name in self.config_manager.get_profile_sections(): self.main_frame.show_error("Error", f"Profile '{name}' already exists.") return try: defaults = self.config_manager._get_expected_keys_with_defaults() defaults["bundle_name"] = f"{name}_repo.bundle" defaults["bundle_name_updated"] = f"{name}_update.bundle" self.config_manager.add_section(name) for key, value in defaults.items(): self.config_manager.set_profile_option(name, key, str(value)) self.config_manager.save_config() log_handler.log_info( f"Profile '{name}' added successfully.", func_name=func_name ) sections = self.config_manager.get_profile_sections() self.main_frame.update_profile_dropdown(sections) self.main_frame.profile_var.set(name) # This will trigger the load callback except Exception as e: log_handler.log_exception( f"Error adding profile '{name}': {e}", func_name=func_name ) self.main_frame.show_error("Add Error", f"Failed to add profile:\n{e}") def remove_profile(self) -> None: """Handles the removal of the currently selected profile.""" func_name: str = "remove_profile" profile = self.main_frame.profile_var.get() if not profile: self.main_frame.show_error("Error", "No profile selected.") return if profile == DEFAULT_PROFILE: self.main_frame.show_error( "Denied", f"Cannot remove default profile ('{DEFAULT_PROFILE}')." ) return if self.main_frame.ask_yes_no( title="Confirm Remove", message=f"Remove profile '{profile}'?\nThis cannot be undone.", ): try: removed = self.config_manager.remove_profile_section(profile) if removed: self.config_manager.save_config() log_handler.log_info( f"Profile '{profile}' removed.", func_name=func_name ) self.main_frame.update_status_bar(f"Profile '{profile}' removed.") sections = self.config_manager.get_profile_sections() self.main_frame.update_profile_dropdown( sections ) # This will trigger load of new profile else: self.main_frame.show_error( "Error", f"Could not remove '{profile}'." ) except Exception as e: log_handler.log_exception( f"Error removing profile '{profile}': {e}", func_name=func_name ) self.main_frame.show_error("Error", f"Failed to remove profile:\n{e}") else: self.main_frame.update_status_bar("Removal cancelled.")