This commit introduces a major refactoring of the settings and advanced settings panels to improve user experience and code structure.
Key Changes:
1. **Reset Functionality Refactored:**
- The "Default Settings" logic has been moved from `actions.py` into `settings_frame.py`, where it belongs.
- Clicking "Reset" now opens a dedicated view with separate options for a "Default Reset" and a "Hard Reset", each with clear explanations.
- A global "Cancel" button was added for this new view, and the layout of the components has been centered and cleaned up.
- Error handling for the reset process has been improved to show feedback in the header.
2. **Keyfile Creation UX Overhauled:**
- The "Automation Settings" (Keyfile) view in Advanced Settings is completely redesigned for clarity.
- It now explicitly displays the currently selected backup destination, so the user knows which container will be affected.
- A detailed description has been added to explain the purpose and prerequisites of creating a keyfile.
- The redundant "Apply" button is now hidden in this view.
- Feedback for keyfile creation (success or failure) is now shown as a temporary message in the header instead of a blocking dialog.
- Error messages are more informative, guiding the user on how to proceed (e.g., by creating an encrypted backup first).
3. **String Externalization:**
- All new UI text for the keyfile and reset features has been added to `pbp_app_config.py` to support translation.
This commit introduces several improvements to the user interface and application logic:
- **UI Feedback:**
- Replaces the subtitle text change with a large, centered, temporary message for better visibility of feedback like "Settings saved" or "Hard reset successful".
- Adds several new message strings to `pbp_app_config.py` for consistent UI text.
- **Hard Reset:**
- Fixes a bug where encrypted drives were not unmounted during a hard reset.
- The `_perform_hard_reset` function now correctly uses the existing `encryption_manager` instance to unmount all drives before deleting the configuration and restarting the application.
- The application now provides clear feedback during and after the hard reset process.
- **Settings:**
- Improves the "Advanced Settings" and "Settings" frames by adding success messages and preventing errors on empty selections.
- The main application closing sequence (`on_closing`) is also made more robust, mirroring the new hard reset logic for unmounting drives.
Adds a warning message to the main UI.
The message "Accurate detection is only possible when the drive is mounted" is now displayed in addition to the standard "You can start a backup here" text, under the following conditions:
- The backup mode is active.
- The "Encrypt Backup" option is enabled for the current profile.
- The corresponding encrypted drive is not currently mounted.
This provides clearer feedback to the user on why size calculations might be unavailable or inaccurate for encrypted targets.
This commit introduces several major improvements to the handling of encrypted incremental backups.
1. **Fix LUKS Container Resize:**
The `encryption_helper.sh` script has been fixed to reliably resize LUKS containers. The `cryptsetup resize` command now correctly re-authenticates, resolving an issue where the script would fail because it was incorrectly trying to read a password from an empty stdin stream.
2. **Refactor Backup Directory Structure:**
The storage path for encrypted user backups has been flattened. Backups are now stored directly in the encrypted mount point (e.g., `/backup/pybackup/encrypted_videos/BACKUP_NAME`) instead of a deeply nested folder (`.../user/SOURCE_NAME/BACKUP_NAME`). This simplifies the directory structure as requested.
3. **Correct Incremental Size Estimation:**
The `estimate_incremental_size` function is now more robust.
- The `rsync` command for user backups now correctly uses a trailing slash on the source path.
- This ensures the `--link-dest` comparison works as intended against the new, flat directory structure, leading to an accurate calculation of the required incremental size.
4. **Refine Container Resize Trigger and Logic:**
The logic for automatically resizing encrypted containers in `encryption_manager.py` has been completely overhauled to prevent excessive growth:
- A resize is now only triggered if the projected free space after a backup would fall below a 4 GB buffer.
- The calculation for the new size now correctly adds the required space plus the 4 GB buffer, ensuring sufficient space without over-provisioning.
This commit addresses several bugs related to the Advanced Settings functionality:
- **Fix:** Ensure saved default settings (e.g., force encryption) are correctly applied to the main UI on application startup.
- **Fix:** Prevent the UI from automatically switching away from the Advanced Settings view after clicking "Apply". Settings are now saved in the background, and a temporary success message is displayed in the header.
- **Fix:** Ensure settings are correctly reloaded and displayed when switching between tabs within the Advanced Settings view, resolving inconsistencies after a reset operation.
This commit addresses several issues related to encrypted drive handling during application shutdown and provides better user feedback.
- **Fix(GUI):** Prevent `bgerror` by cancelling pending `_process_queue` calls when the application is closing.
- **Feat(Unmount):** Implement logic to prevent application closure if encrypted drives fail to unmount gracefully. A `MessageDialog` is now displayed to the user in such cases.
- **Feat(UI):** Enhance `HeaderFrame` to display the current mount status of encrypted drives, providing immediate visual feedback.
- **Fix(Syntax):** Correct `SyntaxError: unterminated f-string literal` in `encryption_manager.py` by using triple-quoted f-strings for multi-line content.
- **Fix(Translation):** Add missing translation strings (`unmount_failed_title`, `unmount_failed_message`) to `core/pbp_app_config.py`.
- **Fix(Unmount):** Remove `|| true` from shell commands in `unmount_and_reset_owner` to ensure actual unmount failures are correctly reported and handled by the application logic.
This commit introduces a new "Hard Reset" functionality in the settings, allowing users to reset the application to its initial state by deleting the configuration directory.
Key changes include:
- Added a "Hard Reset" button and a dedicated confirmation frame in `settings_frame.py`.
- Implemented the logic to delete the `.config/py_backup` directory and restart the application.
- Enhanced the hard reset process to unmount encrypted drives if they are mounted, prompting for a password if necessary.
To improve modularity and maintainability, the PasswordDialog class has been refactored:
- Moved PasswordDialog from `pyimage_ui/password_dialog.py` to `shared_libs/message.py`.
- Updated all references and imports to the new location.
- Externalized all user-facing strings in PasswordDialog for translation support.
Additionally, several bug fixes and improvements were made:
- Corrected object access hierarchy in `settings_frame.py` and `advanced_settings_frame.py` by passing manager instances directly.
- Handled `FileNotFoundError` in `actions.py` when selecting remote backup destinations, preventing crashes and displaying "N/A" for disk usage.
- Replaced incorrect `calculating_animation` reference with `animated_icon` in `actions.py`.
- Added missing translation keys in `pbp_app_config.py`.
Der Button für den Testlauf wurde nicht freigegeben, wenn die inkrementelle Berechnung abgeschlossen war. Dies wurde behoben, indem der Status des Buttons in der UI-Refresh-Funktion korrekt gesetzt wird.
fix(logging): Logger früher initialisieren
Der Logger wurde zu spät initialisiert, was dazu führte, dass einige Log-Meldungen auf der Konsole statt im Log-Fenster ausgegeben wurden. Die Initialisierung wurde vorgezogen, um alle Meldungen abzufangen.
refactor: Variablen umbenennen
Einige Variablen wurden für eine bessere Lesbarkeit und Konsistenz im gesamten Code umbenannt (z.B. `testlauf_var` zu `test_run_var`).
Dieses Commit ersetzt die meisten ttk.Checkbutton- und ttk.Radiobutton-Widgets in der gesamten Anwendung durch einen benutzerdefinierten "Switch"-Stil, um ein moderneres Erscheinungsbild zu erzielen.
Die Änderungen umfassen:
- **Hauptfenster**:
- Umwandlung der Backup-Optionen (Voll, Inkrementell, Komprimiert, Verschlüsselt) in Switches.
- Ersetzung der "Genaue Grössenberechnung"-Checkbox durch einen normalen Button.
- Verschiebung der "Testlauf"- und "Sicherheit umgehen"-Switches in die Seitenleiste unter "Einstellungen".
- **Scheduler**:
- Ersetzung aller Radio-Buttons und Checkboxen durch Switches, mit implementierter Logik zur Gewährleistung der exklusiven Auswahl für Backup-Typ und Frequenz.
- **Erweiterte Einstellungen**:
- Umwandlung aller Checkboxen im Abschnitt "Backup-Standards" in Switches.
- **Styling**:
- Hinzufügen eines neuen Stils `Switch2.TCheckbutton` für die Switches in der Seitenleiste, um sie an das dunkle Thema der Seitenleiste anzupassen. Die Konfiguration erfolgt direkt in `main_app.py`.
- **Fehlerbehebungen**:
- Behebung eines `AttributeError`-Absturzes, der durch die Verschiebung der Switches vor der Deklaration ihrer `tk.BooleanVar`-Variablen verursacht wurde.
- Anpassung der zugehörigen Logik in `pyimage_ui/actions.py` an den neuen Button.
This commit introduces the following changes:
- Enhanced Backup Option Logic:
- Implemented mutual exclusivity between 'Compressed' and 'Incremental' backups:
- If 'Compressed' is selected, 'Incremental' is deselected and disabled, and 'Full' is automatically selected.
- Implemented mutual exclusivity between 'Compressed' and 'Encrypted' backups:
- If 'Compressed' is selected, 'Encrypted' is deselected and disabled.
- If 'Encrypted' is selected, 'Compressed' is deselected and disabled.
- If 'Incremental' is selected, 'Compressed' is deselected and disabled.
- These rules are applied consistently across the main backup window, advanced settings, and scheduler.
- UI Improvements:
- Added 'Full', 'Incremental', 'Compressed', and 'Encrypted' checkboxes to the scheduler view.
- Adjusted the layout in the scheduler view to place 'Backup Options' next to 'Folders to back up'.
- Added missing string definitions for new UI elements in core/pbp_app_config.py.
- Refactoring:
- Updated _refresh_backup_options_ui in pyimage_ui/actions.py to handle the new logic.
- Modified _on_compression_toggle in pyimage_ui/advanced_settings_frame.py and _on_compression_toggle_scheduler in pyimage_ui/scheduler_frame.py to reflect the updated exclusivity rules.
- Adjusted _save_job and _load_scheduled_jobs in pyimage_ui/scheduler_frame.py to include and parse the new backup options.
- Updated _parse_job_comment in core/backup_manager.py to correctly parse new backup options from cron job comments.
This commit implements several UI/UX improvements for the "Backup Content" list view based on user feedback.
- feat(ui): User backups are now grouped by their full/incremental chains, similar to system backups, for a more logical and organized view.
- feat(ui): The color scheme for backup chains has been simplified. Each chain (a full backup and its incrementals) now shares a single color to improve visual grouping.
- feat(ui): Incremental backups are now denoted by a ▲ icon in the Type column instead of a different color or font style, providing a clear and clean indicator.
- fix(ui): Adjusted all column widths in the backup lists to ensure all data (especially Date and Time) is fully visible without truncation.
This commit refactors the backup size calculation logic and fixes several bugs related to rsync argument passing and UI actions.
- refactor(core): Centralized all incremental backup size calculation logic within the BackupManager class. This removes duplicated and buggy code from the DataProcessing class and ensures both post-backup reporting and pre-backup estimation use a single, robust implementation.
- fix(backup): The pre-backup "accurate size calculation" now works correctly for all backup types. It uses an `rsync --dry-run` with a proper temporary directory and correctly handles root permissions for system backups.
- fix(backup): The post-backup size reporting for incremental system backups is now accurate. It uses a root-privileged command to inspect file links and calculate the true disk usage, avoiding permission errors.
- fix(backup): Corrected multiple quoting issues with rsync arguments (`--link-dest`, `--exclude-from`) that caused backups to fail or misbehave.
- fix(ui): Fixed a TypeError that occurred when deleting a system backup from the "Backup Content" view.
- feat(backup): Added the `-v` (verbose) flag to rsync for user backups to provide better feedback in the UI.
Implements a more intuitive default view for the "Backup Content" screen based on user context.
- After a backup is completed, the "Backup Content" view will now automatically open the tab corresponding to the type of backup just performed (System or User).
- On a fresh application start, the "Backup Content" view will now always default to showing the "System" backups tab.
- This is achieved by adding state variables to the main app and modifying the navigation logic, while removing the previous behavior of saving the last-viewed tab to the config.
This commit addresses several bugs and improves the logic of the settings panels.
- fix(settings): The "Reset to default settings" action no longer deletes the user-defined file/folder exclusion list.
- fix(settings): Corrected a bug in the "Add to exclude list" function where new entries were not being written correctly. The logic is now more robust and prevents duplicate entries.
- fix(ui): Fixed a TclError crash in Advanced Settings caused by mixing `grid` and `pack` geometry managers.
- feat(settings): Implemented mutual exclusivity for the "trash bin" and "compression/encryption" checkboxes to prevent invalid configurations.
- i18n: Improved and clarified the English text for the trash bin feature descriptions to enable better translation.
Refactor the core backup and encryption logic to use a new, consistent directory structure. This new structure separates encrypted and unencrypted backups and centralizes metadata, making the system more robust and easier to manage.
Key changes:
- Implemented a new directory scheme:
/pybackup/
├── unencrypted/{system,user}/<source>/
├── encrypted/{system,user}/<source>/ (mount point)
├── metadata/
└── pybackup_encrypted.luks
- Reworked path generation logic in BackupManager and EncryptionManager to support the new structure.
- All backup, restore, and listing operations now correctly resolve paths based on the new scheme.
This also includes several bug fixes identified during the refactoring:
- fix(backup): Correctly quote rsync paths for user backups to prevent "No such file or directory" errors.
- fix(encryption): Change key lookup order to Keyring -> Keyfile -> Password Prompt, as requested.
- fix(ui): Remove eager auto-mount on startup to prevent unexpected password prompts. The app now only mounts when required by a user action.
This commit introduces several UI enhancements and bug fixes based on user feedback.
- **Backup Content View:**
- The "Folder" column is now displayed before the "Comment" column for user backups.
- The "Folder" column now shows the simple source name (e.g., "Dokumente") instead of the full backup name.
- Column alignment and widths have been adjusted in both system and user backup views for better readability.
- A timing issue causing progress bars to be missing after unlocking an encrypted volume has been resolved.
- **Advanced Settings:**
- New options have been added to control file deletion behavior (use trash or delete directly).
- The layout of the advanced settings panel has been refined.
- **Encryption:**
- Introduces a keyfile-based authentication mechanism for LUKS containers, reducing the need for password prompts.
- Replaces temporary script files with a dedicated runner script (`privileged_script_runner.sh`) for executing root commands, improving security and robustness.
This commit refactors the encrypted container management to significantly improve usability and robustness.
- **Reduced Password Prompts:** The entire resize operation (unmount, truncate, check, resize, mount) is now consolidated into a single script. This reduces the maximum number of password prompts during a backup with resize from four down to two.
- **Fix "No Space Left" Error:** The resize script is now more robust, including a filesystem check (`e2fsck`) before resizing to prevent the filesystem from failing to expand. This resolves the critical "No space left on device" error.
- **Session-wide Password Cache:** A simple in-memory cache for the LUKS password has been introduced. This prevents further password prompts when unmounting containers, for example, when the application is closed.
- **Improved Logging:** Privileged script execution now logs stderr output even on success, aiding future diagnostics.
This commit addresses several bugs related to the mounting, unmounting, and deletion of encrypted backups, as well as a crash when listing backups.
The key changes are:
- **Fix Double Mount on View:** Removed redundant mount operation when viewing encrypted backup contents. The mount is now handled by a single, centralized function.
- **Fix Deletion of Encrypted Backups:**
- The container is no longer re-mounted if already open, preventing a second password prompt.
- Deletion of encrypted *user* backups is now performed with user-level permissions, removing the need for a third password prompt via pkexec.
- **Fix UI Refresh after Deletion:** The backup list now correctly refreshes after a backup is deleted.
- **Fix Crash on Empty Backup List:** Resolved an `UnboundLocalError` that occurred when listing backups from an empty or non-existent backup directory.
- **Improve Mount Detection:** The `is_mounted` check is now more robust to prevent race conditions or other OS-level inconsistencies.
Replaced the LVM-on-a-file implementation with a more robust, industry-standard LUKS-on-a-file approach.
This change was motivated by persistent and hard-to-debug errors related to LVM state management and duplicate loop device detection during repeated mount/unmount cycles.
The new implementation provides several key benefits:
- **Robustness:** Eliminates the entire LVM layer, which was the root cause of the mount/unmount failures.
- **Improved UX:** Drastically reduces the number of password prompts for encrypted user backups. By changing ownership of the mountpoint, rsync can run with user privileges.
- **Enhanced Security:** The file transfer process (rsync) for user backups no longer runs with root privileges.
- **Better Usability:** Encrypted containers are now left mounted during the application's lifecycle and are only unmounted on exit, improving workflow for consecutive operations.
This commit introduces the core logic for handling incremental user backups.
Changes include:
- Updated `core/backup_manager.py`:
- Modified `_list_user_backups_from_path` to parse new naming convention for user backups (including `_full` and `_incremental`).
- Enhanced `_find_latest_backup` to filter by source name for user backups.
- Adjusted `_run_backup_path` to dynamically determine backup mode (full/incremental) for user backups and apply `--link-dest` accordingly.
- Updated `pyimage_ui/user_backup_content_frame.py`:
- Added `tag_colors` attribute for visual differentiation.
- Included 'type' column in the Treeview.
- Modified `_load_backup_content` to apply coloring based on backup type.
This commit introduces significant improvements to how encrypted backups are handled,
focusing on user experience and system integration.
- Persistent Mounts: Encrypted backup containers now remain mounted across UI view changes,
eliminating repeated password prompts when navigating the application. The container is
automatically unmounted when the destination changes or the application closes.
- Key Management Fallback: The mounting process now intelligently falls back from
keyring to keyfile, and finally to a user password prompt if previous methods fail.
- Enhanced UI Status: The header now provides detailed feedback on the encryption key
status, indicating whether a key is available (via keyring or keyfile) and if the
container is currently in use.
- Reduced pkexec Prompts: By keeping containers mounted, the number of system-level
pkexec authentication prompts is drastically reduced, improving workflow.
- Bug Fixes:
- Corrected a SyntaxError in encryption_manager.py related to string escaping.
- Fixed an AttributeError in header_frame.py by restoring the is_key_in_keyring method.
- Addressed a TclError on application shutdown by safely destroying Tkinter widgets.
Adds logic to prevent the screensaver or screen lock from activating while a backup is in progress.
- Uses a D-Bus call to `org.freedesktop.ScreenSaver.Inhibit` to request a lock.
- The lock is activated when a backup starts.
- The lock is reliably released when the backup finishes, fails, or is cancelled.