forked from clan/clan-core
Merge pull request 'clan-vm-manager: Preserved selection on view change' (#604) from Qubasa-main into main
This commit is contained in:
commit
442551cd24
@ -23,6 +23,7 @@
|
||||
treefmt.programs.mypy.enable = true;
|
||||
treefmt.programs.mypy.directories = {
|
||||
"pkgs/clan-cli".extraPythonPackages = self'.packages.clan-cli.pytestDependencies;
|
||||
"pkgs/clan-vm-manager".extraPythonPackages = self'.packages.clan-vm-manager.propagatedBuildInputs;
|
||||
};
|
||||
|
||||
treefmt.settings.formatter.nix = {
|
||||
|
@ -55,5 +55,5 @@ ignore_missing_imports = true
|
||||
[tool.ruff]
|
||||
target-version = "py311"
|
||||
line-length = 88
|
||||
select = [ "E", "F", "I", "U", "N", "RUF", "ANN", "A" ]
|
||||
select = [ "E", "F", "I", "N", "RUF", "ANN", "A" ]
|
||||
ignore = ["E501", "E402", "ANN101", "ANN401", "A003"]
|
||||
|
@ -7,5 +7,7 @@
|
||||
"path": "../clan-cli/clan_cli"
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
"settings": {
|
||||
"python.linting.mypyEnabled": true
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ from .ui.clan_select_list import ClanEdit, ClanList
|
||||
|
||||
|
||||
class ClanJoinPage(Gtk.Box):
|
||||
def __init__(self, stack: Gtk.Stack) -> None:
|
||||
def __init__(self, *, stack: Gtk.Stack) -> None:
|
||||
super().__init__()
|
||||
self.page = Gtk.Box(
|
||||
orientation=Gtk.Orientation.VERTICAL, spacing=6, expand=True
|
||||
@ -51,12 +51,22 @@ class MainWindow(Gtk.ApplicationWindow):
|
||||
self.stack = Gtk.Stack()
|
||||
# self.stack_switcher = Gtk.StackSwitcher()
|
||||
|
||||
self.list_hooks = {
|
||||
"remount_list": self.remount_list_view,
|
||||
"remount_edit": self.remount_edit_view,
|
||||
"set_selected": self.set_selected,
|
||||
}
|
||||
clan_list = ClanList(**self.list_hooks, selected_vm=None) # type: ignore
|
||||
# Add named stacks
|
||||
self.stack.add_titled(clan_list, "list", "List")
|
||||
self.stack.add_titled(
|
||||
ClanList(self.show_list, self.show_edit, self.set_selected), "list", "List"
|
||||
ClanJoinPage(stack=self.remount_list_view), "join", "Join"
|
||||
)
|
||||
self.stack.add_titled(
|
||||
ClanEdit(remount_list=self.remount_list_view, selected_vm=None),
|
||||
"edit",
|
||||
"Edit",
|
||||
)
|
||||
self.stack.add_titled(ClanJoinPage(self.show_list), "join", "Join")
|
||||
self.stack.add_titled(ClanEdit(self.show_list, None), "edit", "Edit")
|
||||
|
||||
vbox.add(self.stack)
|
||||
|
||||
@ -64,28 +74,31 @@ class MainWindow(Gtk.ApplicationWindow):
|
||||
self.show_all()
|
||||
|
||||
def set_selected(self, sel: VMBase | None) -> None:
|
||||
self.selected = sel
|
||||
print(f"APP selected + {self.selected}")
|
||||
self.selected_vm = sel
|
||||
print(f"APP selected + {self.selected_vm}")
|
||||
|
||||
def show_list(self) -> None:
|
||||
def remount_list_view(self) -> None:
|
||||
widget = self.stack.get_child_by_name("list")
|
||||
print("Remounting ClanListView")
|
||||
if widget:
|
||||
widget.destroy()
|
||||
|
||||
self.stack.add_titled(
|
||||
ClanList(self.show_list, self.show_edit, self.set_selected), "list", "List"
|
||||
)
|
||||
clan_list = ClanList(**self.list_hooks, selected_vm=self.selected_vm) # type: ignore
|
||||
self.stack.add_titled(clan_list, "list", "List")
|
||||
self.show_all()
|
||||
self.stack.set_visible_child_name("list")
|
||||
|
||||
def show_edit(self) -> None:
|
||||
def remount_edit_view(self) -> None:
|
||||
print("Remounting ClanEdit")
|
||||
widget = self.stack.get_child_by_name("edit")
|
||||
if widget:
|
||||
widget.destroy()
|
||||
|
||||
self.stack.add_titled(ClanEdit(self.show_list, self.selected), "edit", "Edit")
|
||||
self.stack.add_titled(
|
||||
ClanEdit(remount_list=self.remount_list_view, selected_vm=self.selected_vm),
|
||||
"edit",
|
||||
"Edit",
|
||||
)
|
||||
self.show_all()
|
||||
self.stack.set_visible_child_name("edit")
|
||||
|
||||
|
@ -6,7 +6,7 @@ from ..models import VMBase, get_initial_vms
|
||||
|
||||
|
||||
class ClanEditForm(Gtk.ListBox):
|
||||
def __init__(self, selected: VMBase | None) -> None:
|
||||
def __init__(self, *, selected: VMBase | None) -> None:
|
||||
super().__init__()
|
||||
self.page = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, expand=True)
|
||||
self.set_border_width(10)
|
||||
@ -47,11 +47,13 @@ class ClanEditForm(Gtk.ListBox):
|
||||
|
||||
|
||||
class ClanEdit(Gtk.Box):
|
||||
def __init__(self, show_list: Callable[[], None], selected: VMBase | None) -> None:
|
||||
def __init__(
|
||||
self, *, remount_list: Callable[[], None], selected_vm: VMBase | None
|
||||
) -> None:
|
||||
super().__init__(orientation=Gtk.Orientation.VERTICAL, expand=True)
|
||||
|
||||
self.show_list = show_list
|
||||
self.selected = selected
|
||||
self.show_list = remount_list
|
||||
self.selected = selected_vm
|
||||
|
||||
button_hooks = {
|
||||
"on_save_clicked": self.on_save,
|
||||
@ -59,7 +61,7 @@ class ClanEdit(Gtk.Box):
|
||||
|
||||
self.toolbar = ClanEditToolbar(**button_hooks)
|
||||
self.add(self.toolbar)
|
||||
self.add(ClanEditForm(self.selected))
|
||||
self.add(ClanEditForm(selected=self.selected))
|
||||
|
||||
def on_save(self, widget: Gtk.Widget) -> None:
|
||||
print("Save clicked saving values")
|
||||
@ -82,14 +84,16 @@ class ClanList(Gtk.Box):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
show_list: Callable[[], None],
|
||||
show_edit: Callable[[], None],
|
||||
*,
|
||||
remount_list: Callable[[], None],
|
||||
remount_edit: Callable[[], None],
|
||||
set_selected: Callable[[VMBase | None], None],
|
||||
selected_vm: VMBase | None,
|
||||
) -> None:
|
||||
super().__init__(orientation=Gtk.Orientation.VERTICAL, expand=True)
|
||||
|
||||
self.show_edit = show_edit
|
||||
self.show_list = show_list
|
||||
self.remount_edit_view = remount_edit
|
||||
self.remount_list_view = remount_list
|
||||
self.set_selected = set_selected
|
||||
|
||||
# TODO: We should use somekind of useState hook here.
|
||||
@ -98,7 +102,7 @@ class ClanList(Gtk.Box):
|
||||
# self.list_store.set_value(self.list_store.get_iter(path), 3, "new value")
|
||||
# self.list_store[path][3] = "new_value"
|
||||
# This class needs to take ownership of the data because it has access to the listStore only
|
||||
self.selected_vm: VMBase | None = None
|
||||
self.selected_vm: VMBase | None = selected_vm
|
||||
|
||||
button_hooks = {
|
||||
"on_start_clicked": self.on_start_clicked,
|
||||
@ -106,27 +110,27 @@ class ClanList(Gtk.Box):
|
||||
"on_edit_clicked": self.on_edit_clicked,
|
||||
}
|
||||
self.toolbar = ClanListToolbar(**button_hooks)
|
||||
self.toolbar.set_is_selected(False)
|
||||
self.toolbar.set_is_selected(self.selected_vm is not None)
|
||||
self.add(self.toolbar)
|
||||
|
||||
self.list_hooks = {
|
||||
"on_select_row": self.on_select_vm,
|
||||
}
|
||||
self.add(ClanListView(**self.list_hooks))
|
||||
self.add(ClanListView(**self.list_hooks, selected_vm=selected_vm))
|
||||
|
||||
def on_start_clicked(self, widget: Gtk.Widget) -> None:
|
||||
print("Start clicked")
|
||||
if self.selected_vm:
|
||||
self.selected_vm.run()
|
||||
# Call this to reload
|
||||
self.show_list()
|
||||
self.remount_list_view()
|
||||
|
||||
def on_stop_clicked(self, widget: Gtk.Widget) -> None:
|
||||
print("Stop clicked")
|
||||
|
||||
def on_edit_clicked(self, widget: Gtk.Widget) -> None:
|
||||
print("Edit clicked")
|
||||
self.show_edit()
|
||||
self.remount_edit_view()
|
||||
|
||||
def on_select_vm(self, vm: VMBase) -> None:
|
||||
print(f"on_select_vm: {vm}")
|
||||
@ -186,9 +190,8 @@ class ClanListView(Gtk.Box):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
# vms: list[VMBase],
|
||||
on_select_row: Callable[[VMBase], None],
|
||||
# on_double_click: Callable[[VMBase], None],
|
||||
selected_vm: VMBase | None,
|
||||
) -> None:
|
||||
super().__init__(expand=True)
|
||||
self.vms: list[VMBase] = [vm.base for vm in get_initial_vms()]
|
||||
@ -202,6 +205,7 @@ class ClanListView(Gtk.Box):
|
||||
|
||||
setColRenderers(self.tree_view)
|
||||
|
||||
self.set_selected_vm(selected_vm)
|
||||
selection = self.tree_view.get_selection()
|
||||
selection.connect("changed", self._on_select_row)
|
||||
self.tree_view.connect("row-activated", self._on_double_click)
|
||||
@ -209,6 +213,20 @@ class ClanListView(Gtk.Box):
|
||||
self.set_border_width(10)
|
||||
self.add(self.tree_view)
|
||||
|
||||
def find_vm(self, vm: VMBase) -> int:
|
||||
for idx, row in enumerate(self.list_store):
|
||||
if row[1] == vm.name: # TODO: Change to path
|
||||
return idx
|
||||
return -1
|
||||
|
||||
def set_selected_vm(self, vm: VMBase | None) -> None:
|
||||
if vm is None:
|
||||
return
|
||||
selection = self.tree_view.get_selection()
|
||||
idx = self.find_vm(vm)
|
||||
print(f"Set selected vm: {vm.name} at {idx}")
|
||||
selection.select_path(idx)
|
||||
|
||||
def insertVM(self, vm: VMBase) -> None:
|
||||
values = list(vm.list_data().values())
|
||||
values[0] = GdkPixbuf.Pixbuf.new_from_file_at_scale(
|
||||
|
@ -10,6 +10,7 @@
|
||||
, gobject-introspection
|
||||
, clan-cli
|
||||
, makeDesktopItem
|
||||
, mypy
|
||||
, ipdb
|
||||
}:
|
||||
let
|
||||
@ -34,7 +35,7 @@ python3.pkgs.buildPythonApplication {
|
||||
];
|
||||
|
||||
buildInputs = [ spice-gtk gtk3 gnome.adwaita-icon-theme ];
|
||||
propagatedBuildInputs = [ ipdb pygobject3 clan-cli ];
|
||||
propagatedBuildInputs = [ mypy ipdb pygobject3 clan-cli ];
|
||||
|
||||
# also re-expose dependencies so we test them in CI
|
||||
passthru.tests = {
|
||||
|
@ -21,8 +21,12 @@ no_implicit_optional = true
|
||||
module = "gi.*"
|
||||
ignore_missing_imports = true
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = "clan_cli.*"
|
||||
ignore_missing_imports = true
|
||||
|
||||
[tool.ruff]
|
||||
target-version = "py311"
|
||||
line-length = 88
|
||||
select = [ "E", "F", "I", "U", "N", "RUF", "ANN", "A" ]
|
||||
select = [ "E", "F", "I", "N", "RUF", "ANN", "A" ]
|
||||
ignore = ["E501", "E402", "N802", "ANN101", "ANN401", "A003"]
|
||||
|
Loading…
Reference in New Issue
Block a user