diff --git a/src/window.py b/src/window.py index 5f4c83f..a0ee4ca 100644 --- a/src/window.py +++ b/src/window.py @@ -16,16 +16,18 @@ # # SPDX-License-Identifier: GPL-3.0-only -from gi.repository import GLib, Gtk, Adw, Gdk, Gio -from .show_properties_window import show_properties_window -import subprocess -import pathlib -import shutil import os +import pathlib +import subprocess -@Gtk.Template(resource_path='/io/github/heliguy4599/FlattoolGUI/window.ui') +from gi.repository import Adw, Gdk, Gio, GLib, Gtk + +from .show_properties_window import show_properties_window + + +@Gtk.Template(resource_path="/io/github/heliguy4599/FlattoolGUI/window.ui") class FlattoolGuiWindow(Adw.ApplicationWindow): - __gtype_name__ = 'FlattoolGuiWindow' + __gtype_name__ = "FlattoolGuiWindow" main_window_title = "Flattool" list_of_flatpaks = Gtk.Template.Child() search_entry = Gtk.Template.Child() @@ -51,40 +53,48 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): in_batch_mode = False should_select_all = False host_flatpaks = None + uninstall_success = True + install_success = True icon_theme = Gtk.IconTheme.new() icon_theme.add_search_path("/var/lib/flatpak/exports/share/icons/") icon_theme.add_search_path(host_home + "/.local/share/flatpak/exports/share/icons") - #host_flatpak_ids = subprocess.run(['flatpak-spawn', '--host', 'flatpak', 'list', '--columns=application'], capture_output=True, encoding="utf-8").stdout.split("\n")[:-1] - #host_flatpak_names = subprocess.run(['flatpak-spawn', '--host', 'flatpak', 'list', '--columns=name'], capture_output=True, encoding="utf-8").stdout.split("\n")[:-1] - #host_flatpak_runtime_ids = subprocess.run(['flatpak-spawn', '--host', 'flatpak', 'list', '--columns=application', '--runtime'], capture_output=True, encoding="utf-8").stdout.split("\n")[:-1] + # host_flatpak_ids = subprocess.run(['flatpak-spawn', '--host', 'flatpak', 'list', '--columns=application'], capture_output=True, encoding="utf-8").stdout.split("\n")[:-1] + # host_flatpak_names = subprocess.run(['flatpak-spawn', '--host', 'flatpak', 'list', '--columns=name'], capture_output=True, encoding="utf-8").stdout.split("\n")[:-1] + # host_flatpak_runtime_ids = subprocess.run(['flatpak-spawn', '--host', 'flatpak', 'list', '--columns=application', '--runtime'], capture_output=True, encoding="utf-8").stdout.split("\n")[:-1] def delete_row(self, widget, row): self.list_of_flatpaks.remove(row) def filter_func(self, row): - if (self.search_entry.get_text().lower() in row.get_title().lower()) or (self.search_entry.get_text().lower() in row.get_subtitle().lower()): + if (self.search_entry.get_text().lower() in row.get_title().lower()) or ( + self.search_entry.get_text().lower() in row.get_subtitle().lower() + ): return True - def trash_folder(_a, path): + def trash_folder(self, _a, path): if not os.path.exists(path): - return(1) + return 1 try: - subprocess.run(['flatpak-spawn', '--host', 'gio', 'trash', path], capture_output=True, check=True) - return(0) + subprocess.run( + ["flatpak-spawn", "--host", "gio", "trash", path], + capture_output=True, + check=True, + ) + return 0 except subprocess.CalledProcessError: - return(2) + return 2 def get_size_format(self, b): - factor=1024 - suffix="B" + factor = 1024 + suffix = "B" for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]: if b < factor: return f"{b:.1f}{unit}{suffix}" b /= factor return f"{b:.1f}{suffix}" - + def get_directory_size(self, directory): """Returns the `directory` size in bytes.""" total = 0 @@ -92,7 +102,7 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): # print("[+] Getting the size of", directory) for entry in os.scandir(directory): if entry.is_symlink(): - continue # Skip symlinks + continue # Skip symlinks if entry.is_file(): # if it's a file, use stat() function total += entry.stat().st_size @@ -113,32 +123,55 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): def uninstall_response(self, widget, response_id, _c, index): ref = self.host_flatpaks[index][8] name = self.host_flatpaks[index][0] - command = ['flatpak-spawn', '--host', 'flatpak', 'remove', ref, '-y'] + command = ["flatpak-spawn", "--host", "flatpak", "remove", ref, "-y"] if response_id == "cancel": self.main_stack.set_visible_child(self.main_box) - return(1) + return 1 if response_id == "purge": - command.append('--delete-data') - try: - subprocess.run(command, capture_output=True, check=True) - self.toast_overlay.add_toast(Adw.Toast.new(("Uninstalled {}").format(name))) - self.refresh_list_of_flatpaks(self, False) - except subprocess.CalledProcessError: - self.toast_overlay.add_toast(Adw.Toast.new(("Can't uninstall {}").format(name))) - self.main_stack.set_visible_child(self.main_box) + command.append("--delete-data") + + def uninstall_callback(*_args): + self.toast_overlay.add_toast( + Adw.Toast.new( + _("Uninstalled {}").format(name) + if self.uninstall_success + else _("Can't uninstall {}").format(name) + ) + ) + self.refresh_list_of_flatpaks(None, False) + self.main_stack.set_visible_child(self.main_box) + + def thread_func(*_args): + try: + subprocess.run(command, capture_output=True, check=True) + self.uninstall_success = True + + except subprocess.CalledProcessError: + self.uninstall_success = False + + task = Gio.Task.new(None, None, uninstall_callback) + task.run_in_thread(thread_func) def uninstall_flatpak(self, _widget, index): self.main_stack.set_visible_child(self.uninstall_please_wait) name = self.host_flatpaks[index][0] id = self.host_flatpaks[index][2] - dialog = Adw.MessageDialog.new(self, ("Uninstall {}?").format(name), _("The app will be removed from your system.")) + dialog = Adw.MessageDialog.new( + self, + ("Uninstall {}?").format(name), + _("The app will be removed from your system."), + ) dialog.set_close_response("cancel") dialog.add_response("cancel", _("Cancel")) dialog.add_response("continue", _("Uninstall")) dialog.set_response_appearance("continue", Adw.ResponseAppearance.DESTRUCTIVE) if os.path.exists(f"{self.user_data_path}{id}"): - dialog.set_body(_("The app will be removed from your system. Optionally, you can also trash its user data.")) + dialog.set_body( + _( + "The app will be removed from your system. Optionally, you can also trash its user data." + ) + ) dialog.add_response("purge", _("Uninstall and Trash Data")) dialog.set_response_appearance("purge", Adw.ResponseAppearance.DESTRUCTIVE) @@ -150,7 +183,7 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): window_title = _("Manage Leftover Data") orphans_window = Adw.Window(title=window_title) orphans_window.set_default_size(350, 400) - #orphans_window.set_size_request(250, 0) + # orphans_window.set_size_request(250, 0) orphans_window.set_modal(True) orphans_window.set_resizable(True) orphans_window.set_transient_for(self) @@ -162,18 +195,34 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): orphans_overlay = Gtk.Overlay() orphans_scroll.set_child(orphans_overlay) orphans_toolbar_view = Adw.ToolbarView() - #orphans_toolbar = Gtk.HeaderBar(show_title_buttons=False) + # orphans_toolbar = Gtk.HeaderBar(show_title_buttons=False) orphans_title_bar = Gtk.HeaderBar() orphans_action_bar = Gtk.ActionBar() orphans_toolbar_view.add_top_bar(orphans_title_bar) orphans_toolbar_view.add_bottom_bar(orphans_action_bar) orphans_toolbar_view.set_content(orphans_toast_overlay) orphans_window.set_content(orphans_toolbar_view) - orphans_list = Gtk.ListBox(selection_mode="none", valign=Gtk.Align.START, margin_top=6, margin_bottom=6, margin_start=12, margin_end=12) + orphans_list = Gtk.ListBox( + selection_mode="none", + valign=Gtk.Align.START, + margin_top=6, + margin_bottom=6, + margin_start=12, + margin_end=12, + ) orphans_list.add_css_class("boxed-list") orphans_overlay.set_child(orphans_list) - no_data = Adw.StatusPage(icon_name="check-plain-symbolic", title=_("No Data"), description=_("There is no leftover user data")) - installing_please_wait = Adw.StatusPage(title=_("Please Wait"), description=_("Flattool is attempting to install the selected apps. This could take a while.")) + no_data = Adw.StatusPage( + icon_name="check-plain-symbolic", + title=_("No Data"), + description=_("There is no leftover user data"), + ) + installing_please_wait = Adw.StatusPage( + title=_("Please Wait"), + description=_( + "Flattool is attempting to install the selected apps. This could take a while." + ), + ) orphans_stack.add_child(installing_please_wait) orphans_stack.add_child(no_data) global total_selected @@ -209,10 +258,20 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): if not file_list[i] in id_list: row_index += 1 select_orphans_tickbox = Gtk.CheckButton(halign=Gtk.Align.CENTER) - orphans_row = Adw.ActionRow(title=GLib.markup_escape_text(file_list[i]), subtitle=_("~") + self.get_size_format(self.get_directory_size(f"{self.user_data_path}{file_list[i]}"))) + orphans_row = Adw.ActionRow( + title=GLib.markup_escape_text(file_list[i]), + subtitle=_("~") + + self.get_size_format( + self.get_directory_size( + f"{self.user_data_path}{file_list[i]}" + ) + ), + ) orphans_row.add_suffix(select_orphans_tickbox) orphans_row.set_activatable_widget(select_orphans_tickbox) - select_orphans_tickbox.connect("toggled", selection_handler, orphans_row.get_title()) + select_orphans_tickbox.connect( + "toggled", selection_handler, orphans_row.get_title() + ) if is_select_all == True: select_orphans_tickbox.set_active(True) orphans_list.append(orphans_row) @@ -228,14 +287,20 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): def trash_button_handler(widget): if total_selected == 0: - return(1) + return 1 show_success = True for i in range(len(selected_rows)): path = f"{self.user_data_path}{selected_rows[i]}" try: - subprocess.run(['flatpak-spawn', '--host', 'gio', 'trash', path], capture_output=False, check=True) + subprocess.run( + ["flatpak-spawn", "--host", "gio", "trash", path], + capture_output=False, + check=True, + ) except: - orphans_toast_overlay.add_toast(Adw.Toast.new(_("Can't trash {}").format(selected_rows[i]))) + orphans_toast_overlay.add_toast( + Adw.Toast.new(_("Can't trash {}").format(selected_rows[i])) + ) show_success = False select_all_button.set_active(False) @@ -244,62 +309,95 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): generate_list(widget, False) + def install_callback(*_args): + orphans_toast_overlay.add_toast( + Adw.Toast.new( + _("Installed all apps") + if self.install_success + else _("Can't install selected apps") + ) + ) + + select_all_button.set_active(False) + orphans_stack.set_visible_child(orphans_scroll) + + self.refresh_list_of_flatpaks(None, False) + generate_list(None, False) + + def thread_func(command): + try: + subprocess.run(command, capture_output=False, check=True) + self.install_success = True + except subprocess.CalledProcessError: + self.install_success = False + def install_on_response(_a, response_id, _b): if response_id == "cancel": orphans_stack.set_visible_child(orphans_scroll) - return(1) - - show_success = True + return 1 + for i in range(len(selected_rows)): - remote = response_id.split('_') - command = ['flatpak-spawn', '--host', 'flatpak', 'installd', '-y', remote[0]] + remote = response_id.split("_") + command = [ + "flatpak-spawn", + "--host", + "flatpak", + "install", + "-y", + remote[0], + ] if "user" in remote[1]: command.append("--user") else: command.append("--system") command.append(selected_rows[i]) - - try: - subprocess.run(command, capture_output=False, check=True) - except: - orphans_toast_overlay.add_toast(Adw.Toast.new(_("Can't install {}").format(selected_rows[i]))) - show_success = False - select_all_button.set_active(False) - orphans_stack.set_visible_child(orphans_scroll) - - if show_success: - orphans_toast_overlay.add_toast(Adw.Toast.new(_("Installed all apps"))) - - self.refresh_list_of_flatpaks(None, False) - generate_list(None, False) + task = Gio.Task.new(None, None, install_callback) + task.run_in_thread( + lambda _task, _obj, _data, _cancellable, cmd=command: thread_func(cmd) + ) def install_button_handler(widget): orphans_stack.set_visible_child(installing_please_wait) + def get_host_remotes(): - output = subprocess.run(['flatpak-spawn', '--host', 'flatpak', 'remotes'], capture_output=True, text=True).stdout - lines = output.strip().split('\n') - columns = lines[0].split('\t') + output = subprocess.run( + ["flatpak-spawn", "--host", "flatpak", "remotes"], + capture_output=True, + text=True, + ).stdout + lines = output.strip().split("\n") + columns = lines[0].split("\t") data = [columns] for line in lines[1:]: - row = line.split('\t') + row = line.split("\t") data.append(row) - return(data) + return data host_remotes = get_host_remotes() - + dialog = Adw.MessageDialog.new(self, _("Choose a Remote")) dialog.set_close_response("cancel") dialog.add_response("cancel", _("Cancel")) dialog.connect("response", install_on_response, dialog.choose_finish) dialog.set_transient_for(orphans_window) if len(host_remotes) > 1: - dialog.set_body(_("Choose the Flatpak Remote Repository where attempted app downloads will be from.")) + dialog.set_body( + _( + "Choose the Flatpak Remote Repository where attempted app downloads will be from." + ) + ) for i in range(len(host_remotes)): remote_name = host_remotes[i][0] remote_option = host_remotes[i][1] - dialog.add_response(f"{remote_name}_{remote_option}", f"{remote_name} {remote_option}") - dialog.set_response_appearance(f"{remote_name}_{remote_option}", Adw.ResponseAppearance.SUGGESTED) + dialog.add_response( + f"{remote_name}_{remote_option}", + f"{remote_name} {remote_option}", + ) + dialog.set_response_appearance( + f"{remote_name}_{remote_option}", + Adw.ResponseAppearance.SUGGESTED, + ) else: remote_name = host_remotes[0][0] remote_option = host_remotes[0][1] @@ -315,16 +413,26 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): select_all_button.connect("toggled", toggle_button_handler) orphans_action_bar.pack_start(select_all_button) - trash_button = Gtk.Button(label="Trash", valign=Gtk.Align.CENTER, tooltip_text=_("Trash Selected")) + trash_button = Gtk.Button( + label="Trash", valign=Gtk.Align.CENTER, tooltip_text=_("Trash Selected") + ) trash_button.add_css_class("destructive-action") trash_button.connect("clicked", trash_button_handler) orphans_action_bar.pack_end(trash_button) - install_button = Gtk.Button(label="Install", valign=Gtk.Align.CENTER, tooltip_text=_("Attempt to Install Selected")) + install_button = Gtk.Button( + label="Install", + valign=Gtk.Align.CENTER, + tooltip_text=_("Attempt to Install Selected"), + ) install_button.connect("clicked", install_button_handler) install_button.set_visible(False) orphans_action_bar.pack_end(install_button) - test = subprocess.run(['flatpak-spawn', '--host', 'flatpak', 'remotes'], capture_output=True, text=True).stdout + test = subprocess.run( + ["flatpak-spawn", "--host", "flatpak", "remotes"], + capture_output=True, + text=True, + ).stdout for char in test: if char.isalnum(): install_button.set_visible(True) @@ -337,9 +445,9 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): selected_rows.append(file) else: total_selected -= 1 - to_find = (file) + to_find = file selected_rows.remove(to_find) - + if total_selected == 0: orphans_window.set_title(window_title) trash_button.set_sensitive(False) @@ -357,34 +465,46 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): def find_app_icon(self, app_id): try: - icon_path = self.icon_theme.lookup_icon(app_id, None, 512, 1, self.get_direction(), 0).get_file().get_path() + icon_path = ( + self.icon_theme.lookup_icon( + app_id, None, 512, 1, self.get_direction(), 0 + ) + .get_file() + .get_path() + ) except GLib.GError: icon_path = None if icon_path: - image=Gtk.Image.new_from_file(icon_path) + image = Gtk.Image.new_from_file(icon_path) image.set_icon_size(Gtk.IconSize.LARGE) image.add_css_class("icon-dropshadow") else: - image=Gtk.Image.new_from_icon_name("application-x-executable-symbolic") + image = Gtk.Image.new_from_icon_name("application-x-executable-symbolic") image.set_icon_size(Gtk.IconSize.LARGE) - return(image) + return image def generate_list_of_flatpaks(self): self.set_title(self.main_window_title) self.batch_actions_enable(False) self.selected_host_flatpak_indexes = [] self.should_select_all = self.batch_select_all_button.get_active() + def get_host_flatpaks(): - output = subprocess.run(['flatpak-spawn', '--host', 'flatpak', 'list', '--columns=all'], capture_output=True, text=True).stdout - lines = output.strip().split('\n') - columns = lines[0].split('\t') + output = subprocess.run( + ["flatpak-spawn", "--host", "flatpak", "list", "--columns=all"], + capture_output=True, + text=True, + ).stdout + lines = output.strip().split("\n") + columns = lines[0].split("\t") data = [columns] for line in lines[1:]: - row = line.split('\t') + row = line.split("\t") data.append(row) - return(data) + return data + self.host_flatpaks = get_host_flatpaks() - if self.host_flatpaks == [['']]: + if self.host_flatpaks == [[""]]: self.main_stack.set_visible_child(self.no_flatpaks) self.search_button.set_visible(False) self.search_bar.set_visible(False) @@ -395,12 +515,13 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): app_name = self.host_flatpaks[index][0] app_id = self.host_flatpaks[index][2] app_ref = self.host_flatpaks[index][8] - flatpak_row = Adw.ActionRow(title=GLib.markup_escape_text(app_name), subtitle=app_ref) + flatpak_row = Adw.ActionRow( + title=GLib.markup_escape_text(app_name), subtitle=app_ref + ) flatpak_row.add_prefix(self.find_app_icon(app_id)) if (not self.show_runtimes) and "runtime" in self.host_flatpaks[index][12]: continue - if os.path.exists(f"{self.user_data_path}{app_id}"): has_data_icon = Gtk.Image.new_from_icon_name("paper-filled-symbolic") @@ -409,19 +530,29 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): has_data_icon.set_margin_end(10) flatpak_row.add_suffix(has_data_icon) - trash_button = Gtk.Button(icon_name="user-trash-symbolic", valign=Gtk.Align.CENTER, tooltip_text=_("Uninstall {}").format(app_name)) + trash_button = Gtk.Button( + icon_name="user-trash-symbolic", + valign=Gtk.Align.CENTER, + tooltip_text=_("Uninstall {}").format(app_name), + ) trash_button.add_css_class("flat") trash_button.connect("clicked", self.uninstall_flatpak, index) flatpak_row.add_suffix(trash_button) - properties_button = Gtk.Button(icon_name="info-symbolic", valign=Gtk.Align.CENTER, tooltip_text=_("View Properties")) + properties_button = Gtk.Button( + icon_name="info-symbolic", + valign=Gtk.Align.CENTER, + tooltip_text=_("View Properties"), + ) properties_button.add_css_class("flat") properties_button.connect("clicked", show_properties_window, index, self) flatpak_row.add_suffix(properties_button) select_flatpak_tickbox = Gtk.CheckButton(halign=Gtk.Align.CENTER) select_flatpak_tickbox.add_css_class("flat") - select_flatpak_tickbox.connect("toggled", self.flatpak_row_select_handler, index) + select_flatpak_tickbox.connect( + "toggled", self.flatpak_row_select_handler, index + ) flatpak_row.add_suffix(select_flatpak_tickbox) if self.in_batch_mode: @@ -433,7 +564,7 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): else: select_flatpak_tickbox.set_visible(False) self.batch_mode_bar.set_revealed(False) - + self.list_of_flatpaks.append(flatpak_row) def refresh_list_of_flatpaks(self, widget, should_toast): @@ -441,13 +572,13 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): self.generate_list_of_flatpaks() if should_toast: self.toast_overlay.add_toast(Adw.Toast.new(_("List refreshed"))) - + def show_runtimes_toggle_handler(self, state): if state: self.show_runtimes = True else: self.show_runtimes = False - self.refresh_list_of_flatpaks(self, False) + self.refresh_list_of_flatpaks(None, False) self.selected_host_flatpak_indexes.clear() def batch_mode_handler(self, widget): @@ -456,7 +587,7 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): self.in_batch_mode = True else: self.in_batch_mode = False - self.refresh_list_of_flatpaks(self, False) + self.refresh_list_of_flatpaks(None, False) self.batch_actions_enable(False) def batch_actions_enable(self, should_enable): @@ -474,25 +605,33 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): def on_batch_clean_response(self, dialog, response, _a): if response == "cancel": - return(1) + return 1 show_success = True for i in range(len(self.selected_host_flatpak_indexes)): app_id = self.host_flatpaks[self.selected_host_flatpak_indexes[i]][2] app_name = self.host_flatpaks[self.selected_host_flatpak_indexes[i]][0] path = f"{self.user_data_path}{app_id}" - trash = self.trash_folder(path) + trash = self.trash_folder(None, path) if trash == 1: show_success = False - self.toast_overlay.add_toast(Adw.Toast.new(_("No user data for {}").format(app_name))) + self.toast_overlay.add_toast( + Adw.Toast.new(_("No user data for {}").format(app_name)) + ) elif trash == 2: show_success = False - self.toast_overlay.add_toast(Adw.Toast.new(_("Can't trash user data for {}").format(app_name))) + self.toast_overlay.add_toast( + Adw.Toast.new(_("Can't trash user data for {}").format(app_name)) + ) if show_success: self.toast_overlay.add_toast(Adw.Toast.new(_("Trashed user data"))) self.refresh_list_of_flatpaks(_a, False) def batch_clean_handler(self, widget): - dialog = Adw.MessageDialog.new(self, _("Delete Selected User Data?"), _("This user data will be sent to the trash.")) + dialog = Adw.MessageDialog.new( + self, + _("Delete Selected User Data?"), + _("This user data will be sent to the trash."), + ) dialog.set_close_response("cancel") dialog.add_response("cancel", _("Cancel")) dialog.add_response("continue", _("Trash Data")) @@ -509,36 +648,44 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): app_id = self.host_flatpaks[self.selected_host_flatpak_indexes[i]][2] ref = self.host_flatpaks[self.selected_host_flatpak_indexes[i]][8] name = self.host_flatpaks[self.selected_host_flatpak_indexes[i]][0] - command = ['flatpak-spawn', '--host', 'flatpak', 'remove', ref, '-y'] + command = ["flatpak-spawn", "--host", "flatpak", "remove", ref, "-y"] if response_id == "cancel": - return(1) + return 1 if response_id == "purge": - command.append('--delete-data') - + command.append("--delete-data") + try: subprocess.run(command, capture_output=False, check=True) except subprocess.CalledProcessError: - self.toast_overlay.add_toast(Adw.Toast.new(_("Can't uninstall {}").format(name))) + self.toast_overlay.add_toast( + Adw.Toast.new(_("Can't uninstall {}").format(name)) + ) self.toast_overlay.add_toast(Adw.Toast.new(_("Uninstalled apps"))) self.batch_select_all_button.set_active(False) - self.refresh_list_of_flatpaks(self, False) + self.refresh_list_of_flatpaks(None, False) def batch_uninstall_handler(self, widget): - dialog = Adw.MessageDialog.new(self, _("Uninstall Selected Apps?"), _("Optionally, you can also trash their user data")) + dialog = Adw.MessageDialog.new( + self, + _("Uninstall Selected Apps?"), + _("Optionally, you can also trash their user data"), + ) dialog.set_close_response("cancel") dialog.add_response("cancel", _("Cancel")) dialog.add_response("continue", _("Uninstall")) dialog.add_response("purge", _("Uninstall and Trash Data")) dialog.set_response_appearance("continue", Adw.ResponseAppearance.DESTRUCTIVE) dialog.set_response_appearance("purge", Adw.ResponseAppearance.DESTRUCTIVE) - dialog.connect("response", self.batch_uninstall_on_response, dialog.choose_finish) + dialog.connect( + "response", self.batch_uninstall_on_response, dialog.choose_finish + ) Gtk.Window.present(dialog) def batch_key_handler(self, _b, event, _c, _d): if event == Gdk.KEY_Escape: self.batch_mode_button.set_active(False) - + def flatpak_row_select_handler(self, tickbox, index): if tickbox.get_active(): self.selected_host_flatpak_indexes.append(index) @@ -558,7 +705,9 @@ class FlattoolGuiWindow(Adw.ApplicationWindow): super().__init__(**kwargs) self.list_of_flatpaks.set_filter_func(self.filter_func) self.generate_list_of_flatpaks() - self.search_entry.connect("search-changed", lambda *_: self.list_of_flatpaks.invalidate_filter()) + self.search_entry.connect( + "search-changed", lambda *_: self.list_of_flatpaks.invalidate_filter() + ) self.search_bar.connect_entry(self.search_entry) self.refresh_button.connect("clicked", self.refresh_list_of_flatpaks, True) self.batch_mode_button.connect("toggled", self.batch_mode_handler)