diff --git a/src/host_info.py b/src/host_info.py
index 1db56d1..dbf1395 100644
--- a/src/host_info.py
+++ b/src/host_info.py
@@ -238,6 +238,7 @@ class HostInfo:
icon_theme.add_search_path(f"{i}/exports/share/icons")
flatpaks = []
+ id_to_flatpak = {}
ref_to_flatpak = {}
remotes = {}
installations = []
@@ -248,6 +249,7 @@ class HostInfo:
def get_flatpaks(this, callback=None):
# Callback is a function to run after the host flatpaks are found
this.flatpaks.clear()
+ this.id_to_flatpak.clear()
this.ref_to_flatpak.clear()
this.remotes.clear()
this.installations.clear()
@@ -336,6 +338,7 @@ class HostInfo:
for i in lines:
package = Flatpak(i.split("\t"))
this.flatpaks.append(package)
+ this.id_to_flatpak[package.info["id"]] = package
this.ref_to_flatpak[package.info["ref"]] = package
# Dependant Runtimes
diff --git a/src/main_window/window.py b/src/main_window/window.py
index 9825f1e..1197e6d 100644
--- a/src/main_window/window.py
+++ b/src/main_window/window.py
@@ -63,12 +63,14 @@ class WarehouseWindow(Adw.ApplicationWindow):
page.instance.start_loading()
def end_loading(self, *args):
- for _, page in self.pages.items():
- if page.instance:
- page.instance.end_loading()
+ for _, page in self.pages.items():
+ if page.instance:
+ page.instance.end_loading()
+ self.refresh_button.set_sensitive(True)
def refresh_handler(self, *args):
self.start_loading()
+ self.refresh_button.set_sensitive(False)
HostInfo.get_flatpaks(callback=self.end_loading)
def __init__(self, **kwargs):
diff --git a/src/meson.build b/src/meson.build
index e1a2b70..139d30d 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -12,8 +12,7 @@ blueprints = custom_target('blueprints',
'properties_page/properties_page.blp',
'user_data_page/data_box.blp',
'user_data_page/user_data_page.blp',
- 'user_data_page/active_data_page.blp',
- 'user_data_page/leftover_data_page.blp',
+ 'user_data_page/data_subpage.blp',
'change_version_page/change_version_page.blp',
),
output: '.',
@@ -66,8 +65,7 @@ warehouse_sources = [
'change_version_page/change_version_page.py',
'user_data_page/data_box.py',
'user_data_page/user_data_page.py',
- 'user_data_page/active_data_page.py',
- 'user_data_page/leftover_data_page.py',
+ 'user_data_page/data_subpage.py',
'../data/style.css',
]
diff --git a/src/user_data_page/active_data_page.blp b/src/user_data_page/active_data_page.blp
deleted file mode 100644
index 2040566..0000000
--- a/src/user_data_page/active_data_page.blp
+++ /dev/null
@@ -1,41 +0,0 @@
-using Gtk 4.0;
-using Adw 1;
-
-template $ActiveDataPage : ScrolledWindow {
- Box {
- orientation: vertical;
- Box {
- orientation: vertical;
- margin-start: 24;
- margin-end: 24;
- Label {
- label: _("Active User Data");
- styles ["title-1"]
- hexpand: true;
- halign: start;
- }
- Label {
- label: "32 Items - 39.7 GB";
- styles ["title-3"]
- hexpand: true;
- halign: start;
- }
- }
- Separator {
- margin-start: 12;
- margin-end: 12;
- margin-top: 9;
- margin-bottom: 6;
- }
- FlowBox flow_box {
- styles ["boxed-list"]
- homogeneous: true;
- valign: start;
- selection-mode: none;
- max-children-per-line: 6;
- margin-start: 12;
- margin-end: 12;
- margin-bottom: 12;
- }
- }
-}
\ No newline at end of file
diff --git a/src/user_data_page/active_data_page.py b/src/user_data_page/active_data_page.py
deleted file mode 100644
index 04ca401..0000000
--- a/src/user_data_page/active_data_page.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from gi.repository import Adw, Gtk, GLib, Gio, Pango
-from .host_info import HostInfo
-from .error_toast import ErrorToast
-from .data_box import DataBox
-import pathlib, os
-
-@Gtk.Template(resource_path="/io/github/flattool/Warehouse/user_data_page/active_data_page.ui")
-class ActiveDataPage(Gtk.ScrolledWindow):
- __gtype_name__ = 'ActiveDataPage'
- gtc = Gtk.Template.Child
-
- flow_box = gtc()
-
- def generate_list(self, *args):
- data = f"{HostInfo.home}/.var/app"
- for folder in os.listdir(data):
- print(folder)
-
- def __init__(self, main_window, data_page, **kwargs):
- super().__init__(**kwargs)
-
- self.generate_list()
-
- # self.select_button.connect("toggled", lambda *_: self.set_selection_mode(self.select_button.get_active()))
- # self.flow_box.connect("child-activated", lambda _, item: (cb := (row := item.get_child()).check_button).set_active((not cb.get_active()) if row.get_activatable() else False))
-
- # Extra Object Creation
-
- # Apply
-
- # Connections
\ No newline at end of file
diff --git a/src/user_data_page/data_box.blp b/src/user_data_page/data_box.blp
index 695d814..05ac3bf 100644
--- a/src/user_data_page/data_box.blp
+++ b/src/user_data_page/data_box.blp
@@ -13,7 +13,7 @@ template $DataBox : ListBox {
Box title_box {
margin-top: 12;
margin-bottom: 12;
- Image app_icon {
+ Image image {
margin-start: 12;
margin-end: 12;
icon-name: "application-x-executable-symbolic";
@@ -31,7 +31,7 @@ template $DataBox : ListBox {
}
Label subtitle_label {
label: "No subtitle set";
- hexpand: true;
+ // hexpand: true;
halign: start;
ellipsize: middle;
margin-end: 12;
@@ -43,6 +43,9 @@ template $DataBox : ListBox {
margin-start: 12;
margin-end: 6;
margin-bottom: 6;
+ Spinner spinner {
+ spinning: true;
+ }
Label size_label {
label: "No size set";
halign: start;
diff --git a/src/user_data_page/data_box.py b/src/user_data_page/data_box.py
index 6dac6f7..c73cb89 100644
--- a/src/user_data_page/data_box.py
+++ b/src/user_data_page/data_box.py
@@ -1,13 +1,32 @@
from gi.repository import Adw, Gtk, GLib, Gio, Pango
from .host_info import HostInfo
+import subprocess
@Gtk.Template(resource_path="/io/github/flattool/Warehouse/user_data_page/data_box.ui")
class DataBox(Gtk.ListBox):
__gtype_name__ = 'DataBox'
gtc = Gtk.Template.Child
+ image = gtc()
title_label = gtc()
+ subtitle_label = gtc()
+ size_label = gtc()
check_button = gtc()
- def __init__(self, main_window, path, **kwargs):
- super().__init__(**kwargs)
\ No newline at end of file
+ def idle_stuff(self):
+ self.title_label.set_label(self.title)
+ self.subtitle_label.set_label(self.subtitle)
+ if self.icon_path:
+ self.image.add_css_class("icon-dropshadow")
+ self.image.set_from_file(self.icon_path)
+
+ def __init__(self, title, subtitle, data_path, icon_path=None, callback=None, **kwargs):
+ super().__init__(**kwargs)
+
+ self.title = title
+ self.subtitle = subtitle
+ self.icon_path = icon_path
+ self.data_path = data_path
+ self.callback = callback
+
+ self.idle_stuff()
diff --git a/src/user_data_page/data_subpage.blp b/src/user_data_page/data_subpage.blp
new file mode 100644
index 0000000..01f1e40
--- /dev/null
+++ b/src/user_data_page/data_subpage.blp
@@ -0,0 +1,60 @@
+using Gtk 4.0;
+using Adw 1;
+
+template $DataSubpage : ScrolledWindow {
+ Box {
+ orientation: vertical;
+ Box {
+ orientation: vertical;
+ margin-start: 24;
+ margin-end: 24;
+ Label title {
+ label: _("No Title Set");
+ styles ["title-1"]
+ hexpand: true;
+ halign: start;
+ }
+ Box {
+ Label subtitle {
+ label: "No Subtutle Set";
+ styles ["title-3"]
+ }
+ Image {
+ icon-name: "dot-symbolic";
+ margin-start: 6;
+ margin-end: 6;
+ margin-top: 3;
+ valign: center;
+ }
+ Spinner spinner {
+ spinning: true;
+ valign: center;
+ margin-top: 3;
+ margin-end: 6;
+ }
+ Label size_label {
+ label: _("Loading Size…");
+ styles ["title-3"]
+ hexpand: true;
+ halign: start;
+ }
+ }
+ }
+ Separator {
+ margin-start: 12;
+ margin-end: 12;
+ margin-top: 9;
+ margin-bottom: 6;
+ }
+ FlowBox flow_box {
+ styles ["boxed-list"]
+ homogeneous: true;
+ valign: start;
+ selection-mode: none;
+ max-children-per-line: 6;
+ margin-start: 12;
+ margin-end: 12;
+ margin-bottom: 12;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/user_data_page/data_subpage.py b/src/user_data_page/data_subpage.py
new file mode 100644
index 0000000..be3c645
--- /dev/null
+++ b/src/user_data_page/data_subpage.py
@@ -0,0 +1,86 @@
+from gi.repository import Adw, Gtk, GLib, Gio, Pango
+from .host_info import HostInfo
+from .error_toast import ErrorToast
+from .data_box import DataBox
+from .host_info import HostInfo
+import subprocess
+
+@Gtk.Template(resource_path="/io/github/flattool/Warehouse/user_data_page/data_subpage.ui")
+class DataSubpage(Gtk.ScrolledWindow):
+ __gtype_name__ = 'DataSubpage'
+ gtc = Gtk.Template.Child
+
+ title = gtc()
+ subtitle = gtc()
+ spinner = gtc()
+ size_label = gtc()
+ flow_box = gtc()
+
+ def human_readable_size(self, size):
+ units = ['KB', 'MB', 'GB', 'TB']
+ # size *= 1024
+ for unit in units:
+ if size < 1024:
+ return f"~ {round(size)} {unit}"
+ size /= 1024
+ return f"~ {round(size)} PB"
+
+ def get_size(self, path):
+ sed = "sed 's/K/ KB/; s/M/ MB/; s/G/ GB/; s/T/ TB/; s/P/ PB/;'"
+ self.total_size += int(subprocess.run(['du', '-s', path], capture_output=True, text=True).stdout.split("\t")[0])
+
+ def show_size(self, data):
+ for folder in data:
+ self.get_size(f"{HostInfo.home}/.var/app/{folder}")
+
+ self.size_label.set_label(self.human_readable_size(self.total_size))
+ self.spinner.set_visible(False)
+
+ def generate_list(self, sort_mode, data=None, paks=None):
+ self.total_size = 0
+ Gio.Task().run_in_thread(lambda *_: self.show_size(data))
+ self.flow_box.remove_all()
+ total = len(data)
+ GLib.idle_add(lambda *_z: self.subtitle.set_label(_("{} Items").format(total)))
+ self.boxes.clear()
+
+ def thread(sort_mode, data, paks):
+ if paks:
+ for package in paks:
+ folder = package.info["id"]
+ box = DataBox(package.info["name"], folder, f"{HostInfo.home}/.var/app/{folder}", package.icon_path)
+ self.boxes.append(box)
+ else:
+ for folder in data:
+ box = DataBox(folder.split('.')[-1], folder, f"{HostInfo.home}/.var/app/{folder}")
+ self.boxes.append(box)
+
+ def callback(sort_mode):
+ if sort_mode == "name":
+ self.boxes = sorted(self.boxes, key=lambda box: box.title)
+ elif sort_mode == "id":
+ self.boxes = sorted(self.boxes, key=lambda box: box.subtitle)
+ else:
+ pass
+
+ for box in self.boxes:
+ self.flow_box.append(box)
+
+ Gio.Task.new(None, None, lambda *_: callback(sort_mode)).run_in_thread(lambda *_: thread(sort_mode, data, paks))
+
+ def __init__(self, title, main_window, **kwargs):
+ super().__init__(**kwargs)
+
+ GLib.idle_add(lambda *_: self.title.set_label(title))
+
+ # self.select_button.connect("toggled", lambda *_: self.set_selection_mode(self.select_button.get_active()))
+ # self.flow_box.connect("child-activated", lambda _, item: (cb := (row := item.get_child()).check_button).set_active((not cb.get_active()) if row.get_activatable() else False))
+
+ # Extra Object Creation
+ self.main_window = main_window
+ self.total_size = 0
+ self.boxes = []
+
+ # Apply
+
+ # Connections
\ No newline at end of file
diff --git a/src/user_data_page/leftover_data_page.blp b/src/user_data_page/leftover_data_page.blp
deleted file mode 100644
index 2e6aa44..0000000
--- a/src/user_data_page/leftover_data_page.blp
+++ /dev/null
@@ -1,41 +0,0 @@
-using Gtk 4.0;
-using Adw 1;
-
-template $LeftoverDataPage : ScrolledWindow {
- Box {
- orientation: vertical;
- Box {
- orientation: vertical;
- margin-start: 24;
- margin-end: 24;
- Label {
- label: _("Leftover User Data");
- styles ["title-1"]
- hexpand: true;
- halign: start;
- }
- Label {
- label: "25 Items - 18.6 GB";
- styles ["title-3"]
- hexpand: true;
- halign: start;
- }
- }
- Separator {
- margin-start: 12;
- margin-end: 12;
- margin-top: 9;
- margin-bottom: 6;
- }
- FlowBox {
- styles ["boxed-list"]
- homogeneous: true;
- valign: start;
- selection-mode: none;
- max-children-per-line: 6;
- margin-start: 12;
- margin-end: 12;
- margin-bottom: 12;
- }
- }
-}
\ No newline at end of file
diff --git a/src/user_data_page/leftover_data_page.py b/src/user_data_page/leftover_data_page.py
deleted file mode 100644
index 84d0c0c..0000000
--- a/src/user_data_page/leftover_data_page.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from gi.repository import Adw, Gtk, GLib, Gio, Pango
-from .host_info import HostInfo
-from .error_toast import ErrorToast
-from .data_box import DataBox
-
-@Gtk.Template(resource_path="/io/github/flattool/Warehouse/user_data_page/leftover_data_page.ui")
-class LeftoverDataPage(Gtk.ScrolledWindow):
- __gtype_name__ = 'LeftoverDataPage'
- gtc = Gtk.Template.Child
-
- def __init__(self, main_window, data_page, **kwargs):
- super().__init__(**kwargs)
-
- # Extra Object Creation
-
- # Apply
-
- # Connections
\ No newline at end of file
diff --git a/src/user_data_page/user_data_page.py b/src/user_data_page/user_data_page.py
index 4424db5..aa0fdd4 100644
--- a/src/user_data_page/user_data_page.py
+++ b/src/user_data_page/user_data_page.py
@@ -1,7 +1,9 @@
from gi.repository import Adw, Gtk, GLib, Gio, Pango
from .error_toast import ErrorToast
-from .active_data_page import ActiveDataPage
-from .leftover_data_page import LeftoverDataPage
+from .data_box import DataBox
+from .data_subpage import DataSubpage
+from .host_info import HostInfo
+import os
@Gtk.Template(resource_path="/io/github/flattool/Warehouse/user_data_page/user_data_page.ui")
class UserDataPage(Adw.BreakpointBin):
@@ -47,11 +49,33 @@ class UserDataPage(Adw.BreakpointBin):
# elif self.switcher_bar.get_reveal():
# self.header_bar.set_show_title(False)
+ def sort_data(self, *args):
+ self.data_flatpaks.clear()
+ self.active_data.clear()
+ self.leftover_data.clear()
+ # paks = dict(HostInfo.id_to_flatpak)
+
+ for folder in os.listdir(f"{HostInfo.home}/.var/app"):
+ try:
+ self.data_flatpaks.append(HostInfo.id_to_flatpak[folder])
+ self.active_data.append(folder)
+ except KeyError:
+ self.leftover_data.append(folder)
+
def start_loading(self, *args):
+ self.adp.size_label.set_label("Loading Size…")
+ self.adp.spinner.set_visible(True)
+ self.ldp.size_label.set_label("Loading Size…")
+ self.ldp.spinner.set_visible(True)
pass
def end_loading(self, *args):
- pass
+ self.sort_mode = "id"
+ def callback(*args):
+ self.adp.generate_list(self.sort_mode, data=self.active_data, paks=self.data_flatpaks)
+ self.ldp.generate_list(self.sort_mode, data=self.leftover_data)
+
+ Gio.Task.new(None, None, callback).run_in_thread(self.sort_data)
def __init__(self, main_window, **kwargs):
super().__init__(**kwargs)
@@ -59,16 +83,22 @@ class UserDataPage(Adw.BreakpointBin):
# Extra Object Creation
self.__class__.instance = self
# self.adj = self.scrolled_window.get_vadjustment()
+ self.adp = DataSubpage(_("Active Data"), main_window)
+ self.ldp = DataSubpage(_("Leftover Data"), main_window)
+ self.data_flatpaks = []
+ self.active_data = []
+ self.leftover_data = []
+ self.total_items = 0
# Apply
self.stack.add_titled_with_icon(
- child=ActiveDataPage(main_window, self),
+ child=self.adp,
name="active",
title=_("Active Data"),
icon_name="file-manager-symbolic",
)
self.stack.add_titled_with_icon(
- child=LeftoverDataPage(main_window, self),
+ child=self.ldp,
name="leftover",
title=_("Leftover Data"),
icon_name="folder-templates-symbolic",
diff --git a/src/warehouse.gresource.xml b/src/warehouse.gresource.xml
index 5403771..775fd45 100644
--- a/src/warehouse.gresource.xml
+++ b/src/warehouse.gresource.xml
@@ -11,8 +11,7 @@
change_version_page/change_version_page.ui
user_data_page/data_box.ui
user_data_page/user_data_page.ui
- user_data_page/active_data_page.ui
- user_data_page/leftover_data_page.ui
+ user_data_page/data_subpage.ui