1
0
forked from clan/clan-core

prepare gtk4 migration

This commit is contained in:
Johannes Kirschbauer 2024-01-06 15:40:42 +01:00
parent 07a0e1db09
commit 40ee264321
Signed by: hsjobeki
SSH Key Fingerprint: SHA256:vX3utDqig7Ph5L0JPv87ZTPb/w7cMzREKVZzzLFg9qU
9 changed files with 214 additions and 197 deletions

View File

@ -8,7 +8,7 @@ from clan_cli import vms
from clan_vm_manager.windows.flash import FlashUSBWindow from clan_vm_manager.windows.flash import FlashUSBWindow
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "4.0")
import multiprocessing as mp import multiprocessing as mp

View File

@ -4,19 +4,19 @@ from typing import Literal
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "4.0")
gi.require_version('Adw', '1')
from clan_cli.errors import ClanError from clan_cli.errors import ClanError
from gi.repository import Gtk from gi.repository import Gtk, Adw
Severity = Literal["Error"] | Literal["Warning"] | Literal["Info"] | str Severity = Literal["Error"] | Literal["Warning"] | Literal["Info"] | str
def show_error_dialog(error: ClanError, severity: Severity | None = "Error") -> None: def show_error_dialog(error: ClanError, severity: Severity | None = "Error") -> None:
message = str(error) message = str(error)
dialog = Gtk.MessageDialog( dialog = Adw.MessageDialog(
None, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, severity parent=None, heading=severity, body=message
) )
print("error:", message) print("error:", message)
dialog.format_secondary_text(message) dialog.add_response("ok", "ok")
dialog.run() dialog.choose()
dialog.destroy()

View File

@ -3,7 +3,7 @@
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "4.0")
from gi.repository import Gtk from gi.repository import Gtk
@ -11,16 +11,17 @@ class ClanJoinPage(Gtk.Box):
def __init__(self, *, stack: Gtk.Stack) -> None: def __init__(self, *, stack: Gtk.Stack) -> None:
super().__init__() super().__init__()
self.page = Gtk.Box( self.page = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, spacing=6, expand=True orientation=Gtk.Orientation.VERTICAL, spacing=6
) )
self.set_border_width(10) # self.set_border_width(10)
self.stack = stack self.stack = stack
button = Gtk.Button(label="Back to list", margin_left=10) button = Gtk.Button(label="Back to list")
button.connect("clicked", self.switch) button.connect("clicked", self.switch)
self.add(button) self.append(button)
self.add(Gtk.Label("Join cLan")) label = Gtk.Label.new("Join cLan")
self.append(label)
def switch(self, widget: Gtk.Widget) -> None: def switch(self, widget: Gtk.Widget) -> None:
self.stack.set_visible_child_name("list") self.stack.set_visible_child_name("list")

View File

