mirror of
https://github.com/morgan9e/warehouse
synced 2026-04-14 00:04:08 +09:00
Implement package reinstalling
This commit is contained in:
@@ -33,6 +33,13 @@ template $PackagesPage : Adw.BreakpointBin {
|
||||
$SidebarButton {}
|
||||
}
|
||||
}
|
||||
Adw.ToolbarView reinstalling_view {
|
||||
[top]
|
||||
Adw.HeaderBar {
|
||||
[start]
|
||||
$SidebarButton {}
|
||||
}
|
||||
}
|
||||
Adw.NavigationSplitView packages_split {
|
||||
sidebar-width-fraction: 0.5;
|
||||
max-sidebar-width: 999999999;
|
||||
|
||||
@@ -7,6 +7,7 @@ from .filters_page import FiltersPage
|
||||
from .sidebar_button import SidebarButton
|
||||
from .uninstall_dialog import UninstallDialog
|
||||
from .loading_status import LoadingStatus
|
||||
from .package_install_worker import PackageInstallWorker
|
||||
import subprocess, os
|
||||
|
||||
@Gtk.Template(resource_path="/io/github/flattool/Warehouse/packages_page/packages_page.ui")
|
||||
@@ -20,6 +21,7 @@ class PackagesPage(Adw.BreakpointBin):
|
||||
scrolled_window = gtc()
|
||||
loading_view = gtc()
|
||||
uninstalling_view = gtc()
|
||||
reinstalling_view = gtc()
|
||||
no_filter_results = gtc()
|
||||
reset_filters_button = gtc()
|
||||
no_packages = gtc()
|
||||
@@ -80,6 +82,8 @@ class PackagesPage(Adw.BreakpointBin):
|
||||
self.stack.set_visible_child(self.loading_view)
|
||||
elif to_set is self.uninstalling:
|
||||
self.stack.set_visible_child(self.uninstalling_view)
|
||||
elif to_set is self.reinstalling:
|
||||
self.stack.set_visible_child(self.reinstalling_view)
|
||||
else:
|
||||
self.stack.set_visible_child(self.packages_split)
|
||||
self.status_stack.set_visible_child(to_set)
|
||||
@@ -313,6 +317,8 @@ class PackagesPage(Adw.BreakpointBin):
|
||||
self.loading_packages = LoadingStatus(_("Loading Packages"), _("This should only take a moment"))
|
||||
self.uninstalling = LoadingStatus(_("Uninstalling Packages"), _("This should only take a moment"))
|
||||
self.uninstalling_view.set_content(self.uninstalling)
|
||||
self.reinstalling = LoadingStatus(_("Reinstalling Package"), _("This could take a while"), True, PackageInstallWorker.cancel)
|
||||
self.reinstalling_view.set_content(self.reinstalling)
|
||||
self.properties_page = PropertiesPage(main_window, self)
|
||||
self.filters_page = FiltersPage(main_window, self)
|
||||
self.filter_settings = Gio.Settings.new("io.github.flattool.Warehouse.filter")
|
||||
|
||||
@@ -4,6 +4,7 @@ from .host_info import HostInfo
|
||||
from .change_version_page import ChangeVersionPage
|
||||
from .uninstall_dialog import UninstallDialog
|
||||
from .loading_status import LoadingStatus
|
||||
from .package_install_worker import PackageInstallWorker
|
||||
import subprocess, os
|
||||
|
||||
@Gtk.Template(resource_path="/io/github/flattool/Warehouse/properties_page/properties_page.ui")
|
||||
@@ -13,10 +14,10 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
stack = gtc()
|
||||
error_tbv = gtc()
|
||||
loading_tbv = gtc()
|
||||
|
||||
|
||||
more_menu = gtc()
|
||||
more_list = gtc()
|
||||
|
||||
|
||||
nav_view = gtc()
|
||||
inner_nav_page = gtc()
|
||||
toast_overlay = gtc()
|
||||
@@ -49,7 +50,7 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
arch_row = gtc()
|
||||
branch_row = gtc()
|
||||
license_row = gtc()
|
||||
|
||||
|
||||
sdk_row = gtc()
|
||||
origin_row = gtc()
|
||||
collection_row = gtc()
|
||||
@@ -59,14 +60,15 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
parent_row = gtc()
|
||||
subject_row = gtc()
|
||||
date_row = gtc()
|
||||
|
||||
|
||||
package = None
|
||||
|
||||
|
||||
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
|
||||
return
|
||||
|
||||
|
||||
self.reinstall_did_error = False
|
||||
self.package = package
|
||||
pkg_name = package.info["name"]
|
||||
if pkg_name != "":
|
||||
@@ -76,12 +78,12 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
else:
|
||||
self.name.set_visible(False)
|
||||
self.inner_nav_page.set_title(_("Properties"))
|
||||
|
||||
|
||||
if package.icon_path:
|
||||
GLib.idle_add(lambda *_: self.app_icon.set_from_file(package.icon_path))
|
||||
else:
|
||||
GLib.idle_add(lambda *_: self.app_icon.set_from_icon_name("application-x-executable-symbolic"))
|
||||
|
||||
|
||||
self.eol_box.set_visible(package.is_eol)
|
||||
self.pin_row.set_visible(package.is_runtime)
|
||||
self.open_app_button.set_visible(package.is_runtime)
|
||||
@@ -93,29 +95,29 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
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 not self.package.dependant_runtime is None:
|
||||
self.runtime_row.set_visible(True)
|
||||
self.runtime_row.set_subtitle(self.package.dependant_runtime.info["name"])
|
||||
self.eol_package_package_status_icon.set_visible(self.package.dependant_runtime.is_eol)
|
||||
|
||||
|
||||
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"))
|
||||
self.data_spinner.set_visible(False)
|
||||
|
||||
|
||||
cli_info = None
|
||||
try:
|
||||
cli_info = package.get_cli_info()
|
||||
@@ -125,10 +127,10 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
except Exception as e:
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not get properties"), str(e)).toast)
|
||||
return
|
||||
|
||||
|
||||
for key, row in self.info_rows.items():
|
||||
row.set_visible(False)
|
||||
|
||||
|
||||
try:
|
||||
subtitle = cli_info[key]
|
||||
row.set_subtitle(subtitle)
|
||||
@@ -141,7 +143,7 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
except Exception as e:
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not get properties"), str(e)).toast)
|
||||
continue
|
||||
|
||||
|
||||
self.mask_label.set_visible(package.is_masked)
|
||||
self.mask_switch.set_active(package.is_masked)
|
||||
self.pin_switch.set_active(package.is_pinned)
|
||||
@@ -150,14 +152,14 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
if self.open_app_button.get_visible():
|
||||
self.more_list.append(self.view_snapshots)
|
||||
self.more_list.append(self.copy_launch_command)
|
||||
|
||||
|
||||
self.more_list.append(self.show_details)
|
||||
self.more_list.append(self.reinstall)
|
||||
|
||||
def open_data_handler(self, *args):
|
||||
if error := self.package.open_data():
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not open data"), str(error)).toast)
|
||||
|
||||
|
||||
def trash_data_handler(self, *args):
|
||||
def on_choice(dialog, response):
|
||||
if response != 'continue':
|
||||
@@ -170,7 +172,7 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not trash data"), cpe.stderr).toast)
|
||||
except Exception as e:
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not trash data"), str(e)).toast)
|
||||
|
||||
|
||||
dialog = Adw.AlertDialog(
|
||||
heading=_("Send {}'s User Data to the Trash?").format(self.package.info["name"]),
|
||||
body=_("Your settings and data for this app will be sent to the trash")
|
||||
@@ -180,7 +182,7 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
dialog.connect("response", on_choice)
|
||||
dialog.set_response_appearance('continue', Adw.ResponseAppearance.DESTRUCTIVE)
|
||||
dialog.present(self.main_window)
|
||||
|
||||
|
||||
def set_mask_handler(self, *args):
|
||||
state = not self.mask_switch.get_active()
|
||||
def callback(*args):
|
||||
@@ -194,9 +196,9 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
self.toast_overlay.add_toast(Adw.Toast(title=response))
|
||||
GLib.idle_add(lambda *_: self.mask_switch.set_active(state))
|
||||
self.package.app_row.masked_status_icon.set_visible(state)
|
||||
|
||||
|
||||
self.package.set_mask(state, callback)
|
||||
|
||||
|
||||
def set_pin_handler(self, *args):
|
||||
state = not self.pin_switch.get_active()
|
||||
def callback(*args):
|
||||
@@ -210,9 +212,9 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
self.toast_overlay.add_toast(Adw.Toast(title=response))
|
||||
GLib.idle_add(lambda *_: self.pin_switch.set_active(state))
|
||||
self.package.app_row.pinned_status_icon.set_visible(state)
|
||||
|
||||
|
||||
self.package.set_pin(state, callback)
|
||||
|
||||
|
||||
def uninstall_handler(self, *args):
|
||||
def on_choice(should_trash):
|
||||
self.packages_page.set_status(self.packages_page.uninstalling)
|
||||
@@ -226,7 +228,7 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not trash data"), cpe.stderr).toast)
|
||||
except Exception as e:
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not trash data"), str(e)).toast)
|
||||
|
||||
|
||||
def callback(*args):
|
||||
if fail := self.package.failed_uninstall:
|
||||
fail = fail.stderr if type(fail) == subprocess.CalledProcessError else fail
|
||||
@@ -235,16 +237,16 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
else:
|
||||
self.main_window.refresh_handler()
|
||||
self.packages_page.packages_toast_overlay.add_toast(Adw.Toast(title=_("Uninstalled {}").format(self.package.info["name"])))
|
||||
|
||||
|
||||
# name = self.package.info["name"]
|
||||
dialog = UninstallDialog(on_choice, os.path.exists(self.package.data_path), self.package.info["name"])
|
||||
dialog.present(self.main_window)
|
||||
|
||||
|
||||
def runtime_row_handler(self, *args):
|
||||
new_page = self.__class__(self.main_window, self.packages_page)
|
||||
new_page.set_properties(self.package.dependant_runtime)
|
||||
self.nav_view.push(new_page)
|
||||
|
||||
|
||||
def open_app_handler(self, *args):
|
||||
self.toast_overlay.add_toast(Adw.Toast(title=_("Openeing {}…").format(self.package.info["name"])))
|
||||
|
||||
@@ -252,17 +254,26 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
if fail := self.package.failed_app_run:
|
||||
fail = fail.stderr if type(fail) == subprocess.CalledProcessError else fail
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not open {}").format(self.package.info["name"]), str(fail)).toast)
|
||||
|
||||
|
||||
self.package.open_app(callback)
|
||||
|
||||
|
||||
def copy_handler(self, row):
|
||||
HostInfo.clipboard.set(row.get_subtitle())
|
||||
self.toast_overlay.add_toast(Adw.Toast(title=_("Copied {}").format(row.get_title())))
|
||||
|
||||
|
||||
def change_version_handler(self, row):
|
||||
page = ChangeVersionPage(self.main_window, self.package)
|
||||
self.nav_view.push(page)
|
||||
|
||||
|
||||
def reinstall_callback(self):
|
||||
HostInfo.main_window.refresh_handler()
|
||||
if not self.reinstall_did_error:
|
||||
HostInfo.main_window.toast_overlay.add_toast(Adw.Toast(title=_("Reinstalled {}").format(self.package.info['name'])))
|
||||
|
||||
def reinstall_error_callback(self, user_facing_label, error_message):
|
||||
self.reinstall_did_error = True
|
||||
GLib.idle_add(lambda *_: HostInfo.main_window.toast_overlay.add_toast(ErrorToast(user_facing_label, error_message).toast))
|
||||
|
||||
def more_menu_handler(self, listbox, row):
|
||||
self.more_menu.popdown()
|
||||
match row.get_child():
|
||||
@@ -271,43 +282,55 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
snapshots_page = HostInfo.main_window.pages[snapshots_row]
|
||||
HostInfo.main_window.activate_row(snapshots_row)
|
||||
snapshots_page.show_snapshot(self.package)
|
||||
|
||||
|
||||
case self.copy_launch_command:
|
||||
try:
|
||||
HostInfo.clipboard.set(f"flatpak run {self.package.info['ref']}")
|
||||
self.toast_overlay.add_toast(Adw.Toast.new(_("Copied launch command")))
|
||||
except Exception as e:
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not copy launch command"), str(e)).toast)
|
||||
|
||||
|
||||
case self.show_details:
|
||||
try:
|
||||
Gio.AppInfo.launch_default_for_uri(f"appstream://{self.package.info['id']}", None)
|
||||
except Exception as e:
|
||||
self.toast_overlay.add_toast(ErrorToast(_("Could not show details"), str(e)).toast)
|
||||
|
||||
|
||||
case self.reinstall:
|
||||
print("not implemented")
|
||||
|
||||
self.reinstall_did_error = False
|
||||
PackageInstallWorker.install(
|
||||
[{
|
||||
"installation": self.package.info['installation'],
|
||||
"remote": self.package.info['origin'],
|
||||
"package_names": [self.package.info['ref']],
|
||||
"extra_flags": ["--reinstall"],
|
||||
}],
|
||||
self.packages_page.reinstalling,
|
||||
self.reinstall_callback,
|
||||
self.reinstall_error_callback,
|
||||
)
|
||||
self.packages_page.set_status(self.packages_page.reinstalling)
|
||||
|
||||
def __init__(self, main_window, packages_page, **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,
|
||||
|
||||
|
||||
"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,
|
||||
@@ -320,9 +343,10 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
self.copy_launch_command = Gtk.Label(halign=Gtk.Align.START, label=_("Copy Launch Command"))
|
||||
self.show_details = Gtk.Label(halign=Gtk.Align.START, label=_("Show Details"))
|
||||
self.reinstall = Gtk.Label(halign=Gtk.Align.START, label=_("Reinstall"))
|
||||
|
||||
self.reinstall_did_error = False
|
||||
|
||||
# Apply
|
||||
|
||||
|
||||
# Connections
|
||||
self.more_list.connect("row-activated", self.more_menu_handler)
|
||||
self.open_data_button.connect("clicked", self.open_data_handler)
|
||||
@@ -334,9 +358,6 @@ class PropertiesPage(Adw.NavigationPage):
|
||||
self.mask_row.connect("activated", self.set_mask_handler)
|
||||
self.pin_row.connect("activated", self.set_pin_handler)
|
||||
self.change_version_row.connect("activated", self.change_version_handler)
|
||||
for key in self.info_rows:
|
||||
row = self.info_rows[key]
|
||||
if type(row) != Adw.ActionRow:
|
||||
continue
|
||||
|
||||
row.connect("activated", self.copy_handler)
|
||||
for key, row in self.info_rows.items():
|
||||
if type(row) is Adw.ActionRow:
|
||||
row.connect("activated", self.copy_handler)
|
||||
|
||||
Reference in New Issue
Block a user