diff --git a/data/io.github.vikdevelop.SaveDesktop.metainfo.xml.in b/data/io.github.vikdevelop.SaveDesktop.metainfo.xml.in index 016ffa5e..e289d0f0 100644 --- a/data/io.github.vikdevelop.SaveDesktop.metainfo.xml.in +++ b/data/io.github.vikdevelop.SaveDesktop.metainfo.xml.in @@ -74,6 +74,7 @@
  • Redesigned Flatpak apps selection: shows app names (not IDs) and backs up selected apps together with their user data
  • New: Sync selected configuration items across PCs to keep archives consistent
  • Updated archive structure with full backward compatibility for older backups
  • +
  • During import, only what is actually in the archive will be displayed in the item selection dialog
  • Updated translations
  • diff --git a/io.github.vikdevelop.SaveDesktop.json b/io.github.vikdevelop.SaveDesktop.json index 2020c25d..1e4501be 100644 --- a/io.github.vikdevelop.SaveDesktop.json +++ b/io.github.vikdevelop.SaveDesktop.json @@ -47,8 +47,8 @@ { "type" : "git", "url" : "https://github.com/ip7z/7zip.git", - "tag" : "25.01", - "commit" : "5e96a8279489832924056b1fa82f29d5837c9469" + "tag" : "26.00", + "commit" : "839151eaaad24771892afaae6bac690e31e58384" } ], "x-checker-data" : { diff --git a/src/core/de_config.py b/src/core/de_config.py index 66f8931e..feda64a3 100644 --- a/src/core/de_config.py +++ b/src/core/de_config.py @@ -84,6 +84,7 @@ def export_flatpaks(path, output_file, install_type): f.write(f"flatpak install --{install_type} {app} -y\n") def create_flatpak_list(): + os.makedirs("Flatpak_Apps", exist_ok=True) export_flatpaks('/var/lib/flatpak/app/', 'Flatpak_Apps/installed_flatpaks.sh', 'system') export_flatpaks(f'{home}/.local/share/flatpak/app', 'Flatpak_Apps/installed_user_flatpaks.sh', 'user') print("[OK] Saving Flatpak app list") @@ -264,8 +265,6 @@ class Save: def __init__(self): os.makedirs("General", exist_ok=True) os.makedirs("DE", exist_ok=True) - os.makedirs("Flatpak_Apps", exist_ok=True) - os.makedirs("Custom_Dirs", exist_ok=True) # General dirs for item in GENERAL_ITEMS.values(): @@ -280,6 +279,7 @@ def __init__(self): # Custom dirs for folder in settings["custom-dirs"]: + os.makedirs("Custom_Dirs", exist_ok=True) short_folder = Path(folder).relative_to(home) safe_copytree(folder, f"Custom_Dirs/{short_folder}") diff --git a/src/gui/items_dialog.py b/src/gui/items_dialog.py index 3a581cc1..d534429a 100644 --- a/src/gui/items_dialog.py +++ b/src/gui/items_dialog.py @@ -6,11 +6,13 @@ from savedesktop.gui.flatpak_apps_dialog import FolderSwitchRow, FlatpakAppsDialog from savedesktop.core.synchronization_setup import create_savedesktop_json from savedesktop.globals import * - + class itemsDialog(Adw.AlertDialog): - def __init__(self, parent): + def __init__(self, parent, items_list=None): super().__init__() self.parent = parent + self.items_list = items_list if items_list is not None else [] + print(self.items_list) self.set_heading(_("Select configuration items")) self.set_body(_("These settings are used for manual and periodic saves, imports, and synchronization.")) @@ -34,7 +36,8 @@ def __init__(self, parent): self.icons_row.set_subtitle_lines(3) self.icons_row.add_suffix(self.switch_01) self.icons_row.set_activatable_widget(self.switch_01) - self.itemsBox.append(child=self.icons_row) + if self.should_show("icon-themes.tgz", "icon-themes-legacy.tgz"): + self.itemsBox.append(child=self.icons_row) # Switch and row of option 'Save themes' self.switch_02 = Gtk.Switch.new() @@ -49,7 +52,8 @@ def __init__(self, parent): self.themes_row.set_subtitle_lines(3) self.themes_row.add_suffix(self.switch_02) self.themes_row.set_activatable_widget(self.switch_02) - self.itemsBox.append(child=self.themes_row) + if self.should_show(".themes", "themes"): + self.itemsBox.append(child=self.themes_row) # Switch and row of option 'Save fonts' self.switch_03 = Gtk.Switch.new() @@ -64,7 +68,8 @@ def __init__(self, parent): self.fonts_row.set_subtitle_lines(3) self.fonts_row.add_suffix(self.switch_03) self.fonts_row.set_activatable_widget(self.switch_03) - self.itemsBox.append(child=self.fonts_row) + if self.should_show("fonts", ".fonts"): + self.itemsBox.append(child=self.fonts_row) # Switch and row of option 'Save backgrounds' self.switch_04 = Gtk.Switch.new() @@ -79,7 +84,8 @@ def __init__(self, parent): self.backgrounds_row.set_subtitle_lines(3) self.backgrounds_row.add_suffix(self.switch_04) self.backgrounds_row.set_activatable_widget(self.switch_04) - self.itemsBox.append(child=self.backgrounds_row) + if self.should_show("backgrounds"): + self.itemsBox.append(child=self.backgrounds_row) # show extension switch and row if user has installed these environments if environment["de_name"] in ["GNOME", "Cinnamon", "COSMIC (Old)", "KDE Plasma"]: @@ -100,7 +106,8 @@ def __init__(self, parent): self.gtk_row.set_subtitle_lines(3) self.gtk_row.add_suffix(self.switch_gtk) self.gtk_row.set_activatable_widget(self.switch_gtk) - self.itemsBox.append(child=self.gtk_row) + if self.should_show("gtk-3.0"): + self.itemsBox.append(child=self.gtk_row) # Switch and row of option 'Save Desktop' (~/Desktop) self.switch_de = Gtk.Switch.new() @@ -116,7 +123,8 @@ def __init__(self, parent): self.desktop_row.set_title_lines(2) self.desktop_row.add_suffix(self.switch_de) self.desktop_row.set_activatable_widget(self.switch_de) - self.itemsBox.append(child=self.desktop_row) + if self.should_show("desktop-folder.tgz"): + self.itemsBox.append(child=self.desktop_row) # Custom directories section self.custom_button = Gtk.Button.new_from_icon_name("go-next-symbolic") @@ -128,9 +136,10 @@ def __init__(self, parent): self.custom_row.set_title("Custom folders") self.custom_row.add_suffix(self.custom_button) self.custom_row.set_activatable_widget(self.custom_button) - self.itemsBox.append(child=self.custom_row) + if self.should_show("Custom_Dirs"): + self.itemsBox.append(child=self.custom_row) - if flatpak: + if flatpak and self.should_show("installed_flatpaks.sh"): self.flatpak_row = Adw.ExpanderRow.new() self.flatpak_row.set_title(title=_("Flatpak apps")) self.flatpak_row.set_subtitle(f"{_('Learn more')}") @@ -178,7 +187,6 @@ def __init__(self, parent): if settings["save-flatpak-data"]: self.switch_06.set_active(True) self.data_row.add_suffix(self.appsButton) - self.flatpak_data_sw_state = settings["save-flatpak-data"] self.switch_06.set_valign(align=Gtk.Align.CENTER) self.switch_07 = Gtk.Switch.new() @@ -207,7 +215,18 @@ def __init__(self, parent): self.add_response('ok', _("Apply")) self.set_response_appearance('ok', Adw.ResponseAppearance.SUGGESTED) self.connect('response', self.itemsdialog_closed) - + + def should_show(self, *search_terms): + if not self.items_list: + return True + + for term in search_terms: + for item in self.items_list: + if term in item: + return True + + return False + def _set_sw05_sensitivity(self, GParamBoolean, switch_05): if not self.switch_05.get_active(): self.switch_06.set_sensitive(False) @@ -219,7 +238,7 @@ def _set_sw05_sensitivity(self, GParamBoolean, switch_05): self.switch_07.set_sensitive(True) def _show_custom_dirs_dialog(self, w): - self.CDDialog = CustomDirsDialog(self.parent) + self.CDDialog = CustomDirsDialog(self.parent, self.items_list) self.CDDialog.choose(self.parent, None, None, None) self.CDDialog.present(self.parent) @@ -244,7 +263,8 @@ def show_extensions_row(self): self.ext_row.set_subtitle_lines(3) self.ext_row.add_suffix(self.switch_ext) self.ext_row.set_activatable_widget(self.switch_ext) - self.itemsBox.append(child=self.ext_row) + if self.should_show("cinnamon", "gnome-shell", "plasma"): + self.itemsBox.append(child=self.ext_row) # Action after closing itemsDialog def itemsdialog_closed(self, w, response): @@ -265,8 +285,3 @@ def itemsdialog_closed(self, w, response): settings["keep-flatpaks"] = self.switch_07.get_active() if hasattr(self, "switch_ext"): settings["save-extensions"] = self.switch_ext.get_active() - self.save_ext_switch_state = False - elif response == 'cancel': - if flatpak: - switch_status = self.flatpak_data_sw_state - settings["save-flatpak-data"] = switch_status diff --git a/src/gui/window.py b/src/gui/window.py index 37092539..49777558 100644 --- a/src/gui/window.py +++ b/src/gui/window.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -import os, sys, re, zipfile, random, string, gi, subprocess, locale, shutil +import os, sys, re, zipfile, random, string, gi, subprocess, locale, shutil, tarfile gi.require_version('Gtk', '4.0') gi.require_version('Adw', '1') from gi.repository import Gtk, Adw, Gio, GLib, Gdk @@ -537,20 +537,71 @@ def import_config(self): self._show_items_dialog() + # Get items which are available in the configuration archive or folder + def _get_archive_items(self): + tmp_file_path = f"{CACHE}/workspace/temp_file" + if os.path.exists(tmp_file_path): + with open(tmp_file_path) as f: + password = f.read().strip() + else: + password = None + + if self.archive_name.endswith(".sd.zip"): + if password: + result = subprocess.run( + ["7z", "l", "-slt", f"-p{password}", self.archive_name], + capture_output=True, + text=True, + check=True + ) + else: + result = subprocess.run( + ["7z", "l", "-slt", self.archive_name], + capture_output=True, + text=True, + check=True + ) + + paths = [] + for line in result.stdout.splitlines(): + if line.startswith("Path = "): + paths.append(line[7:]) + + elif self.archive_name.endswith(".sd.tar.gz"): + with tarfile.open(self.archive_name, "r:*") as tar: + paths = [m.name for m in tar.getmembers()] + else: + cfg = Path(self.archive_name) + + paths = [ + str(f.relative_to(cfg)) + for f in cfg.rglob("*") + if f.is_file() + ] + + return paths + def _show_items_dialog(self): - self.items_dialog = itemsDialog(self) - self.items_dialog.choose(self, None, None, None) - self.items_dialog.connect("response", self._on_items_dialog_response) - self.items_dialog.present(self) + self.archive_items = self._get_archive_items() + self.items_dialog = itemsDialog(self, self.archive_items) + if not self.items_dialog.itemsBox.observe_children().get_n_items() == 0: + self.items_dialog.choose(self, None, None, None) + self.items_dialog.connect("response", self._on_items_dialog_response) + self.items_dialog.present(self) + else: + self._start_gui() def _on_items_dialog_response(self, dialog, response, *args): if response == "cancel": pass elif response == "ok": print("Importing the configuration is in progress…") - self.please_wait() - import_thread = Thread(target=self._call_archive_command) - import_thread.start() + self._start_gui() + + def _start_gui(self): + self.please_wait() + import_thread = Thread(target=self._call_archive_command) + import_thread.start() def _call_archive_command(self): self.archive_proc = subprocess.Popen(