Merge pull request 'clan-vm-manager: Fixed assets folder not included' (#606) from Qubasa-main into main
This commit is contained in:
@@ -35,8 +35,9 @@ def list_history() -> list[HistoryEntry]:
|
|||||||
content: str = f.read()
|
content: str = f.read()
|
||||||
parsed: list[dict] = json.loads(content)
|
parsed: list[dict] = json.loads(content)
|
||||||
logs = [HistoryEntry(**p) for p in parsed]
|
logs = [HistoryEntry(**p) for p in parsed]
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError as ex:
|
||||||
print("Failed to load history")
|
print("Failed to load history. Invalid JSON.")
|
||||||
|
print(f"{user_history_file()}: {ex}")
|
||||||
|
|
||||||
return logs
|
return logs
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,37 @@
|
|||||||
import argparse
|
import argparse
|
||||||
from collections.abc import Callable
|
import sys
|
||||||
|
|
||||||
start_app: Callable | None = None
|
import gi
|
||||||
|
|
||||||
from .app import start_app
|
from .app import Application
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
|
||||||
|
|
||||||
|
def join_command(args: argparse.Namespace) -> None:
|
||||||
|
print("Joining the flake")
|
||||||
|
print(args.clan_uri)
|
||||||
|
|
||||||
|
|
||||||
|
def register_join_parser(parser: argparse.ArgumentParser) -> None:
|
||||||
|
parser.add_argument("clan_uri", type=str, help="machine in the flake to run")
|
||||||
|
parser.set_defaults(func=join_command)
|
||||||
|
|
||||||
|
|
||||||
|
def start_app(args: argparse.Namespace) -> None:
|
||||||
|
app = Application(args)
|
||||||
|
return app.run(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
parser = argparse.ArgumentParser(description="clan-vm-manager")
|
parser = argparse.ArgumentParser(description="clan-vm-manager")
|
||||||
|
subparser = parser.add_subparsers(
|
||||||
|
title="command",
|
||||||
|
description="command to execute",
|
||||||
|
help="the command to execute",
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
register_join_parser(subparser.add_parser("join", help="join a clan"))
|
||||||
parser.set_defaults(func=start_app)
|
parser.set_defaults(func=start_app)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
args.func(args)
|
args.func(args)
|
||||||
|
|||||||
@@ -6,34 +6,16 @@ from typing import Any
|
|||||||
|
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
from clan_vm_manager.models import VMBase
|
from .models import VMBase
|
||||||
|
|
||||||
gi.require_version("Gtk", "3.0")
|
gi.require_version("Gtk", "3.0")
|
||||||
from gi.repository import Gio, Gtk
|
from gi.repository import Gio, Gtk
|
||||||
|
|
||||||
from .constants import constants
|
from .constants import constants
|
||||||
|
from .ui.clan_join_page import ClanJoinPage
|
||||||
from .ui.clan_select_list import ClanEdit, ClanList
|
from .ui.clan_select_list import ClanEdit, ClanList
|
||||||
|
|
||||||
|
|
||||||
class ClanJoinPage(Gtk.Box):
|
|
||||||
def __init__(self, *, stack: Gtk.Stack) -> None:
|
|
||||||
super().__init__()
|
|
||||||
self.page = Gtk.Box(
|
|
||||||
orientation=Gtk.Orientation.VERTICAL, spacing=6, expand=True
|
|
||||||
)
|
|
||||||
self.set_border_width(10)
|
|
||||||
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):
|
class MainWindow(Gtk.ApplicationWindow):
|
||||||
def __init__(self, application: Gtk.Application) -> None:
|
def __init__(self, application: Gtk.Application) -> None:
|
||||||
super().__init__(application=application)
|
super().__init__(application=application)
|
||||||
@@ -75,7 +57,9 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||||||
|
|
||||||
def set_selected(self, sel: VMBase | None) -> None:
|
def set_selected(self, sel: VMBase | None) -> None:
|
||||||
self.selected_vm = sel
|
self.selected_vm = sel
|
||||||
print(f"APP selected + {self.selected_vm}")
|
|
||||||
|
if self.selected_vm:
|
||||||
|
print(f"APP selected + {self.selected_vm.name}")
|
||||||
|
|
||||||
def remount_list_view(self) -> None:
|
def remount_list_view(self) -> None:
|
||||||
widget = self.stack.get_child_by_name("list")
|
widget = self.stack.get_child_by_name("list")
|
||||||
@@ -107,7 +91,7 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||||||
|
|
||||||
|
|
||||||
class Application(Gtk.Application):
|
class Application(Gtk.Application):
|
||||||
def __init__(self) -> None:
|
def __init__(self, args: argparse.Namespace) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
application_id=constants["APPID"], flags=Gio.ApplicationFlags.FLAGS_NONE
|
application_id=constants["APPID"], flags=Gio.ApplicationFlags.FLAGS_NONE
|
||||||
)
|
)
|
||||||
@@ -132,8 +116,3 @@ class Application(Gtk.Application):
|
|||||||
# screen = Gdk.Screen.get_default()
|
# screen = Gdk.Screen.get_default()
|
||||||
# style_context = Gtk.StyleContext()
|
# style_context = Gtk.StyleContext()
|
||||||
# style_context.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
# style_context.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||||
|
|
||||||
|
|
||||||
def start_app(args: argparse.Namespace) -> None:
|
|
||||||
app = Application()
|
|
||||||
return app.run(sys.argv)
|
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ from pathlib import Path
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import clan_cli
|
import clan_cli
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("GdkPixbuf", "2.0")
|
||||||
from gi.repository import GdkPixbuf
|
from gi.repository import GdkPixbuf
|
||||||
|
|
||||||
from clan_vm_manager import assets
|
from clan_vm_manager import assets
|
||||||
@@ -40,6 +43,10 @@ class VMBase:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_idx(name: str) -> int:
|
||||||
|
return list(VMBase.name_to_type_map().keys()).index(name)
|
||||||
|
|
||||||
def list_data(self) -> OrderedDict[str, Any]:
|
def list_data(self) -> OrderedDict[str, Any]:
|
||||||
return OrderedDict(
|
return OrderedDict(
|
||||||
{
|
{
|
||||||
|
|||||||
26
pkgs/clan-vm-manager/clan_vm_manager/ui/clan_join_page.py
Normal file
26
pkgs/clan-vm-manager/clan_vm_manager/ui/clan_join_page.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
|
||||||
|
class ClanJoinPage(Gtk.Box):
|
||||||
|
def __init__(self, *, stack: Gtk.Stack) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.page = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=6, expand=True
|
||||||
|
)
|
||||||
|
self.set_border_width(10)
|
||||||
|
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")
|
||||||
@@ -133,7 +133,7 @@ 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:
|
||||||
print(f"on_select_vm: {vm}")
|
print(f"on_select_vm: {vm.name}")
|
||||||
if vm is None:
|
if vm is None:
|
||||||
self.toolbar.set_is_selected(False)
|
self.toolbar.set_is_selected(False)
|
||||||
else:
|
else:
|
||||||
@@ -215,7 +215,7 @@ class ClanListView(Gtk.Box):
|
|||||||
|
|
||||||
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):
|
||||||
if row[1] == vm.name: # TODO: Change to path
|
if row[VMBase.to_idx("Name")] == vm.name: # TODO: Change to path
|
||||||
return idx
|
return idx
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
@@ -229,16 +229,18 @@ class ClanListView(Gtk.Box):
|
|||||||
|
|
||||||
def insertVM(self, vm: VMBase) -> None:
|
def insertVM(self, vm: VMBase) -> None:
|
||||||
values = list(vm.list_data().values())
|
values = list(vm.list_data().values())
|
||||||
values[0] = GdkPixbuf.Pixbuf.new_from_file_at_scale(
|
icon_idx = VMBase.to_idx("Icon")
|
||||||
filename=values[0], width=64, height=64, preserve_aspect_ratio=True
|
values[icon_idx] = GdkPixbuf.Pixbuf.new_from_file_at_scale(
|
||||||
|
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()
|
||||||
if row is not None:
|
if row is not None:
|
||||||
print(f"Selected {model[row][1]}")
|
vm = VMBase(*model[row])
|
||||||
self.on_select_row(VMBase(*model[row]))
|
print(f"Selected {vm.name}")
|
||||||
|
self.on_select_row(vm)
|
||||||
|
|
||||||
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
|
||||||
@@ -247,24 +249,23 @@ class ClanListView(Gtk.Box):
|
|||||||
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:
|
||||||
VMBase(*model[row]).run()
|
vm = VMBase(*model[row])
|
||||||
|
vm.run()
|
||||||
|
|
||||||
|
|
||||||
def setColRenderers(tree_view: Gtk.TreeView) -> None:
|
def setColRenderers(tree_view: Gtk.TreeView) -> None:
|
||||||
for idx, (key, _) 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
|
||||||
match key:
|
|
||||||
case "Icon":
|
if key.startswith("_"):
|
||||||
|
continue
|
||||||
|
match gtype:
|
||||||
|
case GdkPixbuf.Pixbuf:
|
||||||
renderer = Gtk.CellRendererPixbuf()
|
renderer = Gtk.CellRendererPixbuf()
|
||||||
col = Gtk.TreeViewColumn(key, renderer, pixbuf=idx)
|
col = Gtk.TreeViewColumn(key, renderer, pixbuf=idx)
|
||||||
case "Name" | "URL":
|
case str: # noqa
|
||||||
renderer = Gtk.CellRendererText()
|
renderer = Gtk.CellRendererText()
|
||||||
col = Gtk.TreeViewColumn(key, renderer, text=idx)
|
col = Gtk.TreeViewColumn(key, renderer, text=idx)
|
||||||
case "Status":
|
|
||||||
renderer = Gtk.CellRendererText()
|
|
||||||
col = Gtk.TreeViewColumn(key, renderer, text=idx)
|
|
||||||
case _:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# CommonSetup for all columns
|
# CommonSetup for all columns
|
||||||
if col:
|
if col:
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ python3.pkgs.buildPythonApplication {
|
|||||||
desktopItems = [
|
desktopItems = [
|
||||||
(makeDesktopItem {
|
(makeDesktopItem {
|
||||||
name = "clan-vm-manager";
|
name = "clan-vm-manager";
|
||||||
# TODO: this subcommand is not implemented yet
|
|
||||||
exec = "clan-vm-manager join %u";
|
exec = "clan-vm-manager join %u";
|
||||||
desktopName = "CLan VM Manager";
|
desktopName = "CLan VM Manager";
|
||||||
startupWMClass = "clan";
|
startupWMClass = "clan";
|
||||||
|
|||||||
@@ -2,13 +2,15 @@
|
|||||||
requires = ["setuptools"]
|
requires = ["setuptools"]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "clan-vm-manager"
|
name = "clan-vm-manager"
|
||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
scripts = { clan-vm-manager = "clan_vm_manager:main" }
|
scripts = { clan-vm-manager = "clan_vm_manager:main" }
|
||||||
|
|
||||||
[tool.setuptools.package-data]
|
[tool.setuptools.package-data]
|
||||||
clan_vm_manager = ["*.glade"]
|
clan_vm_manager = ["**/assets/*"]
|
||||||
|
|
||||||
[tool.mypy]
|
[tool.mypy]
|
||||||
python_version = "3.11"
|
python_version = "3.11"
|
||||||
|
|||||||
@@ -12,5 +12,13 @@ mkShell {
|
|||||||
|
|
||||||
# prepend clan-cli for development
|
# prepend clan-cli for development
|
||||||
export PYTHONPATH=../clan-cli:$PYTHONPATH
|
export PYTHONPATH=../clan-cli:$PYTHONPATH
|
||||||
|
|
||||||
|
set -euox
|
||||||
|
# install desktop file
|
||||||
|
cp -f ${clan-vm-manager}/share/applications/clan-vm-manager.desktop ~/.local/share/applications/clan-vm-manager.desktop
|
||||||
|
sleep 2
|
||||||
|
sed -i "s|Exec=.*clan-vm-manager|Exec=${clan-vm-manager}/bin/clan-vm-manager|" ~/.local/share/applications/clan-vm-manager.desktop
|
||||||
|
xdg-mime default clan-vm-manager.desktop x-scheme-handler/clan
|
||||||
|
set +x
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user