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:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."),
|
||||
}
|
||||
}
|
||||
0
pybackup/01-September-2025_000000_system_full.txt
Normal file
0
pybackup/01-September-2025_000000_system_full.txt
Normal 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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user