Add batch copy

This commit is contained in:
Heliguy
2024-09-28 17:02:34 -04:00
parent 01c2f4616f
commit f475390b28
2 changed files with 157 additions and 19 deletions

View File

@@ -129,6 +129,44 @@ template $SnapshotPage : Adw.BreakpointBin {
}
}
}
[bottom]
Revealer {
reveal-child: bind select_button.active;
transition-type: slide_up;
[center]
Box bottom_bar {
styles ["toolbar"]
hexpand: true;
homogeneous: true;
Button select_all_button {
styles ["raised"]
Adw.ButtonContent {
icon-name: "selection-mode-symbolic";
label: _("Select All");
can-shrink: true;
}
}
Button copy_button {
sensitive: false;
styles ["raised"]
Adw.ButtonContent {
icon-name: "edit-copy-symbolic";
label: _("Copy");
can-shrink: true;
}
}
MenuButton more_button {
sensitive: false;
popover: more_popover;
styles ["raised"]
Adw.ButtonContent {
icon-name: "view-more-symbolic";
label: _("More");
can-shrink: true;
}
}
}
}
}
}
;
@@ -178,3 +216,21 @@ template $SnapshotPage : Adw.BreakpointBin {
}
}
}
Popover more_popover {
styles ["menu"]
ListBox more_menu {
Label new_snapshots {
label: _("New Snapshots");
halign: start;
}
Label apply_snapshots {
label: _("Apply Snapshots");
halign: start;
}
Label trash_snapshots {
label: _("Trash Snapshots");
halign: start;
}
}
}

View File

