Further work on snapshots

This commit is contained in:
heliguy
2024-07-30 19:24:07 -04:00
parent 8449b08a62
commit 5ca4d71f95
8 changed files with 316 additions and 48 deletions

View File

@@ -19,6 +19,7 @@ blueprints = custom_target('blueprints',
'change_version_page/change_version_page.blp',
'snapshot_page/snapshot_page.blp',
'snapshot_page/snapshots_list_page.blp',
'snapshot_page/snapshot_box.blp',
),
output: '.',
command: [find_program('blueprint-compiler'), 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@'],
@@ -76,6 +77,7 @@ warehouse_sources = [
'remotes_page/add_remote_dialog.py',
'snapshot_page/snapshot_page.py',
'snapshot_page/snapshots_list_page.py',
'snapshot_page/snapshot_box.py',
'../data/style.css',
]

View File

@@ -0,0 +1,69 @@
using Gtk 4.0;
using Adw 1;
template $SnapshotBox : Gtk.Box {
orientation: vertical;
spacing: 6;
Box {
margin-start: 12;
margin-end: 12;
margin-top: 6;
spacing: 12;
Box {
orientation: vertical;
Label title {
label: "A Snapshot";
wrap: true;
justify: left;
halign: start;
styles ["title-4"]
}
Label date {
label: "2024-04-03 4:30 PM";
wrap: true;
justify: left;
halign: start;
}
}
Label version {
label: "Version: 45.3";
wrap: true;
justify: right;
hexpand: true;
}
}
Box {
margin-start: 6;
margin-end: 6;
margin-bottom: 6;
spacing: 3;
homogeneous: true;
Button {
Adw.ButtonContent {
label: "Apply";
icon-name: "check-plain-symbolic";
can-shrink: true;
}
hexpand: true;
styles ["flat"]
}
Button {
Adw.ButtonContent {
label: "Rename";
icon-name: "dot-symbolic";
can-shrink: true;
}
hexpand: true;
styles ["flat"]
}
Button {
Adw.ButtonContent {
label: "Trash";
icon-name: "user-trash-symbolic";
can-shrink: true;
}
hexpand: true;
styles ["flat"]
}
}
}

View File

@@ -0,0 +1,13 @@
from gi.repository import Adw, Gtk, GLib, Gio
from .host_info import HostInfo
from .error_toast import ErrorToast
import os
@Gtk.Template(resource_path="/io/github/flattool/Warehouse/snapshot_page/snapshot_box.ui")
class SnapshotBox(Gtk.Box):
__gtype_name__ = "SnapshotBox"
def __init__(self, folder, **kwargs):
super().__init__(**kwargs)
print(folder)

View File

@@ -58,55 +58,64 @@ template $SnapshotPage : Adw.BreakpointBin {
ScrolledWindow scrolled_window {
Box {
orientation: vertical;
margin-start: 12;
margin-end: 12;
Label {
label: _("Active Snapshots");
halign: start;
styles ["heading"]
margin-top: 3;
margin-bottom: 6;
Box active_box {
orientation: vertical;
Label {
label: _("Active Snapshots");
halign: start;
styles ["heading"]
margin-top: 3;
margin-bottom: 6;
margin-start: 12;
margin-end: 12;
wrap: true;
}
Label {
label: _("Snapshots of installed apps");
halign: start;
styles ["dim-label"]
margin-start: 12;
margin-end: 12;
wrap: true;
}
ListBox active_listbox {
styles ["navigation-sidebar"]
valign: start;
}
}
Label {
label: _("Snapshots of installed apps");
halign: start;
styles ["dim-label"]
}
ListBox active_listbox {
styles ["navigation-sidebar"]
valign: start;
}
Label {
label: _("Leftover Snapshots");
halign: start;
styles ["heading"]
margin-top: 3;
margin-bottom: 6;
}
Label {
label: _("Snapshots of apps that are no longer installed");
halign: start;
styles ["dim-label"]
}
ListBox leftover_listbox {
styles ["navigation-sidebar"]
valign: start;
Box leftover_box {
orientation: vertical;
Label {
label: _("Leftover Snapshots");
halign: start;
styles ["heading"]
margin-top: 3;
margin-bottom: 6;
margin-start: 12;
margin-end: 12;
wrap: true;
}
Label {
label: _("Snapshots of apps that are no longer installed");
halign: start;
styles ["dim-label"]
margin-start: 12;
margin-end: 12;
wrap: true;
}
ListBox leftover_listbox {
styles ["navigation-sidebar"]
valign: start;
}
}
}
}
}
}
;
content:
Adw.NavigationPage content_navpage {
title: _("Content 8===D~");
Adw.ToolbarView {
[top]
Adw.HeaderBar {
}
}
}
;
}
}
}

