Merge pull request 'gui add stack switcher, remove notebook tabs' (#602) from hsjobeki-main into main
All checks were successful
assets1 / test (push) Successful in 24s
checks / test (push) Successful in 41s
checks-impure / test (push) Successful in 1m4s

This commit is contained in:
clan-bot 2023-12-03 13:11:26 +00:00
commit 354291440a
2 changed files with 189 additions and 42 deletions

View File

@ -6,19 +6,32 @@ from typing import Any
import gi
from clan_vm_manager.models import VMBase
gi.require_version("Gtk", "3.0")
from gi.repository import Gio, Gtk
from .constants import constants
from .ui.clan_select_list import ClanSelectPage
from .ui.clan_select_list import ClanEdit, ClanList
class ClanJoinPage(Gtk.Box):
def __init__(self) -> None:
def __init__(self, stack: Gtk.Stack) -> None:
super().__init__()
self.page = Gtk.Box()
self.page = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=6, expand=True
)
self.set_border_width(10)
self.add(Gtk.Label(label="Join"))
self.stack = stack
button = Gtk.Button(label="Back to list", margin_left=10)
button.connect("clicked", self.switch)
self.add(button)
self.add(Gtk.Label("Join cLan"))
def switch(self, widget: Gtk.Widget) -> None:
self.stack.set_visible_child_name("list")
class MainWindow(Gtk.ApplicationWindow):
@ -35,25 +48,46 @@ class MainWindow(Gtk.ApplicationWindow):
# Add a notebook layout
# https://python-gtk-3-tutorial.readthedocs.io/en/latest/layout.html#notebook
self.notebook = Gtk.Notebook()
vbox.add(self.notebook)
self.stack = Gtk.Stack()
# self.stack_switcher = Gtk.StackSwitcher()
self.notebook.append_page(
ClanSelectPage(self.reload_clan_tab), Gtk.Label(label="Overview")
# Add named stacks
self.stack.add_titled(
ClanList(self.show_list, self.show_edit, self.set_selected), "list", "List"
)
self.notebook.append_page(ClanJoinPage(), Gtk.Label(label="Join"))
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)
# Must be called AFTER all components were added
self.show_all()
def reload_clan_tab(self) -> None:
print("Remounting ClanSelectPage")
self.notebook.remove_page(0)
self.notebook.insert_page(
ClanSelectPage(self.reload_clan_tab), Gtk.Label(label="Overview2"), 0
def set_selected(self, sel: VMBase | None) -> None:
self.selected = sel
print(f"APP selected + {self.selected}")
def show_list(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"
)
# must call show_all before set active tab
self.show_all()
self.notebook.set_current_page(0)
self.stack.set_visible_child_name("list")
def show_edit(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.show_all()
self.stack.set_visible_child_name("edit")
def on_quit(self, *args: Any) -> None:
Gio.Application.quit(self.get_application())

View File

@ -5,10 +5,93 @@ from gi.repository import GdkPixbuf, Gtk
from ..models import VMBase, get_initial_vms
class ClanSelectPage(Gtk.Box):
def __init__(self, reload: Callable[[], None]) -> None:
class ClanEditForm(Gtk.ListBox):
def __init__(self, selected: VMBase | None) -> None:
super().__init__()
self.page = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, expand=True)
self.set_border_width(10)
self.selected = selected
self.set_selection_mode(0)
if self.selected:
row = Gtk.ListBoxRow()
row.add(Gtk.Label(f"\n {self.selected.name}"))
self.add(row)
# ---------- row 1 --------
row = Gtk.ListBoxRow()
row_layout = Gtk.Box(spacing=6, expand=True)
# Doc: pack_start/end takes alignment params Expand, Fill, Padding
row_layout.pack_start(Gtk.Label("Memory Size in MiB"), False, False, 5)
row_layout.pack_start(
Gtk.SpinButton.new_with_range(512, 4096, 256), True, True, 0
)
row.add(row_layout)
self.add(row)
# ----------- row 2 -------
row = Gtk.ListBoxRow()
row_layout = Gtk.Box(spacing=6, expand=True)
row_layout.pack_start(Gtk.Label("CPU Count"), False, False, 5)
row_layout.pack_end(Gtk.SpinButton.new_with_range(1, 5, 1), True, True, 0)
row.add(row_layout)
self.add(row)
def switch(self, widget: Gtk.Widget) -> None:
self.show_list()
class ClanEdit(Gtk.Box):
def __init__(self, show_list: Callable[[], None], selected: VMBase | None) -> None:
super().__init__(orientation=Gtk.Orientation.VERTICAL, expand=True)
self.show_list = show_list
self.selected = selected
button_hooks = {
"on_save_clicked": self.on_save,
}
self.toolbar = ClanEditToolbar(**button_hooks)
self.add(self.toolbar)
self.add(ClanEditForm(self.selected))
def on_save(self, widget: Gtk.Widget) -> None:
print("Save clicked saving values")
self.show_list()
class ClanList(Gtk.Box):
"""
The ClanList
Is the composition of
the ClanListToolbar
the clanListView
# ------------------------#
# - Tools <Join> < Edit> #
# ------------------------#
# - List Items
# - <...>
# ------------------------#
"""
def __init__(
self,
show_list: Callable[[], None],
show_edit: Callable[[], None],
set_selected: Callable[[VMBase | None], None],
) -> None:
super().__init__(orientation=Gtk.Orientation.VERTICAL, expand=True)
self.show_edit = show_edit
self.show_list = show_list
self.set_selected = set_selected
# TODO: We should use somekind of useState hook here.
# that updates the list of VMs when the user changes something
# @hsjobeki reply: @qubasa: This is how to update data in the list store
@ -17,59 +100,89 @@ class ClanSelectPage(Gtk.Box):
# This class needs to take ownership of the data because it has access to the listStore only
self.selected_vm: VMBase | None = None
self.list_hooks = {
"on_select_row": self.on_select_vm,
}
self.add(ClanSelectList(**self.list_hooks))
self.reload = reload
button_hooks = {
"on_start_clicked": self.on_start_clicked,
"on_stop_clicked": self.on_stop_clicked,
"on_backup_clicked": self.on_backup_clicked,
"on_edit_clicked": self.on_edit_clicked,
}
self.add(ClanSelectButtons(**button_hooks))
self.toolbar = ClanListToolbar(**button_hooks)
self.toolbar.set_is_selected(False)
self.add(self.toolbar)
self.list_hooks = {
"on_select_row": self.on_select_vm,
}
self.add(ClanListView(**self.list_hooks))
def on_start_clicked(self, widget: Gtk.Widget) -> None:
print("Start clicked")
if self.selected_vm:
self.selected_vm.run()
self.reload()
# Call this to reload
self.show_list()
def on_stop_clicked(self, widget: Gtk.Widget) -> None:
print("Stop clicked")
def on_backup_clicked(self, widget: Gtk.Widget) -> None:
print("Backup clicked")
def on_edit_clicked(self, widget: Gtk.Widget) -> None:
print("Edit clicked")
self.show_edit()
def on_select_vm(self, vm: VMBase) -> None:
print(f"on_select_vm: {vm}")
if vm is None:
self.toolbar.set_is_selected(False)
else:
self.toolbar.set_is_selected(True)
self.set_selected(vm)
self.selected_vm = vm
class ClanSelectButtons(Gtk.Box):
class ClanListToolbar(Gtk.Toolbar):
def __init__(
self,
*,
on_start_clicked: Callable[[Gtk.Widget], None],
on_stop_clicked: Callable[[Gtk.Widget], None],
on_backup_clicked: Callable[[Gtk.Widget], None],
on_edit_clicked: Callable[[Gtk.Widget], None],
) -> None:
super().__init__(
orientation=Gtk.Orientation.HORIZONTAL, margin_bottom=10, margin_top=10
)
super().__init__(orientation=Gtk.Orientation.HORIZONTAL)
button = Gtk.Button(label="Start", margin_left=10)
button.connect("clicked", on_start_clicked)
self.add(button)
button = Gtk.Button(label="Stop", margin_left=10)
button.connect("clicked", on_stop_clicked)
self.add(button)
button = Gtk.Button(label="Edit", margin_left=10)
button.connect("clicked", on_backup_clicked)
self.add(button)
self.start_button = Gtk.ToolButton(label="Join")
self.start_button.connect("clicked", on_start_clicked)
self.add(self.start_button)
self.edit_button = Gtk.ToolButton(label="Edit")
self.edit_button.connect("clicked", on_edit_clicked)
self.add(self.edit_button)
def set_is_selected(self, s: bool) -> None:
if s:
self.edit_button.set_sensitive(True)
self.start_button.set_sensitive(True)
else:
self.edit_button.set_sensitive(False)
self.start_button.set_sensitive(False)
class ClanSelectList(Gtk.Box):
class ClanEditToolbar(Gtk.Toolbar):
def __init__(
self,
*,
on_save_clicked: Callable[[Gtk.Widget], None],
) -> None:
super().__init__(orientation=Gtk.Orientation.HORIZONTAL)
# Icons See: https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
# Could not find a suitable one
self.save_button = Gtk.ToolButton(label="Save")
self.save_button.connect("clicked", on_save_clicked)
self.add(self.save_button)
class ClanListView(Gtk.Box):
def __init__(
self,
*,