From a92fedc4dd98dc273f7a735ed1607b91e065e2b7 Mon Sep 17 00:00:00 2001 From: vikdevelop Date: Tue, 16 Dec 2025 18:57:07 +0100 Subject: [PATCH 1/6] Attempt to fix saving icons I was notified of a problem concerning the long storage time of archives, which is caused by incorrect icon storage. This commit attempts to fix this problem in every way possible. --- src/core/archive.py | 34 ++++++++++++++++++++++++---------- src/core/de_config.py | 2 +- src/gui/window.py | 12 +++++++----- src/main.py | 2 +- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/core/archive.py b/src/core/archive.py index 43834461..7af4ce32 100644 --- a/src/core/archive.py +++ b/src/core/archive.py @@ -44,15 +44,12 @@ def start_saving(self): # In the periodic saving mode, it's not allowed to save the # configuration without creating the archive - if not self.path_with_filename.endswith(".sd.zip"): + if not self.path_with_filename.endswith(".sd.7z"): print("Moving the configuration to the user-defined directory") self._copy_config_to_folder() else: self._create_archive() - print("Moving the configuration archive to the user-defined directory") - shutil.copyfile('cfg.sd.zip', self.path_with_filename) - print("Configuration saved successfully.") remove_temp_file() @@ -65,7 +62,8 @@ def _copy_config_to_folder(self): # Create a new ZIP archive with 7-Zip def _create_archive(self): - cmd = ['7z', 'a', '-tzip', '-mx=3', '-x!*.zip', '-x!saving_status', 'cfg.sd.zip', '.'] + items_to_backup = [f for f in os.listdir(".") if f not in ('saving_status', '*.7z')] + cmd = ['7z', 'a', '-snL', '-mx=3', 'cfg.sd.7z', *items_to_backup] if settings["enable-encryption"] or os.path.exists(f"{CACHE}/pb"): if password: cmd.insert(4, "-mem=AES256") @@ -80,6 +78,9 @@ def _create_archive(self): else: print("7z finished with warnings:", proc.stderr) + print("Moving the configuration archive to the user-defined directory") + shutil.copyfile('cfg.sd.7z', self.path_with_filename) + class Unpack: def __init__(self, dir_path): self.path_with_filename = dir_path @@ -99,7 +100,7 @@ def start_importing(self): # Check, if the input is archive or folder def _check_config_type(self): # Check, if the input is folder or not - if self.path_with_filename.endswith(".sd.zip"): + if self.path_with_filename.endswith(".sd.zip") or self.path_with_filename.endswith(".sd.7z"): self._unpack_zip_archive() elif self.path_with_filename.endswith(".sd.tar.gz"): self._unpack_tar_archive() @@ -141,11 +142,24 @@ def _unpack_zip_archive(self): raise ValueError(first_error or "Wrong password") print("Checking password is completed.") - cmd = subprocess.run( - ['7z', 'x', '-y', f'-p{password}', self.path_with_filename, f'-o{TEMP_CACHE}'], - capture_output=True, text=True, check=True + cmd = ['7z', 'x', '-y', '-snL'] + + if password: + cmd.append(f'-p{password}') + + cmd.extend([ + self.path_with_filename, + f'-o{TEMP_CACHE}' + ]) + + proc = subprocess.run( + cmd, + capture_output=True, + text=True ) - print(cmd.stdout) + + if proc.returncode >= 7: + raise OSError(proc.stderr) def __handle_sync_error(self): # If 7-Zip returns an error regarding an incorrect password and the {CACHE}/sync file diff --git a/src/core/de_config.py b/src/core/de_config.py index f653dfa3..65b36b98 100644 --- a/src/core/de_config.py +++ b/src/core/de_config.py @@ -17,7 +17,7 @@ def safe_copy(src: str, dst: str): def safe_copytree(src: str, dst: str, ignore=None): if os.path.isdir(src): try: - shutil.copytree(src, dst, dirs_exist_ok=True, ignore=ignore) + shutil.copytree(src, dst, dirs_exist_ok=True, symlinks=True, ignore=ignore) print(f"[OK] Copied dir: {src} → {dst}") except Exception as e: print(f"[ERR] Dir copy failed {src} → {dst}: {e}") diff --git a/src/gui/window.py b/src/gui/window.py index dea00dbb..5af22be4 100644 --- a/src/gui/window.py +++ b/src/gui/window.py @@ -397,6 +397,7 @@ def open_selected(source, res, data): self.file_filter.set_name(_("Save Desktop files")) self.file_filter.add_pattern('*.sd.tar.gz') self.file_filter.add_pattern('*.sd.zip') + self.file_filter.add_pattern('*.sd.7z') self.file_filter_list = Gio.ListStore.new(Gtk.FileFilter); self.file_filter_list.append(self.file_filter) self.file_chooser.set_filters(self.file_filter_list) @@ -517,7 +518,7 @@ def save_config(self): self.archive_name = f"{self.folder}/{self.filename_text}" if not settings["save-without-archive"]: - self.archive_name += ".sd.zip" + self.archive_name += ".sd.7z" self.status_title = _("Saving configuration …\nThe configuration of your desktop environment will be saved in:\n {}/{}.sd.tar.gz\n").split('')[0].split('')[-1] self.status_desc = self._set_status_desc_save() @@ -530,7 +531,7 @@ def save_config(self): def _set_status_desc_save(self): status_old = _("Saving configuration …\nThe configuration of your desktop environment will be saved in:\n {}/{}.sd.tar.gz\n") - status = status_old.replace("sd.tar.gz", "sd.zip") if not settings["save-without-archive"] else status_old.replace("sd.tar.gz", "") + status = status_old.replace("sd.tar.gz", "sd.7z") if not settings["save-without-archive"] else status_old.replace("sd.tar.gz", "") return status.format(self.folder, self.filename_text) # Import configuration @@ -741,6 +742,7 @@ def on_close(self, w): # Remove this folder to cleanup unnecessary content created during saving, # importing, or syncing the configuration only if these files are not present def remove_cache(self): - files_to_check = [f"{CACHE}/pb", f"{CACHE}/sync", f"{CACHE}/workspace/flatpaks_installer.py"] - if not any(os.path.exists(path) for path in files_to_check): - shutil.rmtree(f"{CACHE}/workspace") + if os.path.exists(f"{CACHE}/workspace"): + files_to_check = [f"{CACHE}/pb", f"{CACHE}/sync", f"{CACHE}/workspace/flatpaks_installer.py"] + if not any(os.path.exists(path) for path in files_to_check): + shutil.rmtree(f"{CACHE}/workspace") diff --git a/src/main.py b/src/main.py index e9408004..6509e581 100644 --- a/src/main.py +++ b/src/main.py @@ -85,7 +85,7 @@ def open_dir(self, action, param): if settings["save-without-archive"]: path = f"{self.win.folder}/{self.win.filename_text}" else: - path = f"{self.win.folder}/{self.win.filename_text}.sd.zip" + path = f"{self.win.folder}/{self.win.filename_text}.sd.7z" Gtk.FileLauncher.new(Gio.File.new_for_path(path)).open_containing_folder() From 8da6b6191798f93615d9203ad26b47142c904a77 Mon Sep 17 00:00:00 2001 From: vikdevelop Date: Wed, 17 Dec 2025 19:19:00 +0100 Subject: [PATCH 2/6] 2nd attempt to fix saving icons --- src/core/archive.py | 9 ++++----- src/core/de_config.py | 24 +++++++++++++++++++----- src/gui/window.py | 3 +-- src/main.py | 2 +- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/core/archive.py b/src/core/archive.py index 7af4ce32..91b8ad90 100644 --- a/src/core/archive.py +++ b/src/core/archive.py @@ -44,7 +44,7 @@ def start_saving(self): # In the periodic saving mode, it's not allowed to save the # configuration without creating the archive - if not self.path_with_filename.endswith(".sd.7z"): + if not self.path_with_filename.endswith(".sd.zip"): print("Moving the configuration to the user-defined directory") self._copy_config_to_folder() else: @@ -62,8 +62,7 @@ def _copy_config_to_folder(self): # Create a new ZIP archive with 7-Zip def _create_archive(self): - items_to_backup = [f for f in os.listdir(".") if f not in ('saving_status', '*.7z')] - cmd = ['7z', 'a', '-snL', '-mx=3', 'cfg.sd.7z', *items_to_backup] + cmd = ['7z', 'a', '-snL', '-mx=3', '-x!*.zip', '-x!saving_status', 'cfg.sd.zip', "."] if settings["enable-encryption"] or os.path.exists(f"{CACHE}/pb"): if password: cmd.insert(4, "-mem=AES256") @@ -79,7 +78,7 @@ def _create_archive(self): print("7z finished with warnings:", proc.stderr) print("Moving the configuration archive to the user-defined directory") - shutil.copyfile('cfg.sd.7z', self.path_with_filename) + shutil.copyfile('cfg.sd.zip', self.path_with_filename) class Unpack: def __init__(self, dir_path): @@ -100,7 +99,7 @@ def start_importing(self): # Check, if the input is archive or folder def _check_config_type(self): # Check, if the input is folder or not - if self.path_with_filename.endswith(".sd.zip") or self.path_with_filename.endswith(".sd.7z"): + if self.path_with_filename.endswith(".sd.zip"): self._unpack_zip_archive() elif self.path_with_filename.endswith(".sd.tar.gz"): self._unpack_tar_archive() diff --git a/src/core/de_config.py b/src/core/de_config.py index 65b36b98..8fb8dd2e 100644 --- a/src/core/de_config.py +++ b/src/core/de_config.py @@ -1,4 +1,4 @@ -import os, shutil, argparse +import os, shutil, argparse, subprocess from gi.repository import GLib from savedesktop.globals import * @@ -71,8 +71,12 @@ def __init__(self): safe_copytree(f"{home}/.local/share/backgrounds", "backgrounds") safe_copytree(f"{home}/.local/share/wallpapers", "xdg-data/wallpapers") if settings["save-icons"]: - safe_copytree(f"{home}/.icons", ".icons") - safe_copytree(f"{home}/.local/share/icons", "icons") + xdg_path = f"{home}/.local/share" + legacy_path = f"{home}" + if os.path.isdir(f"{xdg_path}/icons") and os.listdir(f"{xdg_path}/icons"): + subprocess.run(["tar", "-czvf", "icon-themes.tgz", "-C", xdg_path, "icons"]) + if os.path.isdir(f"{legacy_path}/.icons") and os.listdir(f"{legacy_path}/.icons"): + subprocess.run(["tar", "-czvf", "icon-themes-legacy.tgz", "-C", legacy_path, ".icons"]) # Desktop folder if settings["save-desktop-folder"]: @@ -160,8 +164,7 @@ def __init__(self): safe_copytree("gvfs-metadata", f"{home}/.local/share/gvfs-metadata") safe_copytree("backgrounds", f"{home}/.local/share/backgrounds") safe_copytree("wallpapers", f"{home}/.local/share/wallpapers") - safe_copytree("icons", f"{home}/.local/share/icons") - safe_copytree(".icons", f"{home}/.icons") + self.import_icons() # Environment specific if environment: @@ -180,6 +183,17 @@ def __init__(self): if any(os.path.exists(path) for path in ["app", "installed_flatpaks.sh", "installed_user_flatpaks.sh"]): self.create_flatpak_autostart() + # Extract an archive with icon themes + def import_icons(self): + if os.path.exists(f"icon-themes.tgz"): + subprocess.run(["tar", "-xzvf", "icon-themes.tgz"]) + if os.path.exists(f"icon-themes-legacy.tgz"): + subprocess.run(["tar", "-xzvf", "icon-themes-legacy.tgz"]) + print("[OK] Extracting an icons' archive") + + safe_copytree("icons", f"{home}/.local/share/icons") + safe_copytree(".icons", f"{home}/.icons") + # Create an autostart file to install Flatpaks from a list after the next login def create_flatpak_autostart(self): os.system(f"cp /app/share/savedesktop/savedesktop/core/flatpaks_installer.py {CACHE}/workspace") diff --git a/src/gui/window.py b/src/gui/window.py index 5af22be4..75ec2652 100644 --- a/src/gui/window.py +++ b/src/gui/window.py @@ -397,7 +397,6 @@ def open_selected(source, res, data): self.file_filter.set_name(_("Save Desktop files")) self.file_filter.add_pattern('*.sd.tar.gz') self.file_filter.add_pattern('*.sd.zip') - self.file_filter.add_pattern('*.sd.7z') self.file_filter_list = Gio.ListStore.new(Gtk.FileFilter); self.file_filter_list.append(self.file_filter) self.file_chooser.set_filters(self.file_filter_list) @@ -518,7 +517,7 @@ def save_config(self): self.archive_name = f"{self.folder}/{self.filename_text}" if not settings["save-without-archive"]: - self.archive_name += ".sd.7z" + self.archive_name += ".sd.zip" self.status_title = _("Saving configuration …\nThe configuration of your desktop environment will be saved in:\n {}/{}.sd.tar.gz\n").split('')[0].split('')[-1] self.status_desc = self._set_status_desc_save() diff --git a/src/main.py b/src/main.py index 6509e581..e9408004 100644 --- a/src/main.py +++ b/src/main.py @@ -85,7 +85,7 @@ def open_dir(self, action, param): if settings["save-without-archive"]: path = f"{self.win.folder}/{self.win.filename_text}" else: - path = f"{self.win.folder}/{self.win.filename_text}.sd.7z" + path = f"{self.win.folder}/{self.win.filename_text}.sd.zip" Gtk.FileLauncher.new(Gio.File.new_for_path(path)).open_containing_folder() From 2eef61723b816dfad0f531dea1bbf3dd14f44f57 Mon Sep 17 00:00:00 2001 From: vikdevelop Date: Thu, 18 Dec 2025 16:36:13 +0100 Subject: [PATCH 3/6] Set saving flatpaks data and desktop folder to the archive --- src/core/de_config.py | 61 +++++++++++++++++----------------- src/core/flatpaks_installer.py | 6 +++- src/gui/window.py | 2 +- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/core/de_config.py b/src/core/de_config.py index 8fb8dd2e..3cce3301 100644 --- a/src/core/de_config.py +++ b/src/core/de_config.py @@ -1,6 +1,7 @@ import os, shutil, argparse, subprocess from gi.repository import GLib from savedesktop.globals import * +from pathlib import Path # Helping functions def safe_copy(src: str, dst: str): @@ -45,6 +46,9 @@ def safe_copytree(src: str, dst: str, ignore=None): ("xdg-data", f"{home}/.local/share"), ] +# The ~/Desktop folder definition +desktop_dir = Path(GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP)) + class Save: def __init__(self): @@ -74,15 +78,13 @@ def __init__(self): xdg_path = f"{home}/.local/share" legacy_path = f"{home}" if os.path.isdir(f"{xdg_path}/icons") and os.listdir(f"{xdg_path}/icons"): - subprocess.run(["tar", "-czvf", "icon-themes.tgz", "-C", xdg_path, "icons"]) + subprocess.run(["tar", "-czf", "icon-themes.tgz", "-C", xdg_path, "icons"]) if os.path.isdir(f"{legacy_path}/.icons") and os.listdir(f"{legacy_path}/.icons"): - subprocess.run(["tar", "-czvf", "icon-themes-legacy.tgz", "-C", legacy_path, ".icons"]) + subprocess.run(["tar", "-czf", "icon-themes-legacy.tgz", "-C", legacy_path, ".icons"]) # Desktop folder if settings["save-desktop-folder"]: - desktop_dir = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP) - if desktop_dir: - safe_copytree(desktop_dir, "Desktop") + subprocess.run(["tar", "-czf", "desktop-folder.tgz", "-C", str(desktop_dir.parent), str(desktop_dir.name)]) safe_copytree(f"{home}/.local/share/gvfs-metadata", "gvfs-metadata") # Flatpak apps and their data @@ -120,24 +122,14 @@ def save_flatpak_data(self): gsettings = settings["disabled-flatpak-apps-data"] black_list = gsettings # convert GSettings property to a list - os.makedirs(f"{CACHE}/workspace/app", exist_ok=True) - destdir = f"{CACHE}/workspace/app" - - # copy Flatpak apps data - for item in os.listdir(f"{home}/.var/app"): - if item not in black_list and item != "cache": - source_path = os.path.join(f"{home}/.var/app", item) - destination_path = os.path.join(destdir, item) - if os.path.isdir(source_path): - try: - shutil.copytree(source_path, destination_path, ignore=shutil.ignore_patterns('cache')) - except Exception as e: - print(f"Error copying directory {source_path}: {e}") - else: - try: - shutil.copy2(source_path, destination_path) - except Exception as e: - print(f"Error copying file {source_path}: {e}") + cmd = ["tar", "-czf", "flatpak-apps-data.tgz", "--exclude=*/cache"] + + for apps in black_list: + cmd.append(f"--exclude={apps}") + + cmd.extend(["-C", f"{home}/.var", "app"]) + + subprocess.run(cmd) class Import: def __init__(self): @@ -160,10 +152,10 @@ def __init__(self): safe_copytree("gnome-shell", f"{home}/.local/share/gnome-shell") safe_copytree("cinnamon", f"{home}/.local/share/cinnamon") safe_copytree("plasma", f"{home}/.local/share/plasma") - safe_copytree("Desktop", GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP)) safe_copytree("gvfs-metadata", f"{home}/.local/share/gvfs-metadata") safe_copytree("backgrounds", f"{home}/.local/share/backgrounds") safe_copytree("wallpapers", f"{home}/.local/share/wallpapers") + self.import_desktop_folder() self.import_icons() # Environment specific @@ -183,16 +175,25 @@ def __init__(self): if any(os.path.exists(path) for path in ["app", "installed_flatpaks.sh", "installed_user_flatpaks.sh"]): self.create_flatpak_autostart() + # Extract an archive with the Desktop folder + def import_desktop_folder(self): + if os.path.exists("desktop-folder.tgz"): + subprocess.run(["tar", "--keep-newer-files", "--no-overwrite-dir", "-xzvf", "desktop-folder.tgz", "-C", str(desktop_dir.parent)]) + print("[OK] Extracting a Desktop archive") + else: + safe_copytree("Desktop", GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP)) + # Extract an archive with icon themes def import_icons(self): if os.path.exists(f"icon-themes.tgz"): - subprocess.run(["tar", "-xzvf", "icon-themes.tgz"]) + subprocess.run(["tar", "--keep-newer-files", "--no-overwrite-dir", "-xzvf", "icon-themes.tgz", "-C", f"{home}/.local/share/icons"]) + print("[OK] Extracting a XDG icons archive") if os.path.exists(f"icon-themes-legacy.tgz"): - subprocess.run(["tar", "-xzvf", "icon-themes-legacy.tgz"]) - print("[OK] Extracting an icons' archive") - - safe_copytree("icons", f"{home}/.local/share/icons") - safe_copytree(".icons", f"{home}/.icons") + print(f"[OK] Extracting a legacy icons archive") + subprocess.run(["tar", "--keep-newer-files", "--no-overwrite-dir", "-xzf", "icon-themes-legacy.tgz", "--keep-new-files", "-C", f"{home}/.icons", "--keep-new-files"]) + else: + safe_copytree("icons", f"{home}/.local/share/icons") + safe_copytree(".icons", f"{home}/.icons") # Create an autostart file to install Flatpaks from a list after the next login def create_flatpak_autostart(self): diff --git a/src/core/flatpaks_installer.py b/src/core/flatpaks_installer.py index 096d928d..dc3fe965 100644 --- a/src/core/flatpaks_installer.py +++ b/src/core/flatpaks_installer.py @@ -23,12 +23,16 @@ dest_dir = None # If the destination directory variable is not 'None', continue in installing Flatpak apps -if not dest_dir == None: +if dest_dir: # If the destination directory has a directory with installed Flatpak apps user data, install them if os.path.exists(f"{dest_dir}/app"): print("copying the Flatpak apps' user data to the ~/.var/app directory") os.system(f"cp -au {dest_dir}/app/ ~/.var/") + # If the flatpak-apps-data.tgz archive exists, unpack it to the ~/.var/app directory + if os.path.exists(f"{dest_dir}/flatpak-apps-data.tgz"): + subprocess.run(["tar", "--keep-newer-files", "--no-overwrite-dir", "-xzvf", "flatpak-apps-data.tgz", "-C", f"{home}/.var"]) + # If the Bash scripts for installing Flatpak apps to the system exist, install them if os.path.exists(f"{dest_dir}/installed_flatpaks.sh") or os.path.exists(f"{dest_dir}/installed_user_flatpaks.sh"): print("installing the Flatpak apps on the system") diff --git a/src/gui/window.py b/src/gui/window.py index 75ec2652..4e9bdc1c 100644 --- a/src/gui/window.py +++ b/src/gui/window.py @@ -530,7 +530,7 @@ def save_config(self): def _set_status_desc_save(self): status_old = _("Saving configuration …\nThe configuration of your desktop environment will be saved in:\n {}/{}.sd.tar.gz\n") - status = status_old.replace("sd.tar.gz", "sd.7z") if not settings["save-without-archive"] else status_old.replace("sd.tar.gz", "") + status = status_old.replace("sd.tar.gz", "sd.zip") if not settings["save-without-archive"] else status_old.replace("sd.tar.gz", "") return status.format(self.folder, self.filename_text) # Import configuration From c73f6963f2cc74f8fbcaf91a7c6fcd436cc8816d Mon Sep 17 00:00:00 2001 From: vikdevelop Date: Thu, 18 Dec 2025 17:37:22 +0100 Subject: [PATCH 4/6] Remove the --keep-newer-files argument from the Tar commands --- src/core/de_config.py | 8 ++++---- src/core/flatpaks_installer.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/de_config.py b/src/core/de_config.py index 3cce3301..76b524cc 100644 --- a/src/core/de_config.py +++ b/src/core/de_config.py @@ -172,13 +172,13 @@ def __init__(self): print(f"[WARN] Unknown DE: {environment_key}") if flatpak: - if any(os.path.exists(path) for path in ["app", "installed_flatpaks.sh", "installed_user_flatpaks.sh"]): + if any(os.path.exists(path) for path in ["app", "flatpak-apps-data.tgz", "installed_flatpaks.sh", "installed_user_flatpaks.sh"]): self.create_flatpak_autostart() # Extract an archive with the Desktop folder def import_desktop_folder(self): if os.path.exists("desktop-folder.tgz"): - subprocess.run(["tar", "--keep-newer-files", "--no-overwrite-dir", "-xzvf", "desktop-folder.tgz", "-C", str(desktop_dir.parent)]) + subprocess.run(["tar", "-xzvf", "desktop-folder.tgz", "-C", str(desktop_dir.parent)]) print("[OK] Extracting a Desktop archive") else: safe_copytree("Desktop", GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP)) @@ -186,11 +186,11 @@ def import_desktop_folder(self): # Extract an archive with icon themes def import_icons(self): if os.path.exists(f"icon-themes.tgz"): - subprocess.run(["tar", "--keep-newer-files", "--no-overwrite-dir", "-xzvf", "icon-themes.tgz", "-C", f"{home}/.local/share/icons"]) + subprocess.run(["tar", "-xzvf", "icon-themes.tgz", "-C", f"{home}/.local/share/icons"]) print("[OK] Extracting a XDG icons archive") if os.path.exists(f"icon-themes-legacy.tgz"): print(f"[OK] Extracting a legacy icons archive") - subprocess.run(["tar", "--keep-newer-files", "--no-overwrite-dir", "-xzf", "icon-themes-legacy.tgz", "--keep-new-files", "-C", f"{home}/.icons", "--keep-new-files"]) + subprocess.run(["tar", "-xzvf", "icon-themes-legacy.tgz", "-C", f"{home}/.icons"]) else: safe_copytree("icons", f"{home}/.local/share/icons") safe_copytree(".icons", f"{home}/.icons") diff --git a/src/core/flatpaks_installer.py b/src/core/flatpaks_installer.py index dc3fe965..674261bf 100644 --- a/src/core/flatpaks_installer.py +++ b/src/core/flatpaks_installer.py @@ -31,7 +31,7 @@ # If the flatpak-apps-data.tgz archive exists, unpack it to the ~/.var/app directory if os.path.exists(f"{dest_dir}/flatpak-apps-data.tgz"): - subprocess.run(["tar", "--keep-newer-files", "--no-overwrite-dir", "-xzvf", "flatpak-apps-data.tgz", "-C", f"{home}/.var"]) + subprocess.run(["tar", "-xzvf", "flatpak-apps-data.tgz", "-C", f"{Path.home()}/.var"]) # If the Bash scripts for installing Flatpak apps to the system exist, install them if os.path.exists(f"{dest_dir}/installed_flatpaks.sh") or os.path.exists(f"{dest_dir}/installed_user_flatpaks.sh"): @@ -82,4 +82,4 @@ os.remove(autostart_file) # Remove the cache dir after finishing the operations -shutil.rmtree(f"{CACHE}/workspace") +shutil.rmtree(f"{CACHE_FLATPAK}/workspace") From 36d4c9e9aa051cc6945ff687c008155c1f97e345 Mon Sep 17 00:00:00 2001 From: vikdevelop Date: Fri, 19 Dec 2025 22:09:39 +0100 Subject: [PATCH 5/6] Improve status messages and showing output in terminal during saving/import --- src/core/de_config.py | 10 ++++++---- src/gui/window.py | 7 ++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/core/de_config.py b/src/core/de_config.py index 76b524cc..bb535f35 100644 --- a/src/core/de_config.py +++ b/src/core/de_config.py @@ -81,20 +81,21 @@ def __init__(self): subprocess.run(["tar", "-czf", "icon-themes.tgz", "-C", xdg_path, "icons"]) if os.path.isdir(f"{legacy_path}/.icons") and os.listdir(f"{legacy_path}/.icons"): subprocess.run(["tar", "-czf", "icon-themes-legacy.tgz", "-C", legacy_path, ".icons"]) + print("[OK] Saving icons") # Desktop folder if settings["save-desktop-folder"]: subprocess.run(["tar", "-czf", "desktop-folder.tgz", "-C", str(desktop_dir.parent), str(desktop_dir.name)]) safe_copytree(f"{home}/.local/share/gvfs-metadata", "gvfs-metadata") + print("[OK] Saving ~/Desktop folder") # Flatpak apps and their data if flatpak: if settings["save-installed-flatpaks"]: - print("saving list of installed Flatpak apps") os.system("ls /var/lib/flatpak/app/ | awk '{print \"flatpak install --system \" $1 \" -y\"}' > ./installed_flatpaks.sh") os.system("ls ~/.local/share/flatpak/app | awk '{print \"flatpak install --user \" $1 \" -y\"}' > ./installed_user_flatpaks.sh") + print("[OK] Saving list of installed Flatpak apps") if settings["save-flatpak-data"]: - print("saving user data of installed Flatpak apps") self.save_flatpak_data() # Environment specific @@ -130,6 +131,7 @@ def save_flatpak_data(self): cmd.extend(["-C", f"{home}/.var", "app"]) subprocess.run(cmd) + print("[OK] Saving Flatpak apps' data") class Import: def __init__(self): @@ -186,11 +188,11 @@ def import_desktop_folder(self): # Extract an archive with icon themes def import_icons(self): if os.path.exists(f"icon-themes.tgz"): - subprocess.run(["tar", "-xzvf", "icon-themes.tgz", "-C", f"{home}/.local/share/icons"]) + subprocess.run(["tar", "-xzvf", "icon-themes.tgz", "-C", f"{home}/.local/share/"]) print("[OK] Extracting a XDG icons archive") if os.path.exists(f"icon-themes-legacy.tgz"): print(f"[OK] Extracting a legacy icons archive") - subprocess.run(["tar", "-xzvf", "icon-themes-legacy.tgz", "-C", f"{home}/.icons"]) + subprocess.run(["tar", "-xzvf", "icon-themes-legacy.tgz", "-C", f"{home}/"]) else: safe_copytree("icons", f"{home}/.local/share/icons") safe_copytree(".icons", f"{home}/.icons") diff --git a/src/gui/window.py b/src/gui/window.py index 4e9bdc1c..7c0f321f 100644 --- a/src/gui/window.py +++ b/src/gui/window.py @@ -512,7 +512,7 @@ def _checkDialog_closed(self, w, response): # Save configuration def save_config(self): - print("Saving the configuration is in progress…\nFull output will be available after finishing this operation.") + print("Saving the configuration is in progress…") self.archive_mode = "--create" self.archive_name = f"{self.folder}/{self.filename_text}" @@ -535,7 +535,7 @@ def _set_status_desc_save(self): # Import configuration def import_config(self): - print("Importing the configuration is in progress…\nFull output will be available after finishing this operation.") + print("Importing the configuration is in progress…") self.toast_overlay.dismiss_all() self.archive_name = self.path_to_import @@ -552,7 +552,7 @@ def import_config(self): def _call_archive_command(self): self.archive_proc = subprocess.Popen( [sys.executable, "-m", "savedesktop.core.archive", self.archive_mode, self.archive_name], - stdout=subprocess.PIPE, + stdout=None, stderr=subprocess.PIPE, text=True, env={**os.environ, "PYTHONPATH": f"{app_prefix}"} @@ -745,3 +745,4 @@ def remove_cache(self): files_to_check = [f"{CACHE}/pb", f"{CACHE}/sync", f"{CACHE}/workspace/flatpaks_installer.py"] if not any(os.path.exists(path) for path in files_to_check): shutil.rmtree(f"{CACHE}/workspace") + From 6f5d5656edc598418ec9d983a1bf8da03969f563 Mon Sep 17 00:00:00 2001 From: vikdevelop Date: Wed, 24 Dec 2025 14:26:09 +0100 Subject: [PATCH 6/6] Bump to v3.8.1 Also: - improved GTK layout - improved a message about imported configuration --- meson.build | 2 +- po/savedesktop.pot | 2 +- src/gui/window.py | 24 ++++++++++++++++-------- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/meson.build b/meson.build index ab36c0a9..5b33babc 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('savedesktop', - version: '3.8', + version: '3.8.1', meson_version: '>= 1.0.0', default_options: [ 'warning_level=2', 'werror=false', ], ) diff --git a/po/savedesktop.pot b/po/savedesktop.pot index 29446f84..f9fc823d 100644 --- a/po/savedesktop.pot +++ b/po/savedesktop.pot @@ -255,7 +255,7 @@ msgstr "" #: src/gui/window.py msgid "" -"{}\nYou can log out of the system for the changes to take effect, or go back to the previous page and log out later.\n" +"{}\nYou can log out of the system for the changes to take effect, or go back to the previous page and log out later.\n\nIf your archive contains Flatpak apps, they will start installing after the next login." msgstr "" #: src/gui/window.py diff --git a/src/gui/window.py b/src/gui/window.py index 7c0f321f..48894646 100644 --- a/src/gui/window.py +++ b/src/gui/window.py @@ -49,10 +49,18 @@ def __init__(self, *args, **kwargs): self.headerbar.pack_end(child=self.menu_button) # primary layout + self.scrolled = Gtk.ScrolledWindow() + self.scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) + self.scrolled.set_vexpand(True) + self.scrolled.set_hexpand(True) + self.toolbarview.set_content(self.scrolled) + self.headapp = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) - self.headapp.set_valign(Gtk.Align.CENTER) - self.headapp.set_halign(Gtk.Align.CENTER) - self.toolbarview.set_content(self.headapp) + self.headapp.set_valign(Gtk.Align.FILL) + self.headapp.set_halign(Gtk.Align.FILL) + self.headapp.set_vexpand(True) + self.headapp.set_hexpand(True) + self.scrolled.set_child(self.headapp) # A view container for the menu switcher self.stack = Adw.ViewStack(vexpand=True) @@ -543,7 +551,7 @@ def import_config(self): self.status_title = _("Importing configuration …\nImporting configuration from:\n{}\n").split('')[0].split('')[-1] self.status_desc = _("Importing configuration …\nImporting configuration from:\n{}\n").format(self.archive_name) self.done_title = _("The configuration has been applied!") - self.done_desc = _("{}\nYou can log out of the system for the changes to take effect, or go back to the previous page and log out later.\n").format(_("The configuration has been applied!")) + self.done_desc = _("{}\nYou can log out of the system for the changes to take effect, or go back to the previous page and log out later.\n\nIf your archive contains Flatpak apps, they will start installing after the next login.").format(_("The configuration has been applied!")) self.please_wait() import_thread = Thread(target=self._call_archive_command) @@ -576,10 +584,10 @@ def please_wait(self): # Create box widget for this page self.status_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) - self.status_box.set_halign(Gtk.Align.CENTER) - self.status_box.set_valign(Gtk.Align.CENTER) + self.status_box.set_vexpand(True) + self.status_box.set_hexpand(True) self.status_box.set_size_request(350, 100) - self.toolbarview.set_content(self.status_box) + self.scrolled.set_child(self.status_box) # Set bold title self.set_title(self.status_title) @@ -684,7 +692,7 @@ def _back_to_main(self, w): self.status_box.remove(widget) def _set_default_widgets_state(self): - self.toolbarview.set_content(self.headapp) + self.scrolled.set_child(self.headapp) self.headerbar.set_title_widget(self.switcher_title) self.set_title("Save Desktop") self.apply_handler = self.break_point.connect("apply", self.__on_break_point_apply)