diff --git a/src/meson.build b/src/meson.build index 42b6f37..1063bf1 100644 --- a/src/meson.build +++ b/src/meson.build @@ -73,8 +73,9 @@ warehouse_sources = [ 'gtk/error_toast.py', 'gtk/sidebar_button.py', 'gtk/loading_status.py', - 'main_window/window.py', 'gtk/app_row.py', + 'main_window/window.py', + 'package_install_worker.py', 'packages_page/uninstall_dialog.py', 'packages_page/packages_page.py', 'packages_page/filters_page.py', diff --git a/src/package_install_worker.py b/src/package_install_worker.py new file mode 100644 index 0000000..7f66eed --- /dev/null +++ b/src/package_install_worker.py @@ -0,0 +1,47 @@ +from gi.repository import Adw, Gtk, GLib, Gio + +class PackageInstallWorker: + process = None + + @classmethod + def update_status(this, loading_status, ratio, complete=None, total=None): + GLib.idle_add(lambda *_: loading_status.progress_bar.set_fraction(ratio)) + if (not complete is None) and (not total is None): + GLib.idle_add(lambda *_: loading_status.progress_label.set_label(f'{int(ratio + complete / total)} / {total}')) + elif loading_status.progress_label.get_visible(): + GLib.idle_add(lambda *_: loading_status.progress_label.set_visible(False)) + + @classmethod + def install_thread(this, loading_status, remote, installation, names, on_error): + this.process = subprocess.Popen( + ['flatpak-spawn', '--host', 'flatpak', 'install', f'--installation={installation}', names], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + percent_pattern = r'\d{1,3}%' + amount_pattern = r'(\d+)/(\d+)' + for line in this.process.stdout: + line = line.strip() + + percent_match = re.search(percent_pattern, line) + if percent_match: + ratio = int(percent_match.group()[0:-1]) / 100.0 + + amount_match = re.search(amount_pattern, line) + if amount_match: + amount = amount_match.group().split('/') + complete = int(amount[0]) - 1 + total = int(amount[1]) + this.update_status(loading_status, ratio, complete, total) + else: + this.update_status(loading_status, ratio) + + this.process = None + + @classmethod + def install(this, loading_status, remote, installation, names, callback=None, on_error=None): + if not this.process is None: + return "error, already installing something" + + Gio.Task.new(None, None, callback).run_in_thread(this.install_thread, loading_status, remote, installation, names, on_error) + return ""