diff --git a/src/install_page/install_page.blp b/src/install_page/install_page.blp index 54fe668..1f3f0cb 100644 --- a/src/install_page/install_page.blp +++ b/src/install_page/install_page.blp @@ -24,6 +24,13 @@ template $InstallPage : Adw.BreakpointBin { $SidebarButton {} } } + Adw.ToolbarView installing_view { + [top] + Adw.HeaderBar { + [start] + $SidebarButton {} + } + } Adw.MultiLayoutView multi_view { Adw.Layout wide { Adw.NavigationSplitView split_view { diff --git a/src/install_page/install_page.py b/src/install_page/install_page.py index 5c03638..942c5cb 100644 --- a/src/install_page/install_page.py +++ b/src/install_page/install_page.py @@ -4,6 +4,7 @@ from .select_page import SelectPage from .pending_page import PendingPage from .sidebar_button import SidebarButton from .loading_status import LoadingStatus +from .package_install_worker import PackageInstallWorker @Gtk.Template(resource_path="/io/github/flattool/Warehouse/install_page/install_page.ui") class InstallPage(Adw.BreakpointBin): @@ -17,6 +18,7 @@ class InstallPage(Adw.BreakpointBin): pending_page = gtc() status_stack = gtc() loading_view = gtc() + installing_view = gtc() # Referred to in the main window # It is used to determine if a new page should be made or not @@ -34,19 +36,23 @@ class InstallPage(Adw.BreakpointBin): def end_loading(self): self.select_page.end_loading() self.status_stack.set_visible_child(self.multi_view) + + def install_packages(self, package_requests): + print(package_requests) + if PackageInstallWorker.install(package_requests, self.installing_status, HostInfo.main_window.refresh_handler, None): + self.status_stack.set_visible_child(self.installing_view) def __init__(self, main_window, **kwargs): super().__init__(**kwargs) self.instance = self # Extra Object Creation - # ======== self.select_page = SelectPage() - # ======== self.pending_page = PendingPage() + self.installing_status = LoadingStatus(_("Installing Packages"), _("This could take a while"), True, PackageInstallWorker.cancel) # Connections # Apply - # ======== self.split_view.set_sidebar(self.select_page) - # ======== self.split_view.set_content(self.pending_page) self.select_page.results_page.pending_page = self.pending_page self.loading_view.set_content(LoadingStatus(_("Loading Installation Options"), _("This should only take a moment"))) + self.installing_status.button.set_label(_("Cancel")) + self.installing_view.set_content(self.installing_status) diff --git a/src/install_page/pending_page.py b/src/install_page/pending_page.py index b9e55c7..5890c06 100644 --- a/src/install_page/pending_page.py +++ b/src/install_page/pending_page.py @@ -5,30 +5,30 @@ from .result_row import ResultRow class AddedGroup(Adw.PreferencesGroup): __gtype_name__ = "AddedGroup" - + def add_row(self, row): self.rows.append(row) self.add(row) - + def rem_row(self, row): if row in self.rows: self.rows.remove(row) self.remove(row) - + def remove_all(self, button): while len(self.rows) > 0 and (row := self.rows[0]): row.activate() - + def __init__(self, remote, installation, **kwargs): super().__init__(**kwargs) - + self.remote = remote self.installation = installation self.rows = [] - + self.set_title(f"{remote.title}") self.set_description(_("Installation: {}").format(installation)) - + remove_all = Gtk.Button( child=Adw.ButtonContent( icon_name="list-remove-all-symbolic", @@ -39,17 +39,18 @@ class AddedGroup(Adw.PreferencesGroup): remove_all.add_css_class("flat") remove_all.connect("clicked", self.remove_all) self.set_header_suffix(remove_all) - + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/install_page/pending_page.ui") class PendingPage(Adw.NavigationPage): __gtype_name__ = "PendingPage" gtc = Gtk.Template.Child - + stack = gtc() main_view = gtc() none_pending = gtc() preferences_page = gtc() - + install_button = gtc() + def add_package_row(self, row): self.added_packages.append(row.package) row.set_state(ResultRow.PackageState.SELECTED) @@ -64,17 +65,17 @@ class PendingPage(Adw.NavigationPage): group.add_row(added_row) self.groups[key] = group self.preferences_page.add(group) - + added_row.connect("activated", self.remove_package_row, group) self.stack.set_visible_child(self.main_view) - + def remove_package_row(self, row, group): # row.origin_row.set_state(ResultRow.PackageState.NEW) for item in row.origin_list_box: if item.state == ResultRow.PackageState.SELECTED and item.package.is_similar(row.package): item.set_state(ResultRow.PackageState.NEW) break - + group.rem_row(row) if row.package in self.added_packages: self.added_packages.remove(row.package) @@ -83,17 +84,34 @@ class PendingPage(Adw.NavigationPage): key = f"{row.package.remote}<>{row.package.installation}" self.groups.pop(key, None) self.preferences_page.remove(group) - + if len(self.added_packages) == 0: self.stack.set_visible_child(self.none_pending) - + + def on_install(self, *args): + package_requests = [] + for key, group in self.groups.items(): + item = { + 'remote': group.remote.name, + 'installation': group.installation, + 'package_names': [], + } + for row in group.rows: + item['package_names'].append(row.package.app_id) + + package_requests.append(item) + + install_page = HostInfo.main_window.pages[HostInfo.main_window.install_row] + install_page.install_packages(package_requests) + def __init__(self, **kwargs): super().__init__(**kwargs) - + # Extra Object Creation self.groups = {} # remote<>installation: adw.preference_group self.added_packages = [] - + # Connections - + self.install_button.connect("clicked", self.on_install) + # Apply diff --git a/src/package_install_worker.py b/src/package_install_worker.py index 354cf32..0139082 100644 --- a/src/package_install_worker.py +++ b/src/package_install_worker.py @@ -23,13 +23,6 @@ class PackageInstallWorker: total_groups = 0 cancelled = False - @classmethod - def on_error(this, user_facing_label, error_message): - print("\nPackageInstallWorker error:", user_facing_label) - print(error_message, "\n") - if not this.error_callback is None: - this.error_callback(user_facing_label, error_message) - @classmethod def update_status(this, index, package_ratio, complete, total): group_ratio = (package_ratio + complete) / (total or 1) @@ -40,7 +33,7 @@ class PackageInstallWorker: print("=======================================") if not this.loading_status is None: - GLib.idle_add(lambda *_: loading_status.progress_bar.set_fraction(final_ratio)) + GLib.idle_add(lambda *_: this.loading_status.progress_bar.set_fraction(final_ratio)) @classmethod def install_thread(this): @@ -83,7 +76,7 @@ class PackageInstallWorker: errors.append(error) if len(errors) > 0: - this.on_error("\n".join(errors)) + this.on_error(_("Could not install some packages"), "\n".join(errors)) except subprocess.TimeoutExpired as te: this.process.terminate() @@ -95,6 +88,9 @@ class PackageInstallWorker: @classmethod def cancel(this): + if this.process is None: + return + try: this.cancelled = True this.process.terminate() @@ -106,9 +102,19 @@ class PackageInstallWorker: def on_done(this, *args): this.process = None this.cancelled = False + if not this.loading_status is None: + this.loading_status.progress_bar.set_fraction(0.0) + if not this.callback is None: this.callback() + @classmethod + def on_error(this, user_facing_label, error_message): + print("\nPackageInstallWorker error:", user_facing_label) + print(error_message, "\n") + if not this.error_callback is None: + this.error_callback(user_facing_label, error_message) + @classmethod def install(this, groups, loading_status=None, callback=None, error_callback=None): if not this.process is None: @@ -125,5 +131,5 @@ class PackageInstallWorker: this.on_error(_("Could not install packages"), _("No packages were asked to be installed.")) return False - Gio.Task.new(None, None, callback).run_in_thread(lambda *_: this.install_thread()) + Gio.Task.new(None, None, this.on_done).run_in_thread(lambda *_: this.install_thread()) return True