@ -1,48 +1,48 @@
from collections.abc import Callable from typing import Callable, Any
from gi.repository import Gdk, GdkPixbuf, Gtk from gi.repository import Gdk, GdkPixbuf, Gtk, Adw
from ..interfaces import Callbacks from ..interfaces import Callbacks
from ..models import VMBase, VMStatus from ..models import VMBase, VMStatus
from .context_menu import VmMenu # from .context_menu import VmMenu
class ClanEditForm(Gtk.ListBox): class ClanEditForm(Gtk.Box):
def __init__(self, *, selected: VMBase | None) -> None: def __init__(self, *, selected: VMBase | None) -> None:
super().__init__() super().__init__()
self.page = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, expand=True) self.page = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.set_border_width(10) # self.set_border_width(10)
self.selected = selected self.selected = selected
self.set_selection_mode(0) # self.set_selection_mode(0)
if self.selected: if self.selected:
row = Gtk.ListBoxRow() label = Gtk.Box()
row.add(Gtk.Label(f"\n {self.selected.name}")) label.append(Gtk.Label.new(f"\n {self.selected.name}"))
self.add(row) self.append(label)
# ---------- row 1 -------- # ---------- row 1 --------
row = Gtk.ListBoxRow() # row = Gtk.ListBoxRow()
row_layout = Gtk.Box(spacing=6, expand=True) # row_layout = Gtk.Box(spacing=6)
# Doc: pack_start/end takes alignment params Expand, Fill, Padding # # 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.append(Gtk.Label.new("Memory Size in MiB"))
row_layout.pack_start( # row_layout.append(
Gtk.SpinButton.new_with_range(512, 4096, 256), True, True, 0 # Gtk.SpinButton.new_with_range(512, 4096, 256)
) # )
row.add(row_layout) # row.append(row_layout)
self.add(row) # self.append(row)
# ----------- row 2 ------- # # ----------- row 2 -------
row = Gtk.ListBoxRow() # row = Gtk.ListBoxRow()
row_layout = Gtk.Box(spacing=6, expand=True) # row_layout = Gtk.Box(spacing=6)
row_layout.pack_start(Gtk.Label("CPU Count"), False, False, 5) # row_layout.append(Gtk.Label("CPU Count"))
row_layout.pack_end(Gtk.SpinButton.new_with_range(1, 5, 1), True, True, 0) # row_layout.append(Gtk.SpinButton.new_with_range(1, 5, 1))
row.add(row_layout) # row.append(row_layout)
self.add(row) # self.append(row)
def switch(self, widget: Gtk.Widget) -> None: def switch(self, widget: Gtk.Widget) -> None:
self.show_list() self.show_list()
@ -52,14 +52,14 @@ class ClanEdit(Gtk.Box):
def __init__( def __init__(
self, *, remount_list: Callable[[], None], selected_vm: VMBase | None self, *, remount_list: Callable[[], None], selected_vm: VMBase | None
) -> None: ) -> None:
super().__init__(orientation=Gtk.Orientation.VERTICAL, expand=True) super().__init__(orientation=Gtk.Orientation.VERTICAL, )
self.show_list = remount_list self.show_list = remount_list
self.selected = selected_vm self.selected = selected_vm
self.toolbar = ClanEditToolbar(on_save_clicked=self.on_save) # self.toolbar = ClanEditToolbar(on_save_clicked=self.on_save)
self.add(self.toolbar) # self.add(self.toolbar)
self.add(ClanEditForm(selected=self.selected)) self.append(ClanEditForm(selected=self.selected))
def on_save(self, widget: Gtk.Widget) -> None: def on_save(self, widget: Gtk.Widget) -> None:
print("Save clicked saving values") print("Save clicked saving values")
@ -90,7 +90,7 @@ class ClanList(Gtk.Box):
selected_vm: VMBase | None, selected_vm: VMBase | None,
vms: list[VMBase], vms: list[VMBase],
) -> None: ) -> None:
super().__init__(orientation=Gtk.Orientation.VERTICAL, expand=True) super().__init__(orientation=Gtk.Orientation.VERTICAL, )
self.remount_edit_view = remount_edit self.remount_edit_view = remount_edit
self.remount_list_view = remount_list self.remount_list_view = remount_list
@ -100,17 +100,17 @@ class ClanList(Gtk.Box):
self.selected_vm: VMBase | None = selected_vm self.selected_vm: VMBase | None = selected_vm
self.toolbar = ClanListToolbar( # self.toolbar = ClanListToolbar(
selected_vm=selected_vm, # selected_vm=selected_vm,
on_start_clicked=self.on_start_clicked, # on_start_clicked=self.on_start_clicked,
on_stop_clicked=self.on_stop_clicked, # on_stop_clicked=self.on_stop_clicked,
on_edit_clicked=self.on_edit_clicked, # on_edit_clicked=self.on_edit_clicked,
on_join_clan_clicked=self.on_join_clan_clicked, # on_join_clan_clicked=self.on_join_clan_clicked,
on_flash_clicked=self.on_flash_clicked, # on_flash_clicked=self.on_flash_clicked,
) # )
self.add(self.toolbar) # self.add(self.toolbar)
self.add( self.append(
ClanListView( ClanListView(
vms=vms, vms=vms,
on_select_row=self.on_select_vm, on_select_row=self.on_select_vm,
@ -143,13 +143,13 @@ class ClanList(Gtk.Box):
self.remount_edit_view() self.remount_edit_view()
def on_select_vm(self, vm: VMBase) -> None: def on_select_vm(self, vm: VMBase) -> None:
self.toolbar.set_selected_vm(vm) # self.toolbar.set_selected_vm(vm)
self.set_selected(vm) self.set_selected(vm)
self.selected_vm = vm self.selected_vm = vm
class ClanListToolbar(Gtk.Toolbar): class ClanListToolbar(Gtk.Box):
def __init__( def __init__(
self, self,
*, *,
@ -164,23 +164,23 @@ class ClanListToolbar(Gtk.Toolbar):
self.start_button = Gtk.ToolButton(label="Start") self.start_button = Gtk.ToolButton(label="Start")
self.start_button.connect("clicked", on_start_clicked) self.start_button.connect("clicked", on_start_clicked)
self.add(self.start_button) self.append(self.start_button)
self.stop_button = Gtk.ToolButton(label="Stop") self.stop_button = Gtk.ToolButton(label="Stop")
self.stop_button.connect("clicked", on_stop_clicked) self.stop_button.connect("clicked", on_stop_clicked)
self.add(self.stop_button) self.append(self.stop_button)
self.edit_button = Gtk.ToolButton(label="Edit") self.edit_button = Gtk.ToolButton(label="Edit")
self.edit_button.connect("clicked", on_edit_clicked) self.edit_button.connect("clicked", on_edit_clicked)
self.add(self.edit_button) self.append(self.edit_button)
self.join_clan_button = Gtk.ToolButton(label="Join Clan") self.join_clan_button = Gtk.ToolButton(label="Join Clan")
self.join_clan_button.connect("clicked", on_join_clan_clicked) self.join_clan_button.connect("clicked", on_join_clan_clicked)
self.add(self.join_clan_button) self.append(self.join_clan_button)
self.flash_button = Gtk.ToolButton(label="Write to USB") self.flash_button = Gtk.ToolButton(label="Write to USB")
self.flash_button.connect("clicked", on_flash_clicked) self.flash_button.connect("clicked", on_flash_clicked)
self.add(self.flash_button) self.append(self.flash_button)
self.set_selected_vm(selected_vm) self.set_selected_vm(selected_vm)
@ -195,7 +195,7 @@ class ClanListToolbar(Gtk.Toolbar):
self.stop_button.set_sensitive(False) self.stop_button.set_sensitive(False)
class ClanEditToolbar(Gtk.Toolbar): class ClanEditToolbar(Gtk.Box):
def __init__( def __init__(
self, self,
*, *,
@ -208,7 +208,7 @@ class ClanEditToolbar(Gtk.Toolbar):
self.save_button = Gtk.ToolButton(label="Save") self.save_button = Gtk.ToolButton(label="Save")
self.save_button.connect("clicked", on_save_clicked) self.save_button.connect("clicked", on_save_clicked)
self.add(self.save_button) self.append(self.save_button)
class ClanListView(Gtk.Box): class ClanListView(Gtk.Box):
@ -220,29 +220,29 @@ class ClanListView(Gtk.Box):
vms: list[VMBase], vms: list[VMBase],
on_double_click: Callable[[VMBase], None], on_double_click: Callable[[VMBase], None],
) -> None: ) -> None:
super().__init__(expand=True) super().__init__()
self.vms: list[VMBase] = vms self.vms: list[VMBase] = vms
self.on_select_row = on_select_row self.on_select_row = on_select_row
self.on_double_click = on_double_click self.on_double_click = on_double_click
self.context_menu: VmMenu | None = None # self.context_menu: VmMenu | None = None
store_types = VMBase.name_to_type_map().values() store_types = VMBase.name_to_type_map().values()
self.list_store = Gtk.ListStore(*store_types) # self.list_store = Gtk.ListStore(*store_types)
self.tree_view = Gtk.TreeView(self.list_store, expand=True) # self.tree_view = Gtk.TreeView(self.list_store)
for vm in self.vms: # for vm in self.vms:
self.insertVM(vm) # self.insertVM(vm)
setColRenderers(self.tree_view) # setColRenderers(self.tree_view)
self.set_selected_vm(selected_vm) self.set_selected_vm(selected_vm)
selection = self.tree_view.get_selection() # selection = self.tree_view.get_selection()
selection.connect("changed", self._on_select_row) # selection.connect("changed", self._on_select_row)
self.tree_view.connect("row-activated", self._on_double_click) # self.tree_view.connect("row-activated", self._on_double_click)
self.tree_view.connect("button-press-event", self._on_button_pressed) # self.tree_view.connect("button-press-event", self._on_button_pressed)
self.set_border_width(10) # self.set_border_width(10)
self.add(self.tree_view) # self.append(self.tree_view)
def find_vm(self, vm: VMBase) -> int: def find_vm(self, vm: VMBase) -> int:
for idx, row in enumerate(self.list_store): for idx, row in enumerate(self.list_store):
@ -257,13 +257,13 @@ class ClanListView(Gtk.Box):
idx = self.find_vm(vm) idx = self.find_vm(vm)
selection.select_path(idx) selection.select_path(idx)
def insertVM(self, vm: VMBase) -> None: # def insertVM(self, vm: VMBase) -> None:
values = list(vm.list_data().values()) # values = list(vm.list_data().values())
icon_idx = VMBase.to_idx("Icon") # icon_idx = VMBase.to_idx("Icon")
values[icon_idx] = GdkPixbuf.Pixbuf.new_from_file_at_scale( # values[icon_idx] = GdkPixbuf.Pixbuf.new_from_file_at_scale(
filename=values[icon_idx], width=64, height=64, preserve_aspect_ratio=True # filename=values[icon_idx], width=64, height=64, preserve_aspect_ratio=True
) # )
self.list_store.append(values) # self.list_store.append(values)
def _on_select_row(self, selection: Gtk.TreeSelection) -> None: def _on_select_row(self, selection: Gtk.TreeSelection) -> None:
model, row = selection.get_selected() model, row = selection.get_selected()
@ -271,58 +271,58 @@ class ClanListView(Gtk.Box):
vm = VMBase(*model[row]) vm = VMBase(*model[row])
self.on_select_row(vm) self.on_select_row(vm)
def _on_button_pressed( # def _on_button_pressed(
self, tree_view: Gtk.TreeView, event: Gdk.EventButton # self, tree_view: Gtk.TreeView, event: Any
) -> None: # ) -> None:
if self.context_menu: # # if self.context_menu:
self.context_menu.destroy() # # self.context_menu.destroy()
self.context_menu = None # # self.context_menu = None
if event.button == 3: # if event.button == 3:
path, column, x, y = tree_view.get_path_at_pos(event.x, event.y) # path, column, x, y = tree_view.get_path_at_pos(event.x, event.y)
if path is not None: # if path is not None:
vm = VMBase(*self.list_store[path[0]]) # vm = VMBase(*self.list_store[path[0]])
print(event) # print(event)
print(f"Right click on {vm.url}") # print(f"Right click on {vm.url}")
self.context_menu = VmMenu(vm) # # self.context_menu = VmMenu(vm)
self.context_menu.popup_at_pointer(event) # # self.context_menu.popup_at_pointer(event)
def _on_double_click( # def _on_double_click(
self, tree_view: Gtk.TreeView, path: Gtk.TreePath, column: Gtk.TreeViewColumn # self, tree_view: Gtk.TreeView, path: Gtk.TreePath, column: Gtk.TreeViewColumn
) -> None: # ) -> None:
# Get the selection object of the tree view # # Get the selection object of the tree view
selection = tree_view.get_selection() # selection = tree_view.get_selection()
model, row = selection.get_selected() # model, row = selection.get_selected()
if row is not None: # if row is not None:
vm = VMBase(*model[row]) # vm = VMBase(*model[row])
self.on_double_click(vm) # self.on_double_click(vm)
def setColRenderers(tree_view: Gtk.TreeView) -> None: # def setColRenderers(tree_view: Gtk.TreeView) -> None:
for idx, (key, gtype) in enumerate(VMBase.name_to_type_map().items()): # for idx, (key, gtype) in enumerate(VMBase.name_to_type_map().items()):
col: Gtk.TreeViewColumn = None # col: Gtk.TreeViewColumn = None
if key.startswith("_"): # if key.startswith("_"):
continue # continue
if issubclass(gtype, GdkPixbuf.Pixbuf): # if issubclass(gtype, GdkPixbuf.Pixbuf):
renderer = Gtk.CellRendererPixbuf() # renderer = Gtk.CellRendererPixbuf()
col = Gtk.TreeViewColumn(key, renderer, pixbuf=idx) # col = Gtk.TreeViewColumn(key, renderer, pixbuf=idx)
elif issubclass(gtype, bool): # elif issubclass(gtype, bool):
renderer = Gtk.CellRendererToggle() # renderer = Gtk.CellRendererToggle()
col = Gtk.TreeViewColumn(key, renderer, active=idx) # col = Gtk.TreeViewColumn(key, renderer, active=idx)
elif issubclass(gtype, str): # elif issubclass(gtype, str):
renderer = Gtk.CellRendererText() # renderer = Gtk.CellRendererText()
col = Gtk.TreeViewColumn(key, renderer, text=idx) # col = Gtk.TreeViewColumn(key, renderer, text=idx)
else: # else:
raise Exception(f"Unknown type: {gtype}") # raise Exception(f"Unknown type: {gtype}")
# CommonSetup for all columns # # CommonSetup for all columns
if col: # if col:
col.set_resizable(True) # col.set_resizable(True)
col.set_expand(True) # col.set_expand(True)
col.set_property("sizing", Gtk.TreeViewColumnSizing.AUTOSIZE) # col.set_property("sizing", Gtk.TreeViewColumnSizing.AUTOSIZE)
col.set_property("alignment", 0.5) # col.set_property("alignment", 0.5)
col.set_sort_column_id(idx) # col.set_sort_column_id(idx)
tree_view.append_column(col) # tree_view.append_column(col)

View File

@ -1,6 +1,6 @@
import gi import gi
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "4.0")
from gi.repository import Gtk from gi.repository import Gtk
from ..models import VMBase from ..models import VMBase
@ -21,7 +21,7 @@ class VmMenu(Gtk.Menu):
menu_item = Gtk.MenuItem(label=item[0]) menu_item = Gtk.MenuItem(label=item[0])
menu_item.connect("activate", item[1]) menu_item.connect("activate", item[1])
self.append(menu_item) self.append(menu_item)
self.show_all() # self.show_all()
def start_vm(self, widget: Gtk.Widget) -> None: def start_vm(self, widget: Gtk.Widget) -> None:
print("start_vm") print("start_vm")

View File

@ -7,7 +7,7 @@ from clan_vm_manager.errors.show_error import show_error_dialog
from ..interfaces import Callbacks, InitialFlashValues from ..interfaces import Callbacks, InitialFlashValues
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "4.0")
from gi.repository import Gio, Gtk from gi.repository import Gio, Gtk
@ -29,19 +29,19 @@ class FlashUSBWindow(Gtk.ApplicationWindow):
# Initialize the main wincbsdow # Initialize the main wincbsdow
# self.cbs = cbs # self.cbs = cbs
self.set_title("cLAN Manager") self.set_title("cLAN Manager")
self.connect("delete-event", self.on_quit) # self.connect("delete-event", self.on_quit)
self.set_default_size(800, 600) self.set_default_size(800, 600)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, expand=True) vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, )
self.add(vbox) self.append(vbox)
button = Gtk.ToolButton() button = Gtk.ToolButton()
button.set_icon_name("go-previous") button.set_icon_name("go-previous")
button.connect("clicked", self.switch) button.connect("clicked", self.switch)
toolbar = Gtk.Toolbar(orientation=Gtk.Orientation.HORIZONTAL) # toolbar = Gtk.Toolbar(orientation=Gtk.Orientation.HORIZONTAL)
toolbar.add(button) # toolbar.add(button)
vbox.add(toolbar) # vbox.add(toolbar)
self.stack = Gtk.Stack() self.stack = Gtk.Stack()
@ -52,10 +52,10 @@ class FlashUSBWindow(Gtk.ApplicationWindow):
"Details", "Details",
) )
vbox.add(self.stack) vbox.append(self.stack)
# Must be called AFTER all components were added # Must be called AFTER all components were added
self.show_all() # self.show_all()
def switch(self, widget: Gtk.Widget) -> None: def switch(self, widget: Gtk.Widget) -> None:
pass pass

