diff --git a/src/filters_page/filters_page.blp b/src/filters_page/filters_page.blp index afa07a1..9d69141 100644 --- a/src/filters_page/filters_page.blp +++ b/src/filters_page/filters_page.blp @@ -11,6 +11,7 @@ template $FiltersPage : Adw.NavigationPage { Box { margin-start: 12; margin-end: 12; + margin-top: 12; margin-bottom: 12; orientation: vertical; halign: fill; @@ -18,16 +19,6 @@ template $FiltersPage : Adw.NavigationPage { Adw.PreferencesGroup { title: _("Package Type"); description: _("Show packages of these types"); - header-suffix: - Button all_types_button { - Adw.ButtonContent { - label: _("Select All"); - icon-name: "selection-mode-symbolic"; - } - valign: center; - styles ["flat"] - } - ; Adw.ActionRow application_row { title: _("Applications"); subtitle: _("Packages that can be opened"); @@ -39,17 +30,17 @@ template $FiltersPage : Adw.NavigationPage { Adw.ActionRow runtime_row { title: _("Runtimes"); subtitle: _("Packages that applications depend on"); - CheckButton runtime-check { + CheckButton runtime_check { styles["selection-mode"] } - activatable-widget: runtime-check; + activatable-widget: runtime_check; } } - Adw.PreferencesGroup { + Adw.PreferencesGroup remotes_group { title: _("Remotes"); description: _("Show packages from these remotes"); header-suffix: - Button all_remotes_button { + ToggleButton all_remotes_button { Adw.ButtonContent { label: _("Select All"); icon-name: "selection-mode-symbolic"; @@ -58,26 +49,12 @@ template $FiltersPage : Adw.NavigationPage { styles ["flat"] } ; - Adw.ActionRow { - title: _("Flathub"); - subtitle: _("Installation: User"); - CheckButton { - styles["selection-mode"] - } - } - Adw.ActionRow { - title: _("Flathub"); - subtitle: _("Installation: System"); - CheckButton { - styles["selection-mode"] - } - } } - Adw.PreferencesGroup { + Adw.PreferencesGroup runtimes_group { title: _("Runtimes"); description: _("Show apps that use these runtimes"); header-suffix: - Button all_runtimes_button { + ToggleButton all_runtimes_button { Adw.ButtonContent { label: _("Select All"); icon-name: "selection-mode-symbolic"; @@ -86,30 +63,6 @@ template $FiltersPage : Adw.NavigationPage { styles ["flat"] } ; - Adw.ActionRow { - title: _("org.freedesktop.Platform.ffmpeg-full/x86_64/23.08"); - CheckButton { - styles["selection-mode"] - } - } - Adw.ActionRow { - title: _("org.gnome.Platform/x86_64/44"); - CheckButton { - styles["selection-mode"] - } - } - Adw.ActionRow { - title: _("org.gnome.Platform/x86_64/45"); - CheckButton { - styles["selection-mode"] - } - } - Adw.ActionRow { - title: _("org.freedesktop.Platform.Compat.i386/x86_64/23.08"); - CheckButton { - styles["selection-mode"] - } - } } } } diff --git a/src/filters_page/filters_page.py b/src/filters_page/filters_page.py index 8a425d6..d1948a4 100644 --- a/src/filters_page/filters_page.py +++ b/src/filters_page/filters_page.py @@ -1,11 +1,79 @@ -from gi.repository import Adw, Gtk, GLib#, Gio, Pango +from gi.repository import Adw, Gtk, GLib, Gio from .host_info import HostInfo +class FilterRow(Adw.ActionRow): + __gtype_name__ = 'FilterRow' + def __init__(self, item=None, installation=None, **kwargs): + super().__init__(**kwargs) + self.item = item + self.installation = installation + self.check_button = Gtk.CheckButton() + self.check_button.add_css_class("selection-mode") + self.add_suffix(self.check_button) + self.set_activatable_widget(self.check_button) + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/filters_page/filters_page.ui") class FiltersPage(Adw.NavigationPage): __gtype_name__ = 'FiltersPage' gtc = Gtk.Template.Child + app_check = gtc() + runtime_check = gtc() + remotes_group = gtc() + runtimes_group = gtc() + all_remotes_button = gtc() + all_runtimes_button = gtc() + + remote_rows = [] + runtime_rows = [] + + def generate_list(self): + for row in self.remote_rows: + self.remotes_group.remove(row) + + for row in self.runtime_rows: + self.runtimes_group.remove(row) + + self.remote_rows.clear() + self.runtime_rows.clear() + + self.app_check.set_active(self.settings.get_boolean("show-apps")) + self.runtime_check.set_active(self.settings.get_boolean("show-runtimes")) + + remotes_string = self.settings.get_string("runtimes-list") + self.all_remotes_button.set_active("all" == remotes_string) + for installation in HostInfo.installations: + try: + for remote in HostInfo.remotes[installation]: + row = FilterRow(remote, installation) + row.set_title(remote.title) + row.set_subtitle(_("Installation: {}").format(installation)) + row.check_button.set_active(self.all_remotes_button.get_active()) + self.remote_rows.append(row) + self.remotes_group.add(row) + except KeyError: + pass + + runtimes_string = self.settings.get_string("runtimes-list") + self.all_runtimes_button.set_active("all" == runtimes_string) + for ref in HostInfo.dependant_runtime_refs: + row = FilterRow(ref) + row.set_title(ref) + row.check_button.set_active(self.all_runtimes_button.get_active()) + self.runtime_rows.append(row) + self.runtimes_group.add(row) + + def select_all_handler(self, rows, button): + for row in rows: + row.check_button.set_active(button.get_active()) def __init__(self, main_window, packages_page, **kwargs): super().__init__(**kwargs) - # self.connect("hidden", lambda *_: packages_page.filter_button.set_active(False)) \ No newline at end of file + + # Extra Objects Creation + self.settings = Gio.Settings.new("io.github.flattool.Warehouse.filter") + + # Apply + + # Connections + self.all_remotes_button.connect("toggled", lambda *_: self.select_all_handler(self.remote_rows, self.all_remotes_button)) + self.all_runtimes_button.connect("toggled", lambda *_: self.select_all_handler(self.runtime_rows, self.all_runtimes_button)) \ No newline at end of file diff --git a/src/host_info.py b/src/host_info.py index 2e93d08..5dd0332 100644 --- a/src/host_info.py +++ b/src/host_info.py @@ -181,9 +181,11 @@ class Flatpak: class Remote: - def __init__(self, name, installation): + def __init__(self, name, title): self.name = name - self.installation = installation + self.title = title + if title == "" or title == "-": + self.title = name class HostInfo: home = home @@ -202,10 +204,11 @@ class HostInfo: flatpaks = [] ref_to_flatpak = {} - remotes = [] + remotes = {} installations = [] masks = {} pins = {} + dependant_runtime_refs = [] @classmethod def get_flatpaks(this, callback=None): # Callback is a function to run after the host flatpaks are found @@ -215,27 +218,29 @@ class HostInfo: this.installations.clear() this.masks.clear() this.pins.clear() + this.dependant_runtime_refs.clear() def thread(task, *args): # Remotes def remote_info(installation): - # cmd = ['flatpak-spawn', '--host', - # 'flatpak', 'remotes'] - # if installation == "user" or installation == "system": - # cmd.append(f"--{installation}") - # else: - # cmd.append(f"--installation={installation}") - # output = subprocess.run( - # cmd, text=True, - # capture_output=True, - # ).stdout - # lines = output.strip().split("\n") - # for i in lines: - # if i != "": - # this.remotes.append(Remote(i.strip(), installation)) - # if installation == "user" or installation == "system": - # this.installations.append(installation) + cmd = ['flatpak-spawn', '--host', + 'flatpak', 'remotes', '--columns=name,title'] + if installation == "user" or installation == "system": + cmd.append(f"--{installation}") + else: + cmd.append(f"--installation={installation}") + output = subprocess.run( + cmd, text=True, + capture_output=True, + ).stdout + lines = output.strip().replace(" ", "").split("\n") + if lines[0] != '': + remote_list = [] + for line in lines: + line = line.split("\t") + remote_list.append(Remote(line[0], line[1])) + this.remotes[installation] = remote_list # Masks cmd = ['flatpak-spawn', '--host', @@ -278,6 +283,8 @@ class HostInfo: # Get specifically the installation name itself this.installations.append(line.replace("[Installation \"", "").replace("\"]", "").strip()) + this.installations.append("user") + this.installations.append("system") for i in this.installations: remote_info(i) remote_info("user") @@ -309,7 +316,10 @@ class HostInfo: if package.is_runtime: continue package.dependant_runtime = this.ref_to_flatpak[runtime] + if not runtime in this.dependant_runtime_refs: + this.dependant_runtime_refs.append(runtime) this.flatpaks = sorted(this.flatpaks, key=lambda flatpak: flatpak.info["name"].lower()) + this.dependant_runtime_refs = sorted(this.dependant_runtime_refs) Gio.Task.new(None, None, callback).run_in_thread(thread) \ No newline at end of file diff --git a/src/packages_page/packages_page.py b/src/packages_page/packages_page.py index 1d89fc3..572ed47 100644 --- a/src/packages_page/packages_page.py +++ b/src/packages_page/packages_page.py @@ -33,8 +33,14 @@ class PackagesPage(Adw.BreakpointBin): def generate_list(self, *args): self.packages_list_box.remove_all() + GLib.idle_add(lambda *_: self.filters_page.generate_list()) + first = True for package in HostInfo.flatpaks: - row = AppRow(package) + row = None + if first: + row = AppRow(package, lambda *_: self.stack.set_visible_child(self.packages_split)) + else: + row = AppRow(package) package.app_row = row row.masked_status_icon.set_visible(package.is_masked) row.pinned_status_icon.set_visible(package.is_pinned) @@ -51,7 +57,6 @@ class PackagesPage(Adw.BreakpointBin): self.packages_list_box.select_row(first_row) self.properties_page.set_properties(first_row.package) self.scrolled_window.set_vadjustment(Gtk.Adjustment.new(0,0,0,0,0,0)) # Scroll list to top - self.stack.set_visible_child(self.packages_split) def row_select_handler(self, list_box, row): self.properties_page.set_properties(row.package) @@ -99,6 +104,7 @@ class PackagesPage(Adw.BreakpointBin): def __init__(self, main_window, **kwargs): super().__init__(**kwargs) + HostInfo.get_flatpaks(callback=self.generate_list) # Extra Object Creation self.main_window = main_window @@ -107,8 +113,7 @@ class PackagesPage(Adw.BreakpointBin): self.loading_status = StatusBox(_("Fetching Packages"), _("This should only take a moment")) # Apply - HostInfo.get_flatpaks(callback=self.generate_list) - + self.set_status(self.loading_status) self.packages_list_box.set_filter_func(self.filter_func) self.content_stack.add_child(self.properties_page) self.content_stack.add_child(self.filters_page) @@ -126,4 +131,5 @@ class PackagesPage(Adw.BreakpointBin): self.select_button.connect("clicked", self.select_button_handler) self.filter_button.connect("toggled", self.filter_button_handler) self.packages_split.connect("notify::show-content", self.filter_page_handler) - self.packages_bpt.connect("apply", self.filter_page_handler) \ No newline at end of file + self.packages_bpt.connect("apply", self.filter_page_handler) + self.filter_button.set_active(True) \ No newline at end of file diff --git a/src/widgets/app_row.py b/src/widgets/app_row.py index a17a50d..0714d0f 100644 --- a/src/widgets/app_row.py +++ b/src/widgets/app_row.py @@ -12,17 +12,24 @@ class AppRow(Adw.ActionRow): masked_status_icon = gtc() check_button = gtc() - def __init__(self, package, **kwargs): + def idle_stuff(self): + if self.package.icon_path: + self.image.add_css_class("icon-dropshadow") + self.image.set_from_file(self.package.icon_path) + + if self.callback: + self.callback() + + def __init__(self, package, callback=None, **kwargs): super().__init__(**kwargs) # Extra Object Creation self.package = package + self.callback = callback # Apply GLib.idle_add(lambda *_: self.set_title(package.info["name"])) GLib.idle_add(lambda *_: self.set_subtitle(package.info["id"])) - if package.icon_path: - GLib.idle_add(lambda *_: self.image.add_css_class("icon-dropshadow")) - GLib.idle_add(lambda *_: self.image.set_from_file(package.icon_path)) + GLib.idle_add(lambda *_: self.idle_stuff()) # Connections \ No newline at end of file