Merge pull request 'clan_vm_manager: Fix vms not shutting down after closing GTK app. Sync JoinList with ClanStore' (#906) from Qubasa-main into main
This commit is contained in:
commit
1986ecc564
@ -49,7 +49,20 @@ class MainApplication(Adw.Application):
|
||||
)
|
||||
|
||||
self.window: Adw.ApplicationWindow | None = None
|
||||
self.connect("activate", self.show_window)
|
||||
self.connect("activate", self.on_activate)
|
||||
self.connect("shutdown", self.on_shutdown)
|
||||
|
||||
def on_shutdown(self, *_args: Any) -> None:
|
||||
log.debug("Shutting down Adw.Application")
|
||||
log.debug(f"get_windows: {self.get_windows()}")
|
||||
if self.window:
|
||||
# TODO: Doesn't seem to raise the destroy signal. Need to investigate
|
||||
# self.get_windows() returns an empty list. Desync between window and application?
|
||||
self.window.close()
|
||||
# Killing vms directly. This is dirty
|
||||
self.window.kill_vms()
|
||||
else:
|
||||
log.error("No window to destroy")
|
||||
|
||||
def do_command_line(self, command_line: Any) -> int:
|
||||
options = command_line.get_options_dict()
|
||||
@ -74,7 +87,9 @@ class MainApplication(Adw.Application):
|
||||
return 0
|
||||
|
||||
def on_window_hide_unhide(self, *_args: Any) -> None:
|
||||
assert self.window is not None
|
||||
if not self.window:
|
||||
log.error("No window to hide/unhide")
|
||||
return
|
||||
if self.window.is_visible():
|
||||
self.window.hide()
|
||||
else:
|
||||
@ -83,13 +98,13 @@ class MainApplication(Adw.Application):
|
||||
def dummy_menu_entry(self) -> None:
|
||||
log.info("Dummy menu entry called")
|
||||
|
||||
def show_window(self, *_args: Any) -> None:
|
||||
def on_activate(self, app: Any) -> None:
|
||||
if not self.window:
|
||||
self.init_style()
|
||||
self.window = MainWindow(config=ClanConfig(initial_view="list"))
|
||||
self.window.set_application(self)
|
||||
|
||||
self.window.present()
|
||||
self.window.show()
|
||||
|
||||
# TODO: For css styling
|
||||
def init_style(self) -> None:
|
||||
|
@ -79,6 +79,8 @@ class ProfilerStore:
|
||||
print("=" * 7 + key + "=" * 7)
|
||||
print_profile(profiler, pstats.SortKey.TIME)
|
||||
print_profile(profiler, pstats.SortKey.CUMULATIVE)
|
||||
|
||||
if len(self.profilers) > 0:
|
||||
print(explanation)
|
||||
|
||||
|
||||
@ -108,9 +110,8 @@ def profile(func: Callable) -> Callable:
|
||||
res = func(*args, **kwargs)
|
||||
profiler.disable()
|
||||
except Exception as ex:
|
||||
log.exception(ex)
|
||||
profiler.disable()
|
||||
return None
|
||||
raise ex
|
||||
return res
|
||||
|
||||
if os.getenv("PERF", "0") == "1":
|
||||
|
@ -37,6 +37,9 @@ class VMObject(GObject.Object):
|
||||
self.emit("vm_status_changed", self)
|
||||
return GLib.SOURCE_REMOVE
|
||||
|
||||
def update(self, data: HistoryEntry) -> None:
|
||||
self.data = data
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
icon: Path,
|
||||
@ -296,6 +299,7 @@ class VMObject(GObject.Object):
|
||||
return
|
||||
log.info(f"Killing VM {self.get_id()} now")
|
||||
self.vm_process.kill_group()
|
||||
self.build_process.kill_group()
|
||||
|
||||
def read_whole_log(self) -> str:
|
||||
if not self.vm_process.out_file.exists():
|
||||
|
@ -63,19 +63,31 @@ class JoinList:
|
||||
cls._instance = cls.__new__(cls)
|
||||
cls.list_store = Gio.ListStore.new(JoinValue)
|
||||
|
||||
# Rerendering the join list every time an item changes in the clan_store
|
||||
ClanStore.use().clan_store.connect(
|
||||
"items-changed", cls._instance.on_clan_store_items_changed
|
||||
)
|
||||
return cls._instance
|
||||
|
||||
def on_clan_store_items_changed(
|
||||
self, source: Any, position: int, removed: int, added: int
|
||||
) -> None:
|
||||
self.list_store.items_changed(
|
||||
0, self.list_store.get_n_items(), self.list_store.get_n_items()
|
||||
)
|
||||
|
||||
def is_empty(self) -> bool:
|
||||
return self.list_store.get_n_items() == 0
|
||||
|
||||
def push(
|
||||
self, value: JoinValue, after_join: Callable[[JoinValue, JoinValue], None]
|
||||
self, uri: ClanURI, after_join: Callable[[JoinValue, JoinValue], None]
|
||||
) -> None:
|
||||
"""
|
||||
Add a join request.
|
||||
This method can add multiple join requests if called subsequently for each request.
|
||||
"""
|
||||
|
||||
value = JoinValue(uri)
|
||||
if value.url.get_id() in [item.url.get_id() for item in self.list_store]:
|
||||
log.info(f"Join request already exists: {value.url}. Ignoring.")
|
||||
return
|
||||
|
@ -63,7 +63,7 @@ class ClanStore:
|
||||
def push(self, vm: VMObject) -> None:
|
||||
url = vm.data.flake.flake_url
|
||||
|
||||
# Only write to the store if the VM is not already in it
|
||||
# Only write to the store if the Clan is not already in it
|
||||
# Every write to the KVStore rerenders bound widgets to the clan_store
|
||||
if url not in self.clan_store:
|
||||
log.debug(f"Creating new VMStore for {url}")
|
||||
@ -71,8 +71,17 @@ class ClanStore:
|
||||
vm_store.append(vm)
|
||||
self.clan_store[url] = vm_store
|
||||
else:
|
||||
log.debug(f"Appending VM {vm.data.flake.flake_attr} to store")
|
||||
vm_store = self.clan_store[url]
|
||||
machine = vm.data.flake.flake_attr
|
||||
old_vm = vm_store.get(machine)
|
||||
|
||||
if old_vm:
|
||||
log.info(
|
||||
f"VM {vm.data.flake.flake_attr} already exists in store. Updating data field."
|
||||
)
|
||||
old_vm.update(vm.data)
|
||||
else:
|
||||
log.debug(f"Appending VM {vm.data.flake.flake_attr} to store")
|
||||
vm_store.append(vm)
|
||||
|
||||
def remove(self, vm: VMObject) -> None:
|
||||
|
@ -184,13 +184,15 @@ class ClanList(Gtk.Box):
|
||||
if boxed_list.has_css_class("no-shadow"):
|
||||
boxed_list.remove_css_class("no-shadow")
|
||||
|
||||
row = Adw.ActionRow()
|
||||
log.debug("Rendering join row for %s", item.url)
|
||||
|
||||
row = Adw.ActionRow()
|
||||
row.set_title(item.url.params.flake_attr)
|
||||
row.set_subtitle(item.url.get_internal())
|
||||
row.add_css_class("trust")
|
||||
|
||||
if item.url.params.flake_attr in ClanStore.use().clan_store:
|
||||
# Can't do this here because clan store is empty at this point
|
||||
if item.url.get_internal() in ClanStore.use().clan_store:
|
||||
sub = row.get_subtitle()
|
||||
row.set_subtitle(
|
||||
sub + "\nClan already exists. Joining again will update it"
|
||||
@ -223,8 +225,7 @@ class ClanList(Gtk.Box):
|
||||
def on_join_request(self, widget: Any, url: str) -> None:
|
||||
log.debug("Join request: %s", url)
|
||||
clan_uri = ClanURI.from_str(url)
|
||||
value = JoinValue(url=clan_uri)
|
||||
JoinList.use().push(value, self.on_after_join)
|
||||
JoinList.use().push(clan_uri, self.on_after_join)
|
||||
|
||||
def on_after_join(self, source: JoinValue, item: JoinValue) -> None:
|
||||
# If the join request list is empty disable the shadow artefact
|
||||
|
@ -65,6 +65,11 @@ class MainWindow(Adw.ApplicationWindow):
|
||||
for entry in list_history():
|
||||
GLib.idle_add(ClanStore.use().create_vm_task, entry)
|
||||
|
||||
def on_destroy(self, *_args: Any) -> None:
|
||||
self.tray_icon.destroy()
|
||||
def kill_vms(self) -> None:
|
||||
log.debug("Killing all VMs")
|
||||
ClanStore.use().kill_all()
|
||||
|
||||
def on_destroy(self, *_args: Any) -> None:
|
||||
log.info("====Destroying Adw.ApplicationWindow===")
|
||||
ClanStore.use().kill_all()
|
||||
self.tray_icon.destroy()
|
||||
|
Loading…
Reference in New Issue
Block a user