Merge pull request 'clan_vm_manager: Added suffix task to glib task functions' (#894) from Qubasa-main into main
This commit is contained in:
@@ -32,56 +32,19 @@ class GKVStore(GObject.GObject, Gio.ListModel, Generic[K, V]):
|
|||||||
self.key_gen = key_gen
|
self.key_gen = key_gen
|
||||||
self._items: "OrderedDict[K, V]" = OrderedDict()
|
self._items: "OrderedDict[K, V]" = OrderedDict()
|
||||||
|
|
||||||
|
##################################
|
||||||
|
# #
|
||||||
|
# Gio.ListStore Interface #
|
||||||
|
# #
|
||||||
|
##################################
|
||||||
@classmethod
|
@classmethod
|
||||||
def new(cls: Any, gtype: type[V]) -> "GKVStore":
|
def new(cls: Any, gtype: type[V]) -> "GKVStore":
|
||||||
return cls.__new__(cls, gtype)
|
return cls.__new__(cls, gtype)
|
||||||
|
|
||||||
#########################
|
def append(self, item: V) -> None:
|
||||||
# #
|
key = self.key_gen(item)
|
||||||
# READ OPERATIONS #
|
self[key] = item
|
||||||
# #
|
|
||||||
#########################
|
|
||||||
def keys(self) -> list[K]:
|
|
||||||
return list(self._items.keys())
|
|
||||||
|
|
||||||
def values(self) -> list[V]:
|
|
||||||
return list(self._items.values())
|
|
||||||
|
|
||||||
def items(self) -> list[tuple[K, V]]:
|
|
||||||
return list(self._items.items())
|
|
||||||
|
|
||||||
def get(self, key: K, default: V | None = None) -> V | None:
|
|
||||||
return self._items.get(key, default)
|
|
||||||
|
|
||||||
def get_n_items(self) -> int:
|
|
||||||
return len(self._items)
|
|
||||||
|
|
||||||
def do_get_n_items(self) -> int:
|
|
||||||
return self.get_n_items()
|
|
||||||
|
|
||||||
def get_item(self, position: int) -> V | None:
|
|
||||||
if position < 0 or position >= self.get_n_items():
|
|
||||||
return None
|
|
||||||
# Access items by index since OrderedDict does not support direct indexing
|
|
||||||
key = list(self._items.keys())[position]
|
|
||||||
return self._items[key]
|
|
||||||
|
|
||||||
def do_get_item(self, position: int) -> V | None:
|
|
||||||
return self.get_item(position)
|
|
||||||
|
|
||||||
def get_item_type(self) -> GObject.GType:
|
|
||||||
return self.gtype.__gtype__
|
|
||||||
|
|
||||||
def do_get_item_type(self) -> GObject.GType:
|
|
||||||
return self.get_item_type()
|
|
||||||
|
|
||||||
def first(self) -> V:
|
|
||||||
return self.values()[0]
|
|
||||||
|
|
||||||
def last(self) -> V:
|
|
||||||
return self.values()[-1]
|
|
||||||
|
|
||||||
# O(n) operation
|
|
||||||
def find(self, item: V) -> tuple[bool, int]:
|
def find(self, item: V) -> tuple[bool, int]:
|
||||||
log.warning("Finding is O(n) in GKVStore. Better use indexing")
|
log.warning("Finding is O(n) in GKVStore. Better use indexing")
|
||||||
for i, v in enumerate(self.values()):
|
for i, v in enumerate(self.values()):
|
||||||
@@ -89,11 +52,24 @@ class GKVStore(GObject.GObject, Gio.ListModel, Generic[K, V]):
|
|||||||
return True, i
|
return True, i
|
||||||
return False, -1
|
return False, -1
|
||||||
|
|
||||||
#########################
|
def find_with_equal_func(
|
||||||
# #
|
self, item: V, equal_func: Callable[[V, V], bool]
|
||||||
# WRITE OPERATIONS #
|
) -> tuple[bool, int]:
|
||||||
# #
|
log.warning("Finding is O(n) in GKVStore. Better use indexing")
|
||||||
#########################
|
for i, v in enumerate(self.values()):
|
||||||
|
if equal_func(v, item):
|
||||||
|
return True, i
|
||||||
|
return False, -1
|
||||||
|
|
||||||
|
def find_with_equal_func_full(
|
||||||
|
self, item: V, equal_func: Callable[[V, V, Any], bool], user_data: Any
|
||||||
|
) -> tuple[bool, int]:
|
||||||
|
log.warning("Finding is O(n) in GKVStore. Better use indexing")
|
||||||
|
for i, v in enumerate(self.values()):
|
||||||
|
if equal_func(v, item, user_data):
|
||||||
|
return True, i
|
||||||
|
return False, -1
|
||||||
|
|
||||||
def insert(self, position: int, item: V) -> None:
|
def insert(self, position: int, item: V) -> None:
|
||||||
log.warning("Inserting is O(n) in GKVStore. Better use append")
|
log.warning("Inserting is O(n) in GKVStore. Better use append")
|
||||||
log.warning(
|
log.warning(
|
||||||
@@ -122,9 +98,10 @@ class GKVStore(GObject.GObject, Gio.ListModel, Generic[K, V]):
|
|||||||
# Notify the model of the changes
|
# Notify the model of the changes
|
||||||
self.items_changed(position, 0, 1)
|
self.items_changed(position, 0, 1)
|
||||||
|
|
||||||
def append(self, item: V) -> None:
|
def insert_sorted(
|
||||||
key = self.key_gen(item)
|
self, item: V, compare_func: Callable[[V, V, Any], int], user_data: Any
|
||||||
self[key] = item
|
) -> None:
|
||||||
|
raise NotImplementedError("insert_sorted is not implemented in GKVStore")
|
||||||
|
|
||||||
def remove(self, position: int) -> None:
|
def remove(self, position: int) -> None:
|
||||||
if position < 0 or position >= self.get_n_items():
|
if position < 0 or position >= self.get_n_items():
|
||||||
@@ -137,6 +114,56 @@ class GKVStore(GObject.GObject, Gio.ListModel, Generic[K, V]):
|
|||||||
self._items.clear()
|
self._items.clear()
|
||||||
self.items_changed(0, len(self._items), 0)
|
self.items_changed(0, len(self._items), 0)
|
||||||
|
|
||||||
|
def sort(self, compare_func: Callable[[V, V, Any], int], user_data: Any) -> None:
|
||||||
|
raise NotImplementedError("sort is not implemented in GKVStore")
|
||||||
|
|
||||||
|
def splice(self, position: int, n_removals: int, additions: list[V]) -> None:
|
||||||
|
raise NotImplementedError("splice is not implemented in GKVStore")
|
||||||
|
|
||||||
|
##################################
|
||||||
|
# #
|
||||||
|
# Gio.ListModel Interface #
|
||||||
|
# #
|
||||||
|
##################################
|
||||||
|
def get_item(self, position: int) -> V | None:
|
||||||
|
if position < 0 or position >= self.get_n_items():
|
||||||
|
return None
|
||||||
|
# Access items by index since OrderedDict does not support direct indexing
|
||||||
|
key = list(self._items.keys())[position]
|
||||||
|
return self._items[key]
|
||||||
|
|
||||||
|
def do_get_item(self, position: int) -> V | None:
|
||||||
|
return self.get_item(position)
|
||||||
|
|
||||||
|
def get_item_type(self) -> GObject.GType:
|
||||||
|
return self.gtype.__gtype__
|
||||||
|
|
||||||
|
def do_get_item_type(self) -> GObject.GType:
|
||||||
|
return self.get_item_type()
|
||||||
|
|
||||||
|
def get_n_items(self) -> int:
|
||||||
|
return len(self._items)
|
||||||
|
|
||||||
|
def do_get_n_items(self) -> int:
|
||||||
|
return self.get_n_items()
|
||||||
|
|
||||||
|
##################################
|
||||||
|
# #
|
||||||
|
# Dict Interface #
|
||||||
|
# #
|
||||||
|
##################################
|
||||||
|
def keys(self) -> list[K]:
|
||||||
|
return list(self._items.keys())
|
||||||
|
|
||||||
|
def values(self) -> list[V]:
|
||||||
|
return list(self._items.values())
|
||||||
|
|
||||||
|
def items(self) -> list[tuple[K, V]]:
|
||||||
|
return list(self._items.items())
|
||||||
|
|
||||||
|
def get(self, key: K, default: V | None = None) -> V | None:
|
||||||
|
return self._items.get(key, default)
|
||||||
|
|
||||||
# O(1) operation if the key does not exist, O(n) if it does
|
# O(1) operation if the key does not exist, O(n) if it does
|
||||||
def __setitem__(self, key: K, value: V) -> None:
|
def __setitem__(self, key: K, value: V) -> None:
|
||||||
# If the key already exists, remove it O(n)
|
# If the key already exists, remove it O(n)
|
||||||
@@ -178,3 +205,14 @@ class GKVStore(GObject.GObject, Gio.ListModel, Generic[K, V]):
|
|||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return self._items.__str__()
|
return self._items.__str__()
|
||||||
|
|
||||||
|
##################################
|
||||||
|
# #
|
||||||
|
# Custom Methods #
|
||||||
|
# #
|
||||||
|
##################################
|
||||||
|
def first(self) -> V:
|
||||||
|
return self.values()[0]
|
||||||
|
|
||||||
|
def last(self) -> V:
|
||||||
|
return self.values()[-1]
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class JoinValue(GObject.Object):
|
|||||||
url: ClanURI
|
url: ClanURI
|
||||||
entry: HistoryEntry | None
|
entry: HistoryEntry | None
|
||||||
|
|
||||||
def _join_finished(self) -> bool:
|
def _join_finished_task(self) -> bool:
|
||||||
self.emit("join_finished", self)
|
self.emit("join_finished", self)
|
||||||
return GLib.SOURCE_REMOVE
|
return GLib.SOURCE_REMOVE
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ class JoinValue(GObject.Object):
|
|||||||
def __join(self) -> None:
|
def __join(self) -> None:
|
||||||
new_entry = add_history(self.url)
|
new_entry = add_history(self.url)
|
||||||
self.entry = new_entry
|
self.entry = new_entry
|
||||||
GLib.idle_add(self._join_finished)
|
GLib.idle_add(self._join_finished_task)
|
||||||
|
|
||||||
def join(self) -> None:
|
def join(self) -> None:
|
||||||
threading.Thread(target=self.__join).start()
|
threading.Thread(target=self.__join).start()
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class VM(GObject.Object):
|
|||||||
"vm_status_changed": (GObject.SignalFlags.RUN_FIRST, None, [GObject.Object])
|
"vm_status_changed": (GObject.SignalFlags.RUN_FIRST, None, [GObject.Object])
|
||||||
}
|
}
|
||||||
|
|
||||||
def vm_status_changed(self) -> bool:
|
def vm_status_changed_task(self) -> bool:
|
||||||
self.emit("vm_status_changed", self)
|
self.emit("vm_status_changed", self)
|
||||||
return GLib.SOURCE_REMOVE
|
return GLib.SOURCE_REMOVE
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ class VM(GObject.Object):
|
|||||||
yield self.machine
|
yield self.machine
|
||||||
self.machine = None
|
self.machine = None
|
||||||
|
|
||||||
def _pulse_progress_bar(self) -> bool:
|
def _pulse_progress_bar_task(self) -> bool:
|
||||||
if self.progress_bar.is_visible():
|
if self.progress_bar.is_visible():
|
||||||
self.progress_bar.pulse()
|
self.progress_bar.pulse()
|
||||||
return GLib.SOURCE_CONTINUE
|
return GLib.SOURCE_CONTINUE
|
||||||
@@ -150,7 +150,7 @@ class VM(GObject.Object):
|
|||||||
machine=machine,
|
machine=machine,
|
||||||
tmpdir=log_dir,
|
tmpdir=log_dir,
|
||||||
)
|
)
|
||||||
GLib.idle_add(self.vm_status_changed)
|
GLib.idle_add(self.vm_status_changed_task)
|
||||||
|
|
||||||
# Start the logs watcher
|
# Start the logs watcher
|
||||||
self._logs_id = GLib.timeout_add(
|
self._logs_id = GLib.timeout_add(
|
||||||
@@ -162,7 +162,7 @@ class VM(GObject.Object):
|
|||||||
|
|
||||||
# Start the progress bar and show it
|
# Start the progress bar and show it
|
||||||
self.progress_bar.show()
|
self.progress_bar.show()
|
||||||
self.prog_bar_id = GLib.timeout_add(100, self._pulse_progress_bar)
|
self.prog_bar_id = GLib.timeout_add(100, self._pulse_progress_bar_task)
|
||||||
if self.prog_bar_id == 0:
|
if self.prog_bar_id == 0:
|
||||||
log.error("Couldn't spawn a progess bar task")
|
log.error("Couldn't spawn a progess bar task")
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ class VM(GObject.Object):
|
|||||||
# Check if the VM was built successfully
|
# Check if the VM was built successfully
|
||||||
if self.build_process.proc.exitcode != 0:
|
if self.build_process.proc.exitcode != 0:
|
||||||
log.error(f"Failed to build VM {self.get_id()}")
|
log.error(f"Failed to build VM {self.get_id()}")
|
||||||
GLib.idle_add(self.vm_status_changed)
|
GLib.idle_add(self.vm_status_changed_task)
|
||||||
return
|
return
|
||||||
log.info(f"Successfully built VM {self.get_id()}")
|
log.info(f"Successfully built VM {self.get_id()}")
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ class VM(GObject.Object):
|
|||||||
vm=self.data.flake.vm,
|
vm=self.data.flake.vm,
|
||||||
)
|
)
|
||||||
log.debug(f"Started VM {self.get_id()}")
|
log.debug(f"Started VM {self.get_id()}")
|
||||||
GLib.idle_add(self.vm_status_changed)
|
GLib.idle_add(self.vm_status_changed_task)
|
||||||
|
|
||||||
# Start the logs watcher
|
# Start the logs watcher
|
||||||
self._logs_id = GLib.timeout_add(50, self._get_logs_task, self.vm_process)
|
self._logs_id = GLib.timeout_add(50, self._get_logs_task, self.vm_process)
|
||||||
@@ -198,7 +198,7 @@ class VM(GObject.Object):
|
|||||||
# Wait for the VM to stop
|
# Wait for the VM to stop
|
||||||
self.vm_process.proc.join()
|
self.vm_process.proc.join()
|
||||||
log.debug(f"VM {self.get_id()} has stopped")
|
log.debug(f"VM {self.get_id()} has stopped")
|
||||||
GLib.idle_add(self.vm_status_changed)
|
GLib.idle_add(self.vm_status_changed_task)
|
||||||
|
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
if self.is_running():
|
if self.is_running():
|
||||||
@@ -274,7 +274,7 @@ class VM(GObject.Object):
|
|||||||
|
|
||||||
# Try 20 times to stop the VM
|
# Try 20 times to stop the VM
|
||||||
time.sleep(self.KILL_TIMEOUT / 20)
|
time.sleep(self.KILL_TIMEOUT / 20)
|
||||||
GLib.idle_add(self.vm_status_changed)
|
GLib.idle_add(self.vm_status_changed_task)
|
||||||
log.debug(f"VM {self.get_id()} has stopped")
|
log.debug(f"VM {self.get_id()} has stopped")
|
||||||
|
|
||||||
def shutdown(self) -> None:
|
def shutdown(self) -> None:
|
||||||
@@ -348,6 +348,7 @@ class VMs:
|
|||||||
return GLib.SOURCE_REMOVE
|
return GLib.SOURCE_REMOVE
|
||||||
|
|
||||||
def push_history_entry(self, entry: HistoryEntry) -> None:
|
def push_history_entry(self, entry: HistoryEntry) -> None:
|
||||||
|
# TODO: We shouldn't do this here but in the list view
|
||||||
if entry.flake.icon is None:
|
if entry.flake.icon is None:
|
||||||
icon = assets.loc / "placeholder.jpeg"
|
icon = assets.loc / "placeholder.jpeg"
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user