# --- FILE: gitsync_tool/gui/tabs/backup_tab.py --- import tkinter as tk from tkinter import ttk from typing import Callable, Optional from gitutility.gui.tooltip import Tooltip class BackupTab(ttk.Frame): """ The 'Backup Settings' tab in the main application notebook. This tab provides widgets for configuring automatic and manual backups. """ def __init__(self, master: tk.Misc, **kwargs): """ Initializes the Backup Settings tab. Args: master: The parent widget (the ttk.Notebook). **kwargs: Dictionary of callbacks from the main controller. """ super().__init__(master, padding=(10, 10)) # Store callbacks self.manual_backup_callback = kwargs.get('manual_backup_cb') self.browse_folder_callback = kwargs.get('browse_folder_cb') # --- Tkinter Variables specific to this tab --- self.autobackup_var = tk.BooleanVar() self.backup_dir_var = tk.StringVar() self.backup_exclude_extensions_var = tk.StringVar() self.backup_exclude_dirs_var = tk.StringVar() # Configure layout self.columnconfigure(1, weight=1) # Create widgets self._create_widgets() def _create_widgets(self) -> None: """Creates and arranges all widgets for this tab.""" # --- Backup Configuration Frame --- config_frame = ttk.LabelFrame(self, text="Backup Configuration", padding=(10, 5)) config_frame.pack(pady=5, fill="x", expand=False) config_frame.columnconfigure(1, weight=1) # Autobackup Checkbox self.autobackup_checkbox = ttk.Checkbutton( config_frame, text="Enable Auto Backup before Actions (Create/Fetch Bundle)", variable=self.autobackup_var, command=self.toggle_backup_dir_widgets, ) self.autobackup_checkbox.grid(row=0, column=0, columnspan=3, sticky=tk.W, padx=5, pady=(5, 5)) Tooltip( self.autobackup_checkbox, "Automatically create a ZIP backup of the working directory before creating or fetching from a bundle." ) # Backup Directory backup_dir_label = ttk.Label(config_frame, text="Backup Directory:") backup_dir_label.grid(row=1, column=0, sticky=tk.W, padx=5, pady=3) self.backup_dir_entry = ttk.Entry( config_frame, textvariable=self.backup_dir_var, width=60, state=tk.DISABLED ) self.backup_dir_entry.grid(row=1, column=1, sticky=tk.EW, padx=5, pady=3) Tooltip(self.backup_dir_entry, "Directory where automatic and manual backup ZIP files will be stored.") self.backup_dir_button = ttk.Button( config_frame, text="Browse...", width=9, command=self._browse_backup_dir, state=tk.DISABLED ) self.backup_dir_button.grid(row=1, column=2, sticky=tk.W, padx=(0, 5), pady=3) # Exclusions exclude_ext_label = ttk.Label(config_frame, text="Exclude File Exts:") exclude_ext_label.grid(row=2, column=0, sticky=tk.W, padx=5, pady=3) self.backup_exclude_entry = ttk.Entry( config_frame, textvariable=self.backup_exclude_extensions_var, width=60 ) self.backup_exclude_entry.grid(row=2, column=1, columnspan=2, sticky=tk.EW, padx=5, pady=3) Tooltip( self.backup_exclude_entry, "Comma-separated list of file extensions to exclude from backups (e.g., .log, .tmp, .bak)." ) exclude_dir_label = ttk.Label(config_frame, text="Exclude Dirs (Name):") exclude_dir_label.grid(row=3, column=0, sticky=tk.W, padx=5, pady=3) self.backup_exclude_dirs_entry = ttk.Entry( config_frame, textvariable=self.backup_exclude_dirs_var, width=60 ) self.backup_exclude_dirs_entry.grid(row=3, column=1, columnspan=2, sticky=tk.EW, padx=5, pady=3) Tooltip( self.backup_exclude_dirs_entry, "Comma-separated list of directory base names to exclude (e.g., __pycache__, build, node_modules). .git and .svn are always excluded." ) # --- Manual Backup Action Frame --- action_frame = ttk.LabelFrame(self, text="Manual Backup", padding=(10, 5)) action_frame.pack(pady=10, fill="x", expand=False) self.manual_backup_button = ttk.Button( action_frame, text="Backup Now (ZIP)", command=self.manual_backup_callback, state=tk.DISABLED ) self.manual_backup_button.pack(side=tk.LEFT, padx=5, pady=5) Tooltip( self.manual_backup_button, "Create a manual ZIP backup of the working directory now using the configured exclusions." ) def _browse_backup_dir(self): """Internal handler to call the browse callback for the backup directory entry.""" if hasattr(self, "backup_dir_entry") and callable(self.browse_folder_callback): self.browse_folder_callback(self.backup_dir_entry) def toggle_backup_dir_widgets(self) -> None: """Enables or disables the backup directory widgets based on the autobackup checkbox.""" state = tk.NORMAL if self.autobackup_var.get() else tk.DISABLED if hasattr(self, "backup_dir_entry") and self.backup_dir_entry.winfo_exists(): self.backup_dir_entry.config(state=state) if hasattr(self, "backup_dir_button") and self.backup_dir_button.winfo_exists(): self.backup_dir_button.config(state=state) def set_action_widgets_state(self, state: str) -> None: """Sets the state of all action widgets in this tab.""" widgets_to_toggle = [ self.autobackup_checkbox, self.manual_backup_button, ] for widget in widgets_to_toggle: if widget and widget.winfo_exists(): widget.config(state=state) if state == tk.DISABLED: if hasattr(self, "backup_dir_entry"): self.backup_dir_entry.config(state=tk.DISABLED) if hasattr(self, "backup_dir_button"): self.backup_dir_button.config(state=tk.DISABLED) else: self.toggle_backup_dir_widgets()