Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions data/io.github.vikdevelop.SaveDesktop.metainfo.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<li>Redesigned Flatpak apps selection: shows app names (not IDs) and backs up selected apps together with their user data</li>
<li>New: Sync selected configuration items across PCs to keep archives consistent</li>
<li>Updated archive structure with full backward compatibility for older backups</li>
<li>During import, only what is actually in the archive will be displayed in the item selection dialog</li>
<li>Updated translations</li>
</ul>
</description>
Expand Down
4 changes: 2 additions & 2 deletions io.github.vikdevelop.SaveDesktop.json
Original file line number Diff line number Diff line change
Expand Up @@ -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" : {
Expand Down
4 changes: 2 additions & 2 deletions src/core/de_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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():
Expand All @@ -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}")

Expand Down
53 changes: 34 additions & 19 deletions src/gui/items_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."))
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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"]:
Expand All @@ -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()
Expand All @@ -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")
Expand All @@ -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"<a href='https://vikdevelop.github.io/SaveDesktop/wiki/flatpak_apps/{language}'>{_('Learn more')}</a>")
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand All @@ -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)

Expand All @@ -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):
Expand All @@ -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
67 changes: 59 additions & 8 deletions src/gui/window.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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(
Expand Down