@@ -32,10 +32,12 @@ class LeftoverSnapshotRow(Adw.ActionRow):
class SnapshotPage(Adw.BreakpointBin):
__gtype_name__ = "SnapshotPage"
gtc = Gtk.Template.Child
toast_overlay = gtc()
sidebar_navpage = gtc()
search_entry = gtc()
search_bar = gtc()
select_button = gtc()
active_box = gtc()
active_listbox = gtc()
leftover_box = gtc()
@@ -52,55 +54,63 @@ class SnapshotPage(Adw.BreakpointBin):
status_stack = gtc()
loading_view = gtc()
snapshotting_view = gtc()
select_all_button = gtc()
copy_button = gtc()
more_button = gtc()
more_menu = gtc()
new_snapshots = gtc()
apply_snapshots = gtc()
trash_snapshots = gtc()
# Referred to in the main window
# It is used to determine if a new page should be made or not
# This must be set to the created object from within the class's __init__ method
instance = None
page_name = "snapshots"
def sort_snapshots(self, *args):
self.active_snapshot_paks.clear()
self.leftover_snapshots.clear()
bad_folders = []
if not os.path.exists(HostInfo.snapshots_path):
try:
os.makedirs(HostInfo.snapshots_path)
except Exception as e:
self.toast_overlay.add_toast(ErrorToast(_("Could not load Snapshots"), str(e)).toast)
return
for folder in os.listdir(HostInfo.snapshots_path):
if folder.count('.') < 2 or ' ' in folder:
bad_folders.append(folder)
continue
has_tar = False
for file in os.listdir(f"{HostInfo.snapshots_path}{folder}"):
if file.endswith(".tar.zst"):
has_tar = True
break
if not has_tar:
bad_folders.append(folder)
continue
try:
pak = HostInfo.id_to_flatpak[folder]
self.active_snapshot_paks.append(pak)
except KeyError:
self.leftover_snapshots.append(folder)
for folder in bad_folders:
try:
subprocess.run(['gio', 'trash', f'{HostInfo.snapshots_path}{folder}'])
except Exception:
pass
def generate_active_list(self):
for pak in self.active_snapshot_paks:
row = AppRow(pak)
row.check_button.connect("toggled", lambda *_, _row=row: self.row_select_handler(_row))
self.active_listbox.append(row)
if len(self.active_snapshot_paks) > 0:
@@ -109,12 +119,13 @@ class SnapshotPage(Adw.BreakpointBin):
# self.active_listbox.select_row(first_row)
else:
self.active_box.set_visible(False)
def generate_leftover_list(self):
for folder in self.leftover_snapshots:
row = LeftoverSnapshotRow(folder)
row.check_button.connect("toggled", lambda *_, _row=row: self.row_select_handler(_row))
self.leftover_listbox.append(row)
if len(self.leftover_snapshots) > 0:
self.leftover_box.set_visible(True)
if len(self.active_snapshot_paks) == 0:
@@ -123,17 +134,17 @@ class SnapshotPage(Adw.BreakpointBin):
# self.leftover_listbox.select_row(first_row)
else:
self.leftover_box.set_visible(False)
def active_select_handler(self, listbox, row, should_show_content=True, refresh=False):
self.leftover_listbox.select_row(None)
self.list_page.set_snapshots(row.package, refresh)
self.split_view.set_show_content(should_show_content)
def leftover_select_handler(self, listbox, row, should_show_content=True, refresh=False):
self.active_listbox.select_row(None)
self.list_page.set_snapshots(row.folder, refresh)
self.split_view.set_show_content(should_show_content)
def select_first_row(self):
if row := self.active_listbox.get_row_at_index(0):
self.active_listbox.select_row(row)
@@ -156,14 +167,14 @@ class SnapshotPage(Adw.BreakpointBin):
toast = Adw.Toast(title=_("No snapshots for {}").format(package.info['name']), button_label=_("New"))
toast.connect("button-clicked", lambda *_: dialog.present(HostInfo.main_window))
self.toast_overlay.add_toast(toast)
def start_loading(self):
self.status_stack.set_visible_child(self.loading_view)
self.active_box.set_visible(True)
self.active_listbox.remove_all()
self.leftover_box.set_visible(True)
self.leftover_listbox.remove_all()
def end_loading(self):
def callback(*args):
self.new_snapshot_dialog = NewSnapshotDialog(self, self.snapshotting_status, self.refresh)
@@ -176,8 +187,10 @@ class SnapshotPage(Adw.BreakpointBin):
GLib.idle_add(lambda *_: self.stack.set_visible_child(self.scrolled_window))
GLib.idle_add(lambda *_: self.status_stack.set_visible_child(self.split_view))
self.selected_active_rows.clear()
self.selected_leftover_rows.clear()
Gio.Task.new(None, None, callback).run_in_thread(self.sort_snapshots)
def open_snapshots_folder(self, button):
try:
Gio.AppInfo.launch_default_for_uri(f"file://{HostInfo.snapshots_path}", None)
@@ -188,7 +201,7 @@ class SnapshotPage(Adw.BreakpointBin):
def on_cancel(self):
for worker in self.new_snapshot_dialog.workers:
worker.do_cancel("manual_cancel")
def on_new(self, *args):
self.new_snapshot_dialog.present(HostInfo.main_window)
@@ -228,6 +241,70 @@ class SnapshotPage(Adw.BreakpointBin):
return row1.package.info['name'].lower() > row2.package.info['name'].lower()
else:
return row1.name.lower() > row2.name.lower()
def set_selection_mode(self, *args):
enable = self.select_button.get_active()
i = 0
while row := self.active_listbox.get_row_at_index(i):
i += 1
row.check_button.set_visible(enable)
if not enable:
row.check_button.set_active(False)
i = 0
while row := self.leftover_listbox.get_row_at_index(i):
i += 1
row.check_button.set_visible(enable)
if not enable:
row.check_button.set_active(False)
def select_all_handler(self, *args):
i = 0
while row := self.active_listbox.get_row_at_index(i):
i += 1
row.check_button.set_active(True)
i = 0
while row := self.leftover_listbox.get_row_at_index(i):
i += 1
row.check_button.set_active(True)
def row_select_handler(self, row):
if type(row) is AppRow:
if row.check_button.get_active():
self.selected_active_rows.append(row)
elif row in self.selected_active_rows:
self.selected_active_rows.remove(row)
elif type(row) is LeftoverSnapshotRow:
if row.check_button.get_active():
self.selected_leftover_rows.append(row)
elif row in self.selected_leftover_rows:
self.selected_leftover_rows.remove(row)
total_active = len(self.selected_active_rows)
total_leftover = len(self.selected_leftover_rows)
total = total_active + total_leftover
self.sidebar_navpage.set_title(_("{} Selected").format(total_active + total_leftover) if total > 0 else _("Snapshots"))
self.copy_button.set_sensitive(total > 0)
self.more_button.set_sensitive(total > 0)
def select_copy_handler(self, *args):
to_copy = ""
i = 0
while row := self.active_listbox.get_row_at_index(i):
i += 1
if row.check_button.get_active():
to_copy += f"{HostInfo.snapshots_path}{row.package.info['id']}\n"
i = 0
while row := self.leftover_listbox.get_row_at_index(i):
i += 1
if row.check_button.get_active():
to_copy += f"{HostInfo.snapshots_path}{row.folder}\n"
to_copy = to_copy[0:-1]
HostInfo.clipboard.set(to_copy)
self.toast_overlay.add_toast(Adw.Toast(title=_("Copied Snapshot Paths")))
def __init__(self, main_window, **kwargs):
super().__init__(**kwargs)
@@ -236,6 +313,8 @@ class SnapshotPage(Adw.BreakpointBin):
self.__class__.instance = self
self.main_window = main_window
self.active_snapshot_paks = []
self.selected_active_rows = []
self.selected_leftover_rows = []
# self.active_rows = []
self.leftover_snapshots = []
# self.leftover_rows = []
@@ -250,6 +329,9 @@ class SnapshotPage(Adw.BreakpointBin):
self.status_new_button.connect("clicked", self.on_new)
self.new_button.connect("clicked", self.on_new)
self.search_entry.connect("search-changed", self.on_search)
self.select_button.connect("toggled", self.set_selection_mode)
self.select_all_button.connect("clicked", self.select_all_handler)
self.copy_button.connect("clicked", self.select_copy_handler)
# Apply
self.search_bar.set_key_capture_widget(HostInfo.main_window)