mirror of
https://github.com/morgan9e/warehouse
synced 2026-04-14 00:04:08 +09:00
Populate properties panel with correct data
This commit is contained in:
@@ -8,7 +8,6 @@ icon_theme.add_search_path(f"{home}/.local/share/flatpak/exports/share/icons")
|
||||
direction = Gtk.Image().get_direction()
|
||||
|
||||
class Flatpak:
|
||||
cli_info = None
|
||||
|
||||
def open_data(self):
|
||||
if not os.path.exists(self.data_path):
|
||||
@@ -18,24 +17,52 @@ class Flatpak:
|
||||
except GLib.GError as e:
|
||||
return e
|
||||
|
||||
def get_data_size(self, callback=None):
|
||||
size = [None]
|
||||
def thread(*args):
|
||||
sed = "sed 's/K/ KB/; s/M/ MB/; s/G/ GB/; s/T/ TB/; s/P/ PB/;'"
|
||||
size[0] = subprocess.run(['sh', '-c', f"du -sh {self.data_path} | {sed}"], capture_output=True, text=True).stdout.split("\t")[0]
|
||||
def on_done(*arg):
|
||||
if callback:
|
||||
callback(f"~ {size[0]}")
|
||||
Gio.Task.new(None, None, on_done).run_in_thread(thread)
|
||||
|
||||
def trash_data(self, callback=None):
|
||||
def thread(*args):
|
||||
subprocess.run(['gio', 'trash', f"{self.data_path}"])
|
||||
Gio.Task.new(None, None, lambda *_: callback()).run_in_thread(thread)
|
||||
|
||||
def get_cli_info(self):
|
||||
if not self.cli_info:
|
||||
cmd = "LC_ALL=C flatpak info "
|
||||
installation = self.info["installation"]
|
||||
cli_info = {}
|
||||
cmd = "LC_ALL=C flatpak info "
|
||||
installation = self.info["installation"]
|
||||
|
||||
if installation == "user":
|
||||
cmd += "--user "
|
||||
elif installation == "system":
|
||||
cmd += "--system "
|
||||
else:
|
||||
cmd += f"--installation={installation} "
|
||||
if installation == "user":
|
||||
cmd += "--user "
|
||||
elif installation == "system":
|
||||
cmd += "--system "
|
||||
else:
|
||||
cmd += f"--installation={installation} "
|
||||
|
||||
cmd += self.info["ref"]
|
||||
cmd += self.info["ref"]
|
||||
|
||||
output = subprocess.run(['flatpak-spawn', '--host', 'sh', '-c', cmd], text=True, capture_output=True)
|
||||
print(output)
|
||||
try:
|
||||
output = subprocess.run(['flatpak-spawn', '--host', 'sh', '-c', cmd], text=True, capture_output=True).stdout
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
return self.cli_info
|
||||
lines = output.strip().split("\n")
|
||||
for i, word in enumerate(lines):
|
||||
word = word.strip().split(": ", 1)
|
||||
if len(word) < 2:
|
||||
continue
|
||||
|
||||
word[0] = word[0].lower()
|
||||
if "installed" in word[0]:
|
||||
word[1] = word[1].replace("?", " ")
|
||||
cli_info[word[0]] = word[1]
|
||||
|
||||
return cli_info
|
||||
|
||||
def __init__(self, columns):
|
||||
self.is_runtime = "runtime" in columns[12]
|
||||
@@ -52,6 +79,7 @@ class Flatpak:
|
||||
"options": columns[12],
|
||||
}
|
||||
self.data_path = f"{home}/.var/app/{columns[2]}"
|
||||
self.data_size = -1
|
||||
installation = columns[7]
|
||||
if len(i := installation.split(' ')) > 1:
|
||||
self.info["installation"] = i[1].replace("(", "").replace(")", "")
|
||||
|
||||
@@ -6,7 +6,8 @@ template $PropertiesPage : Adw.NavigationPage {
|
||||
Adw.ToastOverlay toast_overlay {
|
||||
Adw.ToolbarView {
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
Adw.HeaderBar header_bar {
|
||||
show-title: false;
|
||||
[end]
|
||||
MenuButton more_menu {
|
||||
icon-name: "view-more-symbolic";
|
||||
@@ -34,7 +35,7 @@ template $PropertiesPage : Adw.NavigationPage {
|
||||
;
|
||||
}
|
||||
}
|
||||
ScrolledWindow {
|
||||
ScrolledWindow scrolled_window {
|
||||
Adw.Clamp {
|
||||
Box {
|
||||
margin-start: 12;
|
||||
@@ -46,6 +47,7 @@ template $PropertiesPage : Adw.NavigationPage {
|
||||
|
||||
Image app_icon {
|
||||
pixel-size: 100;
|
||||
margin-top: 6;
|
||||
margin-bottom: 18;
|
||||
icon-name: "application-x-executable-symbolic";
|
||||
styles["icon-dropshadow"]
|
||||
@@ -68,7 +70,6 @@ template $PropertiesPage : Adw.NavigationPage {
|
||||
wrap: true;
|
||||
wrap-mode: word_char;
|
||||
justify: center;
|
||||
margin-bottom: 18;
|
||||
margin-start: 6;
|
||||
margin-end: 6;
|
||||
}
|
||||
@@ -76,6 +77,7 @@ template $PropertiesPage : Adw.NavigationPage {
|
||||
Box {
|
||||
spacing: 6;
|
||||
homogeneous: true;
|
||||
margin-top: 18;
|
||||
margin-bottom: 12;
|
||||
halign: center;
|
||||
Button open_app_button {
|
||||
@@ -95,8 +97,8 @@ template $PropertiesPage : Adw.NavigationPage {
|
||||
Adw.PreferencesGroup actions {
|
||||
margin-bottom: 12;
|
||||
Adw.SwitchRow pin_row {
|
||||
title: _("Remove When Unused");
|
||||
subtitle: _("Pin this runtime so it's never auto removed");
|
||||
title: _("Disable Automactic Removal");
|
||||
subtitle: _("Pin this runtime to keep it installed");
|
||||
}
|
||||
Adw.ActionRow data_row {
|
||||
title: _("User Data");
|
||||
@@ -117,16 +119,27 @@ template $PropertiesPage : Adw.NavigationPage {
|
||||
icon-name: "user-trash-symbolic";
|
||||
tooltip-text: _("Trash User Data");
|
||||
}
|
||||
|
||||
[suffix]
|
||||
Spinner data_spinner {
|
||||
spinning: true;
|
||||
}
|
||||
}
|
||||
Adw.ExpanderRow version_row {
|
||||
title: _("Version");
|
||||
styles ["property"]
|
||||
[suffix]
|
||||
Label mask_label {
|
||||
label: _("Updates disabled");
|
||||
styles["warning"]
|
||||
}
|
||||
Adw.SwitchRow mask_row {
|
||||
title: _("Disable Updates");
|
||||
subtitle: _("Mask this package so it's never updated");
|
||||
}
|
||||
Adw.ActionRow downgrade_row {
|
||||
title: _("Change Version");
|
||||
subtitle: _("Upgrade or downgrade this package");
|
||||
activatable: true;
|
||||
Image {
|
||||
icon-name: "right-large-symbolic";
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
from gi.repository import Adw, Gtk#, GLib, Gio, Pango
|
||||
from .error_toast import ErrorToast
|
||||
import subprocess, os
|
||||
|
||||
@Gtk.Template(resource_path="/io/github/flattool/Warehouse/properties_page/properties_page.ui")
|
||||
class PropertiesPage(Adw.NavigationPage):
|
||||
__gtype_name__ = 'PropertiesPage'
|
||||
gtc = Gtk.Template.Child
|
||||
toast_overlay = gtc()
|
||||
header_bar = gtc()
|
||||
scrolled_window = gtc()
|
||||
app_icon = gtc()
|
||||
name = gtc()
|
||||
description = gtc()
|
||||
@@ -16,6 +19,7 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
data_row = gtc()
|
||||
open_data_button = gtc()
|
||||
trash_data_button = gtc()
|
||||
data_spinner = gtc()
|
||||
version_row = gtc()
|
||||
mask_row = gtc()
|
||||
downgrade_row = gtc()
|
||||
@@ -40,13 +44,14 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
|
||||
package = None
|
||||
|
||||
def set_properties(self, package):
|
||||
if package == self.package:
|
||||
def set_properties(self, package, refresh=False):
|
||||
if package == self.package and not refresh:
|
||||
# Do not update the ui if the same app row is clicked
|
||||
print("skip")
|
||||
return
|
||||
|
||||
self.package = package
|
||||
self.set_title(package.info["id"])
|
||||
self.set_title(_("{} Properties").format(package.info["name"]))
|
||||
self.name.set_label(package.info["name"])
|
||||
pkg_description = package.info["description"]
|
||||
self.description.set_visible(pkg_description != "")
|
||||
@@ -57,17 +62,94 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
else:
|
||||
self.app_icon.set_from_icon_name("application-x-executable-symbolic")
|
||||
|
||||
package.get_cli_info()
|
||||
self.pin_row.set_visible(package.is_runtime)
|
||||
self.open_app_button.set_visible(package.is_runtime)
|
||||
self.open_app_button.set_visible(not package.is_runtime)
|
||||
if not package.is_runtime:
|
||||
has_path = os.path.exists(package.data_path)
|
||||
self.trash_data_button.set_sensitive(has_path)
|
||||
self.open_data_button.set_sensitive(has_path)
|
||||
|
||||
if has_path:
|
||||
self.trash_data_button.set_visible(False)
|
||||
self.open_data_button.set_visible(False)
|
||||
self.data_spinner.set_visible(True)
|
||||
self.data_row.set_subtitle(_("Loading User Data"))
|
||||
|
||||
def callback(size):
|
||||
self.trash_data_button.set_visible(True)
|
||||
self.open_data_button.set_visible(True)
|
||||
self.data_spinner.set_visible(False)
|
||||
self.data_row.set_subtitle(size)
|
||||
|
||||
self.package.get_data_size(lambda size: callback(size))
|
||||
else:
|
||||
self.data_row.set_subtitle(_("No User Data"))
|
||||
|
||||
cli_info = None
|
||||
try:
|
||||
cli_info = package.get_cli_info()
|
||||
except Exception as e:
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not get properties"), str(e), self.main_window).toast)
|
||||
return
|
||||
|
||||
for key, row in self.info_rows.items():
|
||||
row.set_visible(False)
|
||||
|
||||
try:
|
||||
subtitle = cli_info[key]
|
||||
row.set_subtitle(subtitle)
|
||||
row.set_visible(True)
|
||||
except KeyError:
|
||||
if key == "version":
|
||||
row.set_visible(True)
|
||||
row.set_subtitle(_("No version information found"))
|
||||
continue
|
||||
except Exception as e:
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not get properties"), str(e), self.main_window).toast)
|
||||
continue
|
||||
|
||||
def open_data_handler(self, *args):
|
||||
if error := self.package.open_data():
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not open data"), str(error), self.main_window).toast)
|
||||
|
||||
def trash_data_handler(self, *args):
|
||||
def when_done(*args):
|
||||
self.set_properties(self.package, refresh=True)
|
||||
self.toast_overlay.add_toast(Adw.Toast.new("Trashed User Data"))
|
||||
try:
|
||||
self.package.trash_data(when_done)
|
||||
except Exception as e:
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not trash data"), str(e), self.main_window).toast)
|
||||
|
||||
def __init__(self, main_window, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
# Extra Object Creation
|
||||
self.main_window = main_window
|
||||
self.info_rows = {
|
||||
"version": self.version_row,
|
||||
"installed": self.installed_size_row,
|
||||
|
||||
"id": self.id_row,
|
||||
"ref": self.ref_row,
|
||||
"arch": self.arch_row,
|
||||
"branch": self.branch_row,
|
||||
"license": self.license_row,
|
||||
|
||||
"runtime": self.runtime_row,
|
||||
"sdk": self.sdk_row,
|
||||
"origin": self.origin_row,
|
||||
"collection": self.collection_row,
|
||||
"installation": self.installation_row,
|
||||
|
||||
"commit": self.commit_row,
|
||||
"parent": self.parent_row,
|
||||
"subject": self.subject_row,
|
||||
"date": self.date_row,
|
||||
}
|
||||
|
||||
# Connections
|
||||
self.open_data_button.connect("clicked", self.open_data_handler)
|
||||
self.open_data_button.connect("clicked", self.open_data_handler)
|
||||
self.scrolled_window.get_vadjustment().connect("value-changed", lambda adjustment: self.header_bar.set_show_title(not adjustment.get_value() == 0))
|
||||
self.trash_data_button.connect("clicked", self.trash_data_handler)
|
||||
@@ -2,7 +2,7 @@ from gi.repository import Adw, Gtk, Gdk, GLib, Pango
|
||||
clipboard = Gdk.Display.get_default().get_clipboard()
|
||||
|
||||
class ErrorToast:
|
||||
def __init__(self, display_msg, error_msg, parent_window, format=True):
|
||||
def __init__(self, display_msg, error_msg, parent_window):
|
||||
|
||||
def on_response(dialog, response_id):
|
||||
if response_id == "copy":
|
||||
@@ -10,7 +10,7 @@ class ErrorToast:
|
||||
|
||||
# Extra Object Creation
|
||||
self.toast = Adw.Toast(title=display_msg, button_label=_("Details"))
|
||||
popup = Adw.AlertDialog.new(display_msg, error_msg)
|
||||
popup = Adw.AlertDialog.new(display_msg)
|
||||
|
||||
# Apply
|
||||
print(display_msg)
|
||||
|
||||
Reference in New Issue
Block a user