View File

@@ -1,6 +1,28 @@
from gi.repository import Adw, Gtk, GLib, Gio
from .host_info import HostInfo
from .error_toast import ErrorToast
from .app_row import AppRow
from .snapshots_list_page import SnapshotsListPage
import os, subprocess
class LeftoverSnapshotRow(Adw.ActionRow):
__gtype_name__ = "LeftoverSnapshotRow"
def idle_stuff(self):
self.set_title(self.folder.split('.')[-1])
icon = Gtk.Image.new_from_icon_name("application-x-executable-symbolic")
icon.set_icon_size(Gtk.IconSize.LARGE)
self.add_prefix(icon)
self.add_suffix(self.check_button)
def __init__(self, folder, **kwargs):
super().__init__(**kwargs)
self.set_activatable(True)
self.folder = folder
self.check_button = Gtk.CheckButton(visible=False)
self.check_button.add_css_class("selection-mode")
GLib.idle_add(lambda *_: self.idle_stuff())
@Gtk.Template(resource_path="/io/github/flattool/Warehouse/snapshot_page/snapshot_page.ui")
class SnapshotPage(Adw.BreakpointBin):
@@ -8,17 +30,98 @@ class SnapshotPage(Adw.BreakpointBin):
gtc = Gtk.Template.Child
sidebar_button = gtc()
active_box = gtc()
active_listbox = gtc()
leftover_box = gtc()
leftover_listbox = gtc()
split_view = 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
snapshots_path = f"{HostInfo.home}/.var/app/io.github.flattool.Warehouse/data/Snapshots/"
def sort_snapshots(self, *args):
self.active_snapshot_paks.clear()
self.leftover_snapshots.clear()
bad_folders = []
for folder in os.listdir(self.snapshots_path):
if folder.count('.') < 2 or ' ' in folder:
bad_folders.append(folder)
continue
has_tar = False
for file in os.listdir(f"{self.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'{self.snapshots_path}{folder}'])
except Exception:
pass
def generate_active_list(self):
for pak in self.active_snapshot_paks:
row = AppRow(pak)
self.active_listbox.append(row)
if len(self.active_snapshot_paks) > 0:
self.active_box.set_visible(True)
first_row = self.active_listbox.get_row_at_index(0)
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)
self.leftover_listbox.append(row)
if len(self.leftover_snapshots) > 0:
self.leftover_box.set_visible(True)
if len(self.active_snapshot_paks) == 0:
first_row = self.leftover_box.get_row_at_index(0)
self.leftover_box.select_row(first_row)
else:
self.leftover_box.set_visible(False)
def active_select_handler(self, listbox, row):
self.leftover_listbox.select_row(None)
self.list_page.set_snapshots(row.package.info["id"], row.get_title())
def leftover_select_handler(self, listbox, row):
self.active_listbox.select_row(None)
self.list_page.set_snapshots(row.folder, row.get_title())
def start_loading(self):
self.snapshot_rows.clear()
# self.list_page.start_loading()
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):
pass
def callback(*args):
self.generate_active_list()
self.generate_leftover_list()
# self.list_page.end_loading()
Gio.Task.new(None, None, callback).run_in_thread(self.sort_snapshots)
def __init__(self, main_window, **kwargs):
super().__init__(**kwargs)
@@ -27,11 +130,18 @@ class SnapshotPage(Adw.BreakpointBin):
ms = main_window.main_split
self.__class__.instance = self
self.main_window = main_window
self.snapshot_rows = []
self.active_snapshot_paks = []
# self.active_rows = []
self.leftover_snapshots = []
# self.leftover_rows = []
self.list_page = SnapshotsListPage(self)
# Connections
ms.connect("notify::show-sidebar", lambda *_: self.sidebar_button.set_active(ms.get_show_sidebar()))
self.sidebar_button.connect("toggled", lambda *_: ms.set_show_sidebar(self.sidebar_button.get_active()))
self.active_listbox.connect("row-activated", self.active_select_handler)
self.leftover_listbox.connect("row-activated", self.leftover_select_handler)
# Apply
self.sidebar_button.set_active(ms.get_show_sidebar())
self.sidebar_button.set_active(ms.get_show_sidebar())
self.split_view.set_content(self.list_page)

