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.
182 lines
7.2 KiB
Python
182 lines
7.2 KiB
Python
import tkinter as tk
|
|
from tkinter import ttk
|
|
import os
|
|
|
|
from pbp_app_config import Msg
|
|
from pyimage_ui.comment_editor_dialog import CommentEditorDialog
|
|
|
|
|
|
class SystemBackupContentFrame(ttk.Frame):
|
|
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
|
|
|
|
# --- Backup Content List View ---
|
|
self.content_frame = ttk.LabelFrame(
|
|
self, text=Msg.STR["backup_content"], padding=10)
|
|
self.content_frame.pack(fill=tk.BOTH, expand=True)
|
|
|
|
columns = ("date", "type", "size", "comment", "folder_name")
|
|
self.content_tree = ttk.Treeview(
|
|
self.content_frame, columns=columns, show="headings")
|
|
self.content_tree.heading(
|
|
"date", text=Msg.STR["date"])
|
|
self.content_tree.heading(
|
|
"type", text=Msg.STR["type"])
|
|
self.content_tree.heading(
|
|
"size", text=Msg.STR["size"])
|
|
self.content_tree.heading(
|
|
"comment", text=Msg.STR["comment"])
|
|
self.content_tree.heading(
|
|
"folder_name", text=Msg.STR["folder"])
|
|
|
|
self.content_tree.column("date", width=120, anchor="w")
|
|
self.content_tree.column("type", width=80, anchor="center")
|
|
self.content_tree.column("size", width=100, anchor="e")
|
|
self.content_tree.column("comment", width=200, anchor="w")
|
|
self.content_tree.column("folder_name", width=250, anchor="w")
|
|
|
|
self.content_tree.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
|
|
|
|
self.content_tree.bind("<<TreeviewSelect>>", self._on_item_select)
|
|
|
|
list_button_frame = ttk.Frame(self.content_frame)
|
|
list_button_frame.pack(pady=10)
|
|
|
|
self.restore_button = ttk.Button(list_button_frame, text=Msg.STR["restore"],
|
|
command=self._restore_selected, state="disabled")
|
|
self.restore_button.pack(side=tk.LEFT, padx=5)
|
|
|
|
self.delete_button = ttk.Button(list_button_frame, text=Msg.STR["delete"],
|
|
command=self._delete_selected, state="disabled")
|
|
self.delete_button.pack(side=tk.LEFT, padx=5)
|
|
|
|
self.edit_comment_button = ttk.Button(list_button_frame, text="Kommentar bearbeiten",
|
|
command=self._edit_comment, state="disabled")
|
|
self.edit_comment_button.pack(side=tk.LEFT, padx=5)
|
|
|
|
def show(self, backup_path):
|
|
if backup_path and self.backup_path != backup_path:
|
|
self.backup_path = backup_path
|
|
self._load_backup_content()
|
|
|
|
def hide(self):
|
|
self.grid_remove()
|
|
|
|
def _load_backup_content(self):
|
|
for i in self.content_tree.get_children():
|
|
self.content_tree.delete(i)
|
|
|
|
if not self.backup_path or not os.path.isdir(self.backup_path):
|
|
return
|
|
|
|
# Use the new method to get structured system backup data
|
|
system_backups = self.backup_manager.list_system_backups(
|
|
self.backup_path)
|
|
|
|
for backup_info in system_backups:
|
|
self.content_tree.insert("", "end", values=(
|
|
backup_info.get("date", "N/A"),
|
|
backup_info.get("type", "N/A"),
|
|
backup_info.get("size", "N/A"),
|
|
backup_info.get("comment", ""),
|
|
backup_info.get("folder_name", "N/A")
|
|
))
|
|
self._on_item_select(None) # Disable buttons initially
|
|
|
|
def _on_item_select(self, event):
|
|
selected_item = self.content_tree.focus()
|
|
is_selected = True if selected_item else False
|
|
self.restore_button.config(
|
|
state="normal" if is_selected else "disabled")
|
|
self.delete_button.config(
|
|
state="normal" if is_selected else "disabled")
|
|
self.edit_comment_button.config(
|
|
state="normal" if is_selected else "disabled")
|
|
|
|
def _edit_comment(self):
|
|
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] # Assuming folder_name is the 5th value
|
|
|
|
# Construct the path to the info file
|
|
pybackup_path = os.path.join(self.backup_path, "pybackup")
|
|
info_file_path = os.path.join(pybackup_path, f"{folder_name}.txt")
|
|
|
|
# The file should exist, but we can handle cases where it might not.
|
|
if not os.path.exists(info_file_path):
|
|
# If for some reason the info file is missing, we can create an empty one.
|
|
self.backup_manager.update_comment(info_file_path, "")
|
|
|
|
CommentEditorDialog(self, info_file_path, self.backup_manager)
|
|
self._load_backup_content() # Refresh list to show new comment
|
|
|
|
def _restore_selected(self):
|
|
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
|
|
|
|
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.
|
|
# 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", "/")
|
|
|
|
if not restore_dest_path:
|
|
print("Error: Restore destination not set.")
|
|
# Optionally, show a message box to the user
|
|
return
|
|
|
|
self.backup_manager.start_restore(
|
|
source_path=selected_backup['full_path'],
|
|
dest_path=restore_dest_path,
|
|
is_compressed=selected_backup['is_compressed']
|
|
)
|
|
except AttributeError:
|
|
print("Could not access main application instance to get restore path.")
|
|
|
|
def _delete_selected(self):
|
|
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] # Assuming folder_name is the 5th value
|
|
|
|
# Construct the full path to the backup folder
|
|
pybackup_path = os.path.join(self.backup_path, "pybackup")
|
|
folder_to_delete = os.path.join(pybackup_path, folder_name)
|
|
|
|
# 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)
|