Refactor: Update various modules and add deletion functionality

This commit includes updates across several modules, including:
- backup_manager.py: Enhancements related to backup deletion and regex for backup naming.
- core/data_processing.py: Adjustments to UI state handling.
- pbp_app_config.py: Addition of new UI messages.
- pyimage_ui/actions.py: Refinements in UI actions.
- pyimage_ui/system_backup_content_frame.py: Integration of new deletion logic.
- pyimage_ui/user_backup_content_frame.py: Minor adjustments.

These changes collectively improve backup management, UI responsiveness, and prepare for new deletion features.
This commit is contained in:
2025-09-01 02:02:15 +02:00
parent 7c765019ff
commit fbfc6a7224
7 changed files with 58 additions and 17 deletions

View File

@@ -112,6 +112,33 @@ class BackupManager:
else:
self.logger.log(f"Failed to delete path: {path}")
def start_delete_system_backup(self, path: str, queue):
"""Starts a threaded system backup deletion."""
thread = threading.Thread(target=self._run_delete, args=(path, queue))
thread.daemon = True
thread.start()
def _run_delete(self, path: str, queue):
"""Runs the deletion and puts a message on the queue when done."""
try:
info_file = f"{path}.txt"
# Build a script to remove both the folder and the info file in one go.
# Use -f to avoid errors if the info file doesn't exist.
script_content = f"""
rm -rf '{path}'
rm -f '{info_file}'
"""
if self._execute_as_root(script_content):
self.logger.log(f"Successfully deleted {path} and {info_file}")
queue.put(('deletion_complete', True))
else:
self.logger.log(f"Failed to delete {path}")
queue.put(('deletion_complete', False))
except Exception as e:
self.logger.log(f"Error during threaded deletion: {e}")
queue.put(('deletion_complete', False))
def cancel_backup(self):
if self.process and self.process.poll() is None: # Check if process is still running
self.logger.log("Attempting to cancel backup...")
@@ -528,9 +555,9 @@ set -e
if not os.path.isdir(pybackup_path):
return system_backups
# Regex to parse folder names like '6-März-2024_system_full' or '6-März-2024_system_full.tar.gz'
# Regex to parse folder names like '6-März-2024_143000_system_full' or '6-März-2024_143000_system_full.tar.gz'
name_regex = re.compile(
r"^(\d{1,2}-\w+-\d{4})_system_(full|incremental)(\.tar\.gz)?$", re.IGNORECASE)
r"^(\d{1,2}-\w+-\d{4})_(\d{6})_system_(full|incremental)(\.tar\.gz)?$", re.IGNORECASE)
for item in os.listdir(pybackup_path):
# Skip info files
@@ -543,8 +570,9 @@ set -e
full_path = os.path.join(pybackup_path, item)
date_str = match.group(1)
backup_type_base = match.group(2).capitalize()
is_compressed = match.group(3) is not None
# time_str = match.group(2) # Not currently used in UI, but available
backup_type_base = match.group(3).capitalize()
is_compressed = match.group(4) is not None
backup_type = backup_type_base
if is_compressed:

View File

@@ -242,6 +242,10 @@ class DataProcessing:
self.app.drawing.update_target_projection()
# --- Enable Start Button Logic ---
if self.app.mode == 'backup' and self.app.destination_path:
self.app.start_pause_button.config(state="normal")
# --- Handle Accurate Calculation Completion ---
if calc_type == 'accurate_incremental':
self.app.source_size_bytes = folder_size # Update the source size

View File

@@ -312,6 +312,7 @@ class Msg:
"final_warning_system_restore_title": _("FINAL WARNING"),
"final_warning_system_restore_msg": _("ATTENTION: You are about to restore the system. This process cannot be safely interrupted. All changes since the backup will be lost. \n\nThe computer will automatically restart upon completion. \n\nREALLY PROCEED?"),
"btn_continue": _("PROCEED"),
"deleting_backup_in_progress": _("Deletion in progress... Please wait."),
"select_restore_source_title": _("Select Restore Source"),
"select_restore_destination_title": _("Select Restore Destination"),
@@ -337,4 +338,4 @@ class Msg:
"force_compression": _("Always compress backup"),
"force_encryption": _("Always encrypt backup"),
"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."),
}
}

View File

@@ -376,7 +376,6 @@ class Actions:
"backup_destination_path", path)
self.app.drawing.redraw_right_canvas()
self.app.drawing.update_target_projection()
self.app.start_pause_button.config(state="normal")
current_source = self.app.left_canvas_data.get('folder')
if current_source:

View File

@@ -7,9 +7,10 @@ from pyimage_ui.comment_editor_dialog import CommentEditorDialog
class SystemBackupContentFrame(ttk.Frame):
def __init__(self, master, backup_manager, **kwargs):
def __init__(self, master, backup_manager, actions, **kwargs):
super().__init__(master, **kwargs)
self.backup_manager = backup_manager
self.actions = actions
self.system_backups_list = []
self.backup_path = None
@@ -121,29 +122,30 @@ class SystemBackupContentFrame(ttk.Frame):
selected_item = self.content_tree.focus()
if not selected_item:
return
item_values = self.content_tree.item(selected_item)["values"]
folder_name = item_values[4] # 5th column is folder_name
folder_name = item_values[4] # 5th column is folder_name
selected_backup = None
for backup in self.system_backups_list:
if backup.get("folder_name") == folder_name:
selected_backup = backup
break
if not selected_backup:
print(f"Error: Could not find backup info for {folder_name}")
return
# We need to get the restore destination from the main app
# This is a bit tricky as this frame is isolated.
# This is a bit tricky as this frame is isolated.
# We assume the main app has a way to provide this.
# Let's get it from the config manager, which should be accessible via the backup_manager's app instance.
try:
# Accessing the app instance through the master hierarchy
main_app = self.winfo_toplevel()
restore_dest_path = main_app.config_manager.get_setting("restore_destination_path", "/")
restore_dest_path = main_app.config_manager.get_setting(
"restore_destination_path", "/")
if not restore_dest_path:
print("Error: Restore destination not set.")
# Optionally, show a message box to the user
@@ -169,5 +171,11 @@ class SystemBackupContentFrame(ttk.Frame):
pybackup_path = os.path.join(self.backup_path, "pybackup")
folder_to_delete = os.path.join(pybackup_path, folder_name)
self.backup_manager.delete_privileged_path(folder_to_delete)
self._load_backup_content()
# Lock UI and show status
self.actions._set_ui_state(False) # Lock UI
self.master.show_deletion_status(
Msg.STR["deleting_backup_in_progress"])
# Start deletion in background
self.backup_manager.start_delete_system_backup(
folder_to_delete, self.winfo_toplevel().queue)

View File

@@ -7,11 +7,12 @@ from pyimage_ui.comment_editor_dialog import CommentEditorDialog
class UserBackupContentFrame(ttk.Frame):
def __init__(self, master, backup_manager, **kwargs):
def __init__(self, master, backup_manager, actions, **kwargs):
super().__init__(master, **kwargs)
self.backup_manager = backup_manager
self.backup_manager = backup_manager
self.backup_path = None
self.actions = actions # Store actions object
# --- Backup Content List View ---
self.content_frame = ttk.LabelFrame(