This commit introduces two main improvements: 1. **Backup Deletion:** The user can now delete system and user backups from the "Backup Content" view. 2. **Improved Exclusion List:** The `.cache` directory is now excluded from backups by default, which should prevent "file has vanished" warnings from rsync.
147 lines
5.9 KiB
Python
147 lines
5.9 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, **kwargs):
|
|
super().__init__(master, **kwargs)
|
|
self.backup_manager = backup_manager
|
|
|
|
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):
|
|
# Placeholder for restore logic
|
|
selected_item = self.content_tree.focus()
|
|
if not selected_item:
|
|
return
|
|
backup_name = self.content_tree.item(selected_item)["values"][0]
|
|
print(f"Restoring {backup_name}...")
|
|
|
|
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)
|
|
|
|
# Ask for confirmation
|
|
from shared_libs.message import MessageDialog
|
|
dialog = MessageDialog(master=self, message_type="warning",
|
|
title=Msg.STR["confirm_delete_title"],
|
|
text=Msg.STR["confirm_delete_text"].format(folder_name=folder_name),
|
|
buttons=["ok_cancel"])
|
|
if dialog.get_result() != "ok":
|
|
return
|
|
|
|
self.backup_manager.delete_privileged_path(folder_to_delete)
|
|
self._load_backup_content()
|