diff --git a/src/install_page/install_page.py b/src/install_page/install_page.py index 8a4152b..18f12c8 100644 --- a/src/install_page/install_page.py +++ b/src/install_page/install_page.py @@ -3,29 +3,6 @@ from .host_info import HostInfo from .select_page import SelectPage from .pending_page import PendingPage -class AddedGroup(Adw.PreferencesGroup): - __gtype_name__ = "AddedGroup" - - def add_row(self, row): - self.package_rows.append(row) - self.add(row) - self.set_visible(True) - - def rem_row(self, row): - if row in self.package_rows: - self.package_rows.remove(row) - self.remove(row) - - def __init__(self, remote, installation, **kwargs): - super().__init__(**kwargs) - - self.remote = remote - self.installation = installation - self.package_rows = [] - - self.set_title(f"{remote.title}") - self.set_description(_("Installation: {}").format(installation)) - @Gtk.Template(resource_path="/io/github/flattool/Warehouse/install_page/install_page.ui") class InstallPage(Adw.BreakpointBin): __gtype_name__ = "InstallPage" @@ -57,6 +34,8 @@ class InstallPage(Adw.BreakpointBin): self.instance = self # Extra Object Creation + # ======== self.select_page = SelectPage() + # ======== self.pending_page = PendingPage() # Connections self.break_point.connect("apply", self.breakpoint_handler, True) @@ -64,3 +43,5 @@ class InstallPage(Adw.BreakpointBin): self.select_page.results_page.review_button.connect("clicked", lambda *_: self.split_view.set_show_content(True)) # Apply + # ======== self.split_view.set_sidebar(self.select_page) + # ======== self.split_view.set_content(self.pending_page) diff --git a/src/install_page/pending_page.blp b/src/install_page/pending_page.blp index cfb4a46..1bce7d2 100644 --- a/src/install_page/pending_page.blp +++ b/src/install_page/pending_page.blp @@ -7,13 +7,20 @@ template $PendingPage : Adw.NavigationPage { [top] Adw.HeaderBar { } - Adw.PreferencesPage preferences_page { - Adw.PreferencesGroup { - title: "Flathub"; - description: "Installation: system"; - Adw.ActionRow { - title: "Firefox"; - subtitle: "org.mozilla.Firefox"; + Stack stack { + Adw.StatusPage none_pending { + icon-name: "flatpak-symbolic"; + title: _("Add Packages"); + description: _("Packages queued to install will show up here"); + } + Adw.PreferencesPage preferences_page { + Adw.PreferencesGroup { + title: "Flathub"; + description: "Installation: system"; + Adw.ActionRow { + title: "Firefox"; + subtitle: "org.mozilla.Firefox"; + } } } } diff --git a/src/install_page/pending_page.py b/src/install_page/pending_page.py index c4ae4c5..c49b871 100644 --- a/src/install_page/pending_page.py +++ b/src/install_page/pending_page.py @@ -1,11 +1,61 @@ from gi.repository import Adw, Gtk, GLib, Gio from .host_info import HostInfo from .error_toast import ErrorToast +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 __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)) @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() + none_pending = gtc() + preferences_page = gtc() + + def add_package(self, row): + key = f"{row.package.remote}<>{row.package.installation}" + row = ResultRow(row.package, ResultRow.PackageState.ADDED) + row.connect("activated", self.remove_package, group) + try: + group = self.groups[key] + group.add_row(row) + except KeyError: + group = AddedGroup(row.package.remote, row.package.installation) + group.add_row(row) + self.groups[key] = group + self.preferences_page.append(group) + + def remove_package(self, row, group): + pass + def __init__(self, **kwargs): super().__init__(**kwargs) + + # Extra Object Creation + self.groups = {} # remote<>installation: adw.preference_group + + # Connections + + # Apply diff --git a/src/install_page/result_row.blp b/src/install_page/result_row.blp index 73c969f..d7928a2 100644 --- a/src/install_page/result_row.blp +++ b/src/install_page/result_row.blp @@ -34,17 +34,15 @@ template $ResultRow : Adw.ActionRow { icon-name: "plus-large-symbolic"; } [suffix] + Image selected_image { + icon-name: "check-plain-symbolic"; + } + [suffix] Image sub_image { icon-name: "minus-large-symbolic"; } [suffix] - Image selected_image { - icon-name: "check-plain-symbolic"; - visible: false; - } - [suffix] - Image already_installed_image { - visible: false; + Image installed_image { icon-name: "selection-mode-symbolic"; styles ["success"] } diff --git a/src/install_page/result_row.py b/src/install_page/result_row.py index 6373ea2..88911f3 100644 --- a/src/install_page/result_row.py +++ b/src/install_page/result_row.py @@ -1,6 +1,7 @@ from gi.repository import Adw, Gtk, GLib, Gio, Gdk from .host_info import HostInfo from .error_toast import ErrorToast +from enum import Enum import os, subprocess @Gtk.Template(resource_path="/io/github/flattool/Warehouse/install_page/result_row.ui") @@ -13,6 +14,13 @@ class ResultRow(Adw.ActionRow): add_image = gtc() sub_image = gtc() selected_image = gtc() + installed_image = gtc() + + class PackageState(Enum): + NEW = 0 + SELECTED = 1 + ADDED = 2 + INSTALLED = 3 def idle_stuff(self): self.set_title(GLib.markup_escape_text(self.package.name)) @@ -21,23 +29,43 @@ class ResultRow(Adw.ActionRow): self.branch_label.set_label(GLib.markup_escape_text(self.package.branch)) self.version_label.set_visible(len(self.version_label.get_label()) != 0) self.branch_label.set_visible(len(self.branch_label.get_label()) != 0) - if self.is_added: - self.set_tooltip_text(_("Remove Package from Queue")) - def set_is_added(self, is_added): - self.is_added = is_added - self.set_sensitive(not is_added) - self.add_image.set_visible(not is_added) - self.selected_image.set_visible(is_added) - self.set_tooltip_text(_("This package is queued") if is_added else _("Add Package to Queue")) + def update_state_handler(self, state): + if state == self.state: + return - def __init__(self, package, is_added=False, **kwargs): + self.state = state + self.add_image.set_visible(False) + self.sub_image.set_visible(False) + self.selected_image.set_visible(False) + self.installed_image.set_visible(False) + match state: + case self.PackageState.NEW: + self.set_sensitive(True) + self.set_tooltip_text(_("Add Package to Queue")) + self.add_image.set_visible(True) + case self.PackageState.SELECTED: + self.set_sensitive(False) + self.set_tooltip_text(_("Package has been Added to Queue")) + self.selected_image.set_visible(True) + case self.PackageState.ADDED: + self.set_sensitive(True) + self.set_tooltip_text(_("Remove Package from Queue")) + self.sub_image.set_visible(True) + case self.PackageState.INSTALLED: + self.set_sensitive(False) + self.set_tooltip_text(_("This Package is Already Installed")) + self.installed_image.set_visible(True) + + def __init__(self, package, package_state, parent_row=None, **kwargs): super().__init__(**kwargs) - self.is_added = is_added + # Extra Object Creation + self.state = None self.package = package - self.sub_image.set_visible(is_added) - self.add_image.set_visible(not is_added) + # Connections + # Apply GLib.idle_add(self.idle_stuff) + self.update_state_handler(package_state) diff --git a/src/install_page/results_page.blp b/src/install_page/results_page.blp index 1fb3dfa..be58ac7 100644 --- a/src/install_page/results_page.blp +++ b/src/install_page/results_page.blp @@ -28,10 +28,15 @@ template $ResultsPage : Adw.NavigationPage { } Stack stack { Adw.StatusPage new_search { - icon-name: "flatpak-symbolic"; + icon-name: "loupe-large-symbolic"; title: _("Search for Flatpaks"); description: _("Search for Flatpaks you want to install"); } + Adw.StatusPage too_many { + icon-name: "error-symbolic"; + title: _("Too Many Results"); + description: _("Try being more specific with your search"); + } Adw.StatusPage loading { title: _("Searching"); description: _("This should only take a moment"); diff --git a/src/install_page/results_page.py b/src/install_page/results_page.py index eb44004..39e55b5 100644 --- a/src/install_page/results_page.py +++ b/src/install_page/results_page.py @@ -42,6 +42,7 @@ class ResultsPage(Adw.NavigationPage): results_list = gtc() stack = gtc() new_search = gtc() + too_many = gtc() loading = gtc() results_view= gtc() no_results = gtc() @@ -50,10 +51,14 @@ class ResultsPage(Adw.NavigationPage): self.remote = remote self.installation = installation self.set_title(_("Search {}").format(remote.title)) + self.search_entry.set_text("") self.search_entry.grab_focus() if nav_view: nav_view.push(self) + def add_package(self, row): + print(row) + def on_search(self, *args): self.packages.clear() self.stack.set_visible_child(self.loading) @@ -66,15 +71,19 @@ class ResultsPage(Adw.NavigationPage): def thread(*args): installation = "" if self.installation == "user" or self.installation == "system": - installation = self.installation + installation = f"--{self.installation}" else: installation = f"--installation={self.installation}" try: output = subprocess.run( - ['flatpak-spawn', '--host', 'flatpak', 'search', '--columns=all', self.remote.name, installation, self.search_entry.get_text()], + ['flatpak-spawn', '--host', 'flatpak', 'search', '--columns=all', installation, self.search_entry.get_text()], check=True, text=True, capture_output=True ).stdout.split('\n') + if len(output) > 100: + GLib.idle_add(lambda *_: self.stack.set_visible_child(self.too_many)) + return + for line in output: line = line.strip() @@ -82,19 +91,27 @@ class ResultsPage(Adw.NavigationPage): if len(info) != 6: continue + remotes = info[5].split(',') + if not self.remote.name in remotes: + continue + package = AddedPackage(info[0], info[2], info[4], info[3], self.remote, self.installation) - row = ResultRow(package) + row = ResultRow(package, ResultRow.PackageState.NEW) + row.connect("activated", self.add_package) self.packages.append(package) GLib.idle_add(lambda *_, _row=row: self.results_list.append(_row)) + if len(self.packages) > 0: + GLib.idle_add(lambda *_: self.stack.set_visible_child(self.results_view)) + else: + GLib.idle_add(lambda *_: self.stack.set_visible_child(self.no_results)) + except subprocess.CalledProcessError as cpe: print(cpe) def callback(*args): - if len(self.packages) > 0: - self.stack.set_visible_child(self.results_view) - else: - self.stack.set_visible_child(self.no_results) + pass + Gio.Task.new(None, None, callback).run_in_thread(thread) diff --git a/src/install_page/select_page.py b/src/install_page/select_page.py index c9061c8..d1587ad 100644 --- a/src/install_page/select_page.py +++ b/src/install_page/select_page.py @@ -17,10 +17,12 @@ class SelectPage(Adw.NavigationPage): test = gtc() def start_loading(self): - pass + self.nav_view.pop() + for row in self.remote_rows: + self.remotes_group.remove(row) + self.remote_rows.clear() def end_loading(self): - total_remotes = 0 for installation, remotes in HostInfo.remotes.items(): for remote in remotes: if remote.disabled: @@ -30,9 +32,9 @@ class SelectPage(Adw.NavigationPage): row.add_suffix(Gtk.Image(icon_name="right-large-symbolic")) row.connect("activated", self.results_page.show_remote, remote, installation, self.nav_view) self.remotes_group.add(row) - total_remotes += 1 + self.remote_rows.append(row) - self.remotes_group.set_visible(total_remotes != 0) + self.remotes_group.set_visible(len(self.remote_rows) != 0) def __init__(self, **kwargs): super().__init__(**kwargs) @@ -45,6 +47,7 @@ class SelectPage(Adw.NavigationPage): self.sidebar_button.connect("toggled", lambda *_: ms.set_show_sidebar(self.sidebar_button.get_active())) self.add_remote_row.connect("activated", lambda *_: HostInfo.main_window.activate_row(HostInfo.main_window.remotes_row)) self.nav_view.connect("popped", self.results_page.on_back) + self.remote_rows = [] self.test.connect("clicked", lambda *_: self.nav_view.push(self.results_page))