View File

@@ -2,5 +2,38 @@ using Gtk 4.0;
using Adw 1;
template $SnapshotsListPage : Adw.NavigationPage {
title: _("Snapshots");
title: _("Snapshots List");
Adw.ToastOverlay {
Adw.ToolbarView {
[top]
Adw.HeaderBar {
}
ScrolledWindow {
Adw.Clamp {
margin-start: 12;
margin-end: 12;
margin-top: 12;
margin-bottom: 12;
ListBox listbox {
valign: start;
selection-mode: none;
styles ["boxed-list"]
}
}
}
[bottom]
ActionBar {
[center]
Button new_button {
margin-top: 3;
margin-bottom: 3;
styles ["pill", "suggested-action"]
Adw.ButtonContent {
icon-name: "plus-large-symbolic";
label: _("New Snapshot");
}
}
}
}
}
}

View File

@@ -1,8 +1,39 @@
from gi.repository import Adw, Gtk, GLib, Gio
from .host_info import HostInfo
from .error_toast import ErrorToast
from .snapshot_box import SnapshotBox
import os
@Gtk.Template(resource_path="/io/github/flattool/Warehouse/snapshot_page/snapshots_list_page.ui")
class SnapshotsListPage(Adw.NavigationPage):
__gtype_name__ = "SnapshotsListPage"
gtc = Gtk.Template.Child
gtc = Gtk.Template.Child
listbox = gtc()
snapshots_path = f"{HostInfo.home}/.var/app/io.github.flattool.Warehouse/data/Snapshots/"
def thread(self, *args):
for snapshot in os.listdir(f"{self.snapshots_path}{self.current_folder}"):
row = SnapshotBox(snapshot)
self.snapshots_rows.append(row)
def callback(self, *args):
for i, row in enumerate(self.snapshots_rows):
self.listbox.append(row)
self.listbox.get_row_at_index(i).set_activatable(False)
def set_snapshots(self, folder, title):
self.current_folder = folder
self.set_title(_("{} Snapshots").format(title))
self.snapshots_rows.clear()
self.listbox.remove_all()
Gio.Task.new(None, None, self.callback).run_in_thread(self.thread)
def __init__(self, parent_page, **kwargs):
super().__init__(**kwargs)
self.current_folder = None
self.snapshots_rows = []

View File

@@ -17,6 +17,7 @@
<file preprocess="xml-stripblanks">remotes_page/add_remote_dialog.ui</file>
<file preprocess="xml-stripblanks">snapshot_page/snapshot_page.ui</file>
<file preprocess="xml-stripblanks">snapshot_page/snapshots_list_page.ui</file>
<file preprocess="xml-stripblanks">snapshot_page/snapshot_box.ui</file>
<!-- <file preprocess="xml-stripblanks">../data/io.github.flattool.Warehouse.metainfo.xml.in</file> -->
</gresource>
<gresource prefix="/io/github/flattool/Warehouse/icons/scalable/actions/">