mirror of
https://github.com/morgan9e/warehouse
synced 2026-04-15 00:34:42 +09:00
Further work on snapshots
This commit is contained in:
@@ -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',
|
||||
]
|
||||
|
||||
|
||||
69
src/snapshot_page/snapshot_box.blp
Normal file
69
src/snapshot_page/snapshot_box.blp
Normal 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"]
|
||||
}
|
||||
}
|
||||
}
|
||||
13
src/snapshot_page/snapshot_box.py
Normal file
13
src/snapshot_page/snapshot_box.py
Normal 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)
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 = []
|
||||
@@ -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/">
|
||||
|
||||
Reference in New Issue
Block a user