feat: Implementierung von Papierkorb- und reinen Synchronisierungsoptionen für Benutzer-Backups
This commit is contained in:
@@ -82,7 +82,7 @@ class BackupManager:
|
||||
finally:
|
||||
self.inhibit_cookie = None
|
||||
|
||||
def start_backup(self, queue, source_path: str, dest_path: str, is_system: bool, is_dry_run: bool = False, exclude_files: Optional[List[Path]] = None, source_size: int = 0, is_compressed: bool = False, is_encrypted: bool = False, mode: str = "incremental"):
|
||||
def start_backup(self, queue, source_path: str, dest_path: str, is_system: bool, is_dry_run: bool = False, exclude_files: Optional[List[Path]] = None, source_size: int = 0, is_compressed: bool = False, is_encrypted: bool = False, mode: str = "incremental", use_trash_bin: bool = False, no_trash_bin: bool = False):
|
||||
self.is_system_process = is_system
|
||||
self._inhibit_screensaver()
|
||||
|
||||
@@ -95,12 +95,12 @@ class BackupManager:
|
||||
return None
|
||||
|
||||
thread = threading.Thread(target=self._run_backup_path, args=(
|
||||
queue, source_path, dest_path, is_system, is_dry_run, exclude_files, source_size, is_compressed, is_encrypted, mode, mount_point))
|
||||
queue, source_path, dest_path, is_system, is_dry_run, exclude_files, source_size, is_compressed, is_encrypted, mode, mount_point, use_trash_bin, no_trash_bin))
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
return thread
|
||||
|
||||
def _run_backup_path(self, queue, source_path: str, dest_path: str, is_system: bool, is_dry_run: bool, exclude_files: Optional[List[Path]], source_size: int, is_compressed: bool, is_encrypted: bool, mode: str, mount_point: Optional[str]):
|
||||
def _run_backup_path(self, queue, source_path: str, dest_path: str, is_system: bool, is_dry_run: bool, exclude_files: Optional[List[Path]], source_size: int, is_compressed: bool, is_encrypted: bool, mode: str, mount_point: Optional[str], use_trash_bin: bool, no_trash_bin: bool):
|
||||
try:
|
||||
base_dest_path = os.path.dirname(dest_path)
|
||||
pybackup_dir = os.path.join(base_dest_path, "pybackup")
|
||||
@@ -140,6 +140,19 @@ class BackupManager:
|
||||
command.append(f"--exclude-from={AppConfig.MANUAL_EXCLUDE_LIST_PATH}")
|
||||
if is_dry_run:
|
||||
command.append('--dry-run')
|
||||
|
||||
# Handle trash bin / pure sync options for user backups
|
||||
if not is_system:
|
||||
trash_bin_path = os.path.join(rsync_base_dest, ".Trash")
|
||||
if use_trash_bin:
|
||||
command.extend(['--backup', f'--backup-dir={trash_bin_path}', '--delete'])
|
||||
# Exclude the trash bin itself from the backup
|
||||
command.append(f"--exclude={os.path.basename(trash_bin_path)}/")
|
||||
elif no_trash_bin:
|
||||
command.append('--delete')
|
||||
# Exclude the trash bin itself from the backup if it exists from previous use_trash_bin
|
||||
command.append(f"--exclude={os.path.basename(trash_bin_path)}/")
|
||||
|
||||
command.extend([source_path, rsync_dest])
|
||||
self.logger.log(f"Rsync command: {' '.join(command)}")
|
||||
|
||||
|
@@ -352,5 +352,10 @@ class Msg:
|
||||
"force_incremental_backup": _("Always force incremental backup (except first)"),
|
||||
"force_compression": _("Always compress backup"),
|
||||
"force_encryption": _("Always encrypt backup"),
|
||||
"use_trash_bin": _("Papierkorb verwenden"),
|
||||
"no_trash_bin": _("Kein Papierkorb (reine Synchronisierung)"),
|
||||
"sync_mode_pure_sync": _("Synchronisierungsmodus: Reine Synchronisierung (Dateien werden gelöscht)"),
|
||||
"sync_mode_trash_bin": _("Synchronisierungsmodus: Papierkorb verwenden (Gelöschte Dateien werden verschoben)"),
|
||||
"sync_mode_no_delete": _("Synchronisierungsmodus: Keine Löschung (Dateien bleiben im Ziel)"),
|
||||
"encryption_note_system_backup": _("Note: For system backups, encryption only applies to files directly within the /home directory. Folders are not automatically encrypted unless explicitly included in the backup."),
|
||||
}
|
||||
|
21
main_app.py
21
main_app.py
@@ -384,6 +384,7 @@ class MainApplication(tk.Tk):
|
||||
self.after(100, self.actions.on_sidebar_button_click,
|
||||
restore_dest_folder)
|
||||
self._process_queue()
|
||||
self._update_sync_mode_display() # Call after loading state
|
||||
|
||||
def _setup_log_window(self):
|
||||
self.log_frame = ttk.Frame(self.content_frame)
|
||||
@@ -427,6 +428,10 @@ class MainApplication(tk.Tk):
|
||||
self.info_checkbox_frame, text=Msg.STR["info_text_placeholder"])
|
||||
self.info_label.pack(anchor=tk.W, fill=tk.X, pady=5)
|
||||
|
||||
self.sync_mode_label = ttk.Label(
|
||||
self.info_checkbox_frame, text="", foreground="blue")
|
||||
self.sync_mode_label.pack(anchor=tk.W, fill=tk.X, pady=2)
|
||||
|
||||
self.time_info_frame = ttk.Frame(self.info_checkbox_frame)
|
||||
self.time_info_frame.pack(anchor=tk.W, fill=tk.X, pady=5)
|
||||
|
||||
@@ -748,6 +753,22 @@ class MainApplication(tk.Tk):
|
||||
self.encrypted_cb.config(state="disabled")
|
||||
|
||||
self.actions._refresh_backup_options_ui()
|
||||
self._update_sync_mode_display() # Update sync mode display after options are loaded
|
||||
|
||||
def _update_sync_mode_display(self):
|
||||
use_trash_bin = self.config_manager.get_setting("use_trash_bin", False)
|
||||
no_trash_bin = self.config_manager.get_setting("no_trash_bin", False)
|
||||
|
||||
if self.left_canvas_data.get('folder') == "Computer":
|
||||
self.sync_mode_label.config(text="") # Not applicable for system backups
|
||||
return
|
||||
|
||||
if no_trash_bin:
|
||||
self.sync_mode_label.config(text=Msg.STR["sync_mode_pure_sync"], foreground="red")
|
||||
elif use_trash_bin:
|
||||
self.sync_mode_label.config(text=Msg.STR["sync_mode_trash_bin"], foreground="orange")
|
||||
else:
|
||||
self.sync_mode_label.config(text=Msg.STR["sync_mode_no_delete"], foreground="green")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@@ -245,6 +245,7 @@ class Actions:
|
||||
|
||||
self._start_left_canvas_calculation(
|
||||
button_text, str(folder_path), icon_name, extra_info)
|
||||
self.app._update_sync_mode_display() # Update sync mode display when source changes
|
||||
|
||||
def _start_left_canvas_calculation(self, button_text, folder_path, icon_name, extra_info):
|
||||
self.app.start_pause_button.config(state="disabled")
|
||||
@@ -723,6 +724,11 @@ class Actions:
|
||||
|
||||
is_dry_run = self.app.testlauf_var.get()
|
||||
is_compressed = self.app.compressed_var.get()
|
||||
use_trash_bin = self.app.config_manager.get_setting("use_trash_bin", False)
|
||||
no_trash_bin = self.app.config_manager.get_setting("no_trash_bin", False)
|
||||
|
||||
# Determine mode for user backup based on UI selection
|
||||
mode = "full" if self.app.vollbackup_var.get() else "incremental"
|
||||
|
||||
self.app.backup_manager.start_backup(
|
||||
queue=self.app.queue,
|
||||
@@ -734,5 +740,7 @@ class Actions:
|
||||
source_size=source_size_bytes,
|
||||
is_compressed=is_compressed,
|
||||
is_encrypted=is_encrypted,
|
||||
mode='full',
|
||||
password=password)
|
||||
mode=mode,
|
||||
password=password,
|
||||
use_trash_bin=use_trash_bin,
|
||||
no_trash_bin=no_trash_bin)
|
Reference in New Issue
Block a user