View File

@ -12,9 +12,11 @@ from clan_vm_manager.errors.show_error import show_error_dialog
from ..interfaces import Callbacks, InitialJoinValues from ..interfaces import Callbacks, InitialJoinValues
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "4.0")
gi.require_version("Adw", "1")
from gi.repository import GdkPixbuf, Gio, Gtk
from gi.repository import GdkPixbuf, Gio, Gtk, Adw
class Trust(Gtk.Box): class Trust(Gtk.Box):
@ -36,16 +38,16 @@ class Trust(Gtk.Box):
preserve_aspect_ratio=True, preserve_aspect_ratio=True,
) )
) )
layout = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, expand=True) layout = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
layout.set_border_width(20) # layout.set_border_width(20)
layout.set_spacing(20) layout.set_spacing(20)
if self.url is not None: if self.url is not None:
self.entry = Gtk.Label(label=str(self.url)) self.entry = Gtk.Label(label=str(self.url))
layout.add(icon) layout.append(icon)
layout.add(Gtk.Label(label="Clan URL")) layout.append(Gtk.Label(label="Clan URL"))
else: else:
layout.add(Gtk.Label(label="Enter Clan URL")) layout.append(Gtk.Label(label="Enter Clan URL"))
self.entry = Gtk.Entry() self.entry = Gtk.Entry()
# Autocomplete # Autocomplete
# TODO: provide intelligent suggestions # TODO: provide intelligent suggestions
@ -60,7 +62,7 @@ class Trust(Gtk.Box):
self.entry.set_completion(completion) self.entry.set_completion(completion)
self.entry.set_placeholder_text("clan://") self.entry.set_placeholder_text("clan://")
layout.add(self.entry) layout.append(self.entry)
if self.url is None: if self.url is None:
trust_button = Gtk.Button(label="Load cLAN-URL") trust_button = Gtk.Button(label="Load cLAN-URL")
@ -68,9 +70,9 @@ class Trust(Gtk.Box):
trust_button = Gtk.Button(label="Trust cLAN-URL") trust_button = Gtk.Button(label="Trust cLAN-URL")
trust_button.connect("clicked", self.on_trust_clicked) trust_button.connect("clicked", self.on_trust_clicked)
layout.add(trust_button) layout.append(trust_button)
self.set_center_widget(layout) self.append(layout)
def on_trust_clicked(self, widget: Gtk.Widget) -> None: def on_trust_clicked(self, widget: Gtk.Widget) -> None:
try: try:
@ -86,6 +88,7 @@ class Trust(Gtk.Box):
self.on_trust(uri.get_internal(), item.flake) self.on_trust(uri.get_internal(), item.flake)
except ClanError as e: except ClanError as e:
pass
show_error_dialog(e) show_error_dialog(e)
@ -103,34 +106,34 @@ class Details(Gtk.Box):
preserve_aspect_ratio=True, preserve_aspect_ratio=True,
) )
) )
layout = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, expand=True) layout = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, )
layout.set_border_width(20) # layout.set_border_width(20)
upper = Gtk.Box(orientation="vertical") upper = Gtk.Box(orientation="vertical")
upper.set_spacing(20) upper.set_spacing(20)
upper.add(Gtk.Label(label="Clan URL")) upper.append(Gtk.Label(label="Clan URL"))
upper.add(icon) upper.append(icon)
label = Gtk.Label(label=str(url)) label = Gtk.Label(label=str(url))
upper.add(label) upper.append(label)
description_label = Gtk.Label(label=flake.description) description_label = Gtk.Label(label=flake.description)
upper.add(description_label) upper.append(description_label)
lower = Gtk.Box(orientation="horizontal", expand=True) lower = Gtk.Box(orientation="horizontal", )
lower.set_spacing(20) lower.set_spacing(20)
join_button = Gtk.Button(label="Join") join_button = Gtk.Button(label="Join")
join_button.connect("clicked", self.on_join) join_button.connect("clicked", self.on_join)
join_action_area = Gtk.Box(orientation="horizontal", expand=False) join_action_area = Gtk.Box(orientation="horizontal", )
join_button_area = Gtk.Box(orientation="vertical", expand=False) join_button_area = Gtk.Box(orientation="vertical", )
join_action_area.pack_end(join_button_area, expand=False, fill=False, padding=0) join_action_area.append(join_button_area)
join_button_area.pack_end(join_button, expand=False, fill=False, padding=0) join_button_area.append(join_button)
join_details = Gtk.Label(label="Info") join_details = Gtk.Label(label="Info")
join_details_area = Gtk.Box(orientation="horizontal", expand=False) join_details_area = Gtk.Box(orientation="horizontal", )
join_label_area = Gtk.Box(orientation="vertical", expand=False) join_label_area = Gtk.Box(orientation="vertical", )
for info in [ for info in [
f"Memory: {flake.clan_name}", f"Memory: {flake.clan_name}",
@ -139,19 +142,19 @@ class Details(Gtk.Box):
]: ]:
details_label = Gtk.Label(label=info) details_label = Gtk.Label(label=info)
details_label.set_justify(Gtk.Justification.LEFT) details_label.set_justify(Gtk.Justification.LEFT)
join_label_area.pack_end(details_label, expand=False, fill=False, padding=0) join_label_area.append(details_label)
join_label_area.pack_end(join_details, expand=False, fill=False, padding=0) join_label_area.append(join_details)
join_details_area.pack_start( join_details_area.append(
join_label_area, expand=False, fill=False, padding=0 join_label_area
) )
lower.pack_start(join_details_area, expand=True, fill=True, padding=0) lower.append(join_details_area)
lower.pack_end(join_action_area, expand=True, fill=True, padding=0) lower.append(join_action_area)
layout.pack_start(upper, expand=False, fill=False, padding=0) layout.append(upper)
layout.add(lower) layout.append(lower)
self.add(layout) self.append(layout)
def on_join(self, widget: Gtk.Widget) -> None: def on_join(self, widget: Gtk.Widget) -> None:
# TODO: @Qubasa # TODO: @Qubasa
@ -163,21 +166,34 @@ class JoinWindow(Gtk.ApplicationWindow):
def __init__(self, initial_values: InitialJoinValues, cbs: Callbacks) -> None: def __init__(self, initial_values: InitialJoinValues, cbs: Callbacks) -> None:
super().__init__() super().__init__()
# Initialize the main wincbsdow # Initialize the main wincbsdow
self.cbs = cbs self.cbs = cbs
self.set_title("cLAN Manager") self.set_title("cLAN Manager")
self.connect("delete-event", self.on_quit) # self.connect("delete-event", self.on_quit)
self.set_default_size(800, 600) self.set_default_size(800, 600)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, expand=True) # menu = Gtk.Menu()
self.add(vbox) # menu_bar = Gtk.MenuBar()
button = Gtk.ToolButton() # main_menu = Gtk.MenuItem("Menu")
button.set_icon_name("go-previous") # menu_item = Gtk.MenuItem("Start", "Start the selected clan")
button.connect("clicked", self.switch)
toolbar = Gtk.Toolbar(orientation=Gtk.Orientation.HORIZONTAL) # menu_bar.append(main_menu)
toolbar.add(button) # main_menu.set_submenu(menu)
vbox.add(toolbar) # menu.append(menu_item)
# vbox.add(menu_bar)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
self.set_child(vbox)
# button = Gtk.ToolButton()
# button.set_icon_name("go-previous")
# button.connect("clicked", self.switch)
# toolbar = Gtk.Toolbar(orientation=Gtk.Orientation.HORIZONTAL)
# toolbar.add(button)
# vbox.add(toolbar)
self.stack = Gtk.Stack() self.stack = Gtk.Stack()
@ -188,12 +204,12 @@ class JoinWindow(Gtk.ApplicationWindow):
"Trust", "Trust",
) )
vbox.add(self.stack) vbox.append(self.stack)
# vbox.add(Gtk.Entry(text=str(initial_values.url))) # vbox.add(Gtk.Entry(text=str(initial_values.url)))
# Must be called AFTER all components were added # Must be called AFTER all components were added
self.show_all() # self.show_all()
def on_trust(self, url: str, flake: FlakeConfig) -> None: def on_trust(self, url: str, flake: FlakeConfig) -> None:
self.stack.add_titled( self.stack.add_titled(
@ -201,7 +217,7 @@ class JoinWindow(Gtk.ApplicationWindow):
"details", "details",
"Details", "Details",
) )
self.show_all() # self.show_all()
self.stack.set_visible_child_name("details") self.stack.set_visible_child_name("details")
def switch(self, widget: Gtk.Widget) -> None: def switch(self, widget: Gtk.Widget) -> None:

