From de919387604a32bff4f150b59b260891903d7e46 Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Wed, 3 Apr 2024 11:36:33 +0200 Subject: [PATCH] Clan VM Manager: connect feedback with events --- pkgs/clan-vm-manager/clan_vm_manager/app.py | 7 ++++++ .../clan_vm_manager/components/vmobj.py | 25 ++++++++++++++++++- .../clan_vm_manager/singletons/toast.py | 14 +++++++++++ .../clan_vm_manager/views/list.py | 5 ++++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/pkgs/clan-vm-manager/clan_vm_manager/app.py b/pkgs/clan-vm-manager/clan_vm_manager/app.py index a1ce1230..f0278faf 100644 --- a/pkgs/clan-vm-manager/clan_vm_manager/app.py +++ b/pkgs/clan-vm-manager/clan_vm_manager/app.py @@ -5,6 +5,7 @@ from typing import Any, ClassVar import gi from clan_vm_manager import assets +from clan_vm_manager.singletons.toast import InfoToast, ToastOverlay gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") @@ -52,6 +53,7 @@ class MainApplication(Adw.Application): def on_shutdown(self, source: "MainApplication") -> None: log.debug("Shutting down Adw.Application") + if self.get_windows() == []: log.warning("No windows to destroy") if self.window: @@ -75,6 +77,11 @@ class MainApplication(Adw.Application): setup_logging(logging.INFO, root_log_name=__name__.split(".")[0]) log.debug("Debug logging enabled") + if "debug" in options: + ToastOverlay.use().add_toast_unique( + InfoToast("Debug logging enabled").toast, "info.debugging.enabled" + ) + args = command_line.get_arguments() self.activate() diff --git a/pkgs/clan-vm-manager/clan_vm_manager/components/vmobj.py b/pkgs/clan-vm-manager/clan_vm_manager/components/vmobj.py index aa613e1e..474c2298 100644 --- a/pkgs/clan-vm-manager/clan_vm_manager/components/vmobj.py +++ b/pkgs/clan-vm-manager/clan_vm_manager/components/vmobj.py @@ -18,6 +18,12 @@ from clan_cli.history.add import HistoryEntry from clan_cli.machines.machines import Machine from clan_vm_manager.components.executor import MPProcess, spawn +from clan_vm_manager.singletons.toast import ( + InfoToast, + SuccessToast, + ToastOverlay, + WarningToast, +) gi.require_version("GObject", "2.0") gi.require_version("Gtk", "4.0") @@ -96,7 +102,16 @@ class VMObject(GObject.Object): # Signal may be emited multiple times self.emit("vm_build_notify", self.is_building(), self.is_running()) - self.switch.set_state(self.is_running() and not self.is_building()) + prev_state = self.switch.get_state() + next_state = self.is_running() and not self.is_building() + + self.switch.set_state(next_state) + if prev_state is False and next_state is True: + ToastOverlay.use().add_toast_unique( + SuccessToast(f"{source.data.flake.flake_attr} started").toast, + "success.vm.start", + ) + if self.switch.get_sensitive() is False and not self.is_building(): self.switch.set_sensitive(True) @@ -107,6 +122,10 @@ class VMObject(GObject.Object): with self.switch.handler_block(self.switch_handler_id): self.switch.set_active(False) log.error(f"VM exited with error. Exitcode: {exitc}") + ToastOverlay.use().add_toast_unique( + WarningToast(f"VM exited with error. Exitcode: {exitc}").toast, + "warning.vm.exit", + ) def _on_switch_toggle(self, switch: Gtk.Switch, user_state: bool) -> None: if switch.get_active(): @@ -310,6 +329,10 @@ class VMObject(GObject.Object): GLib.idle_add(self._vm_status_changed_task) log.debug(f"VM {self.get_id()} has stopped") + ToastOverlay.use().add_toast_unique( + InfoToast(f"Stopped {self.get_id()}").toast, "info.vm.exit" + ) + def shutdown(self) -> None: if not self.is_running(): log.warning("VM not running. Ignoring shutdown request.") diff --git a/pkgs/clan-vm-manager/clan_vm_manager/singletons/toast.py b/pkgs/clan-vm-manager/clan_vm_manager/singletons/toast.py index 13d5843c..ea735edc 100644 --- a/pkgs/clan-vm-manager/clan_vm_manager/singletons/toast.py +++ b/pkgs/clan-vm-manager/clan_vm_manager/singletons/toast.py @@ -94,6 +94,20 @@ class WarningToast: self.toast.set_timeout(0) +class InfoToast: + toast: Adw.Toast + + def __init__(self, message: str, persistent: bool = False) -> None: + super().__init__() + self.toast = Adw.Toast.new(f" {message}") + self.toast.set_use_markup(True) + + self.toast.set_priority(Adw.ToastPriority.NORMAL) + + if persistent: + self.toast.set_timeout(0) + + class SuccessToast: toast: Adw.Toast diff --git a/pkgs/clan-vm-manager/clan_vm_manager/views/list.py b/pkgs/clan-vm-manager/clan_vm_manager/views/list.py index 59377c73..44bffcc1 100644 --- a/pkgs/clan-vm-manager/clan_vm_manager/views/list.py +++ b/pkgs/clan-vm-manager/clan_vm_manager/views/list.py @@ -11,6 +11,7 @@ from clan_vm_manager.components.interfaces import ClanConfig from clan_vm_manager.components.vmobj import VMObject from clan_vm_manager.singletons.toast import ( LogToast, + SuccessToast, ToastOverlay, WarningToast, ) @@ -318,6 +319,10 @@ class ClanList(Gtk.Box): JoinList.use().push(clan_uri, self.on_after_join) def on_after_join(self, source: JoinValue) -> None: + ToastOverlay.use().add_toast_unique( + SuccessToast(f"Added/updated {source.url.machine.name}").toast, + "success.join", + ) # If the join request list is empty disable the shadow artefact if JoinList.use().is_empty(): self.join_boxed_list.add_css_class("no-shadow")