View File

@ -4,7 +4,7 @@ import gi
from ..models import VMBase, get_initial_vms from ..models import VMBase, get_initial_vms
gi.require_version("Gtk", "3.0") gi.require_version("Gtk", "4.0")
from gi.repository import Gio, Gtk from gi.repository import Gio, Gtk
@ -17,12 +17,12 @@ class OverviewWindow(Gtk.ApplicationWindow):
def __init__(self, cbs: Callbacks) -> None: def __init__(self, cbs: Callbacks) -> None:
super().__init__() super().__init__()
self.set_title("cLAN Manager") self.set_title("cLAN Manager")
self.connect("delete-event", self.on_quit) # self.connect("delete-event", self.on_quit)
self.set_default_size(800, 600) self.set_default_size(800, 600)
self.cbs = cbs self.cbs = cbs
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, expand=True) vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, )
self.add(vbox) self.set_child(vbox)
self.stack = Gtk.Stack() self.stack = Gtk.Stack()
clan_list = ClanList( clan_list = ClanList(
@ -45,10 +45,10 @@ class OverviewWindow(Gtk.ApplicationWindow):
"Edit", "Edit",
) )
vbox.add(self.stack) vbox.append(self.stack)
# Must be called AFTER all components were added # Must be called AFTER all components were added
self.show_all() # self.show_all()
def set_selected(self, sel: VMBase | None) -> None: def set_selected(self, sel: VMBase | None) -> None:
self.selected_vm = sel self.selected_vm = sel
@ -75,7 +75,7 @@ class OverviewWindow(Gtk.ApplicationWindow):
selected_vm=self.selected_vm, selected_vm=self.selected_vm,
) )
self.stack.add_titled(clan_list, "list", "List") self.stack.add_titled(clan_list, "list", "List")
self.show_all() # self.show_all()
self.stack.set_visible_child_name("list") self.stack.set_visible_child_name("list")
def remount_edit_view(self) -> None: def remount_edit_view(self) -> None:
@ -88,7 +88,7 @@ class OverviewWindow(Gtk.ApplicationWindow):
"edit", "edit",
"Edit", "Edit",
) )
self.show_all() # self.show_all()
self.stack.set_visible_child_name("edit") self.stack.set_visible_child_name("edit")
def on_quit(self, *args: Any) -> None: def on_quit(self, *args: Any) -> None:

View File

@ -4,13 +4,13 @@
, copyDesktopItems , copyDesktopItems
, pygobject3 , pygobject3
, wrapGAppsHook , wrapGAppsHook
, gtk3 , gtk4
, spice-gtk
, gnome , gnome
, gobject-introspection , gobject-introspection
, clan-cli , clan-cli
, makeDesktopItem , makeDesktopItem
, ipdb , ipdb
, libadwaita
}: }:
let let
source = ./.; source = ./.;
@ -33,7 +33,7 @@ python3.pkgs.buildPythonApplication {
gobject-introspection gobject-introspection
]; ];
buildInputs = [ spice-gtk gtk3 gnome.adwaita-icon-theme ]; buildInputs = [ gtk4 libadwaita gnome.adwaita-icon-theme ];
propagatedBuildInputs = [ pygobject3 clan-cli ]; propagatedBuildInputs = [ pygobject3 clan-cli ];
# also re-expose dependencies so we test them in CI # also re-expose dependencies so we test them in CI