Merge pull request 'UI: Added joining multiple clans one after another over clan url' (#826) from Qubasa-main into main
This commit is contained in:
@@ -1,10 +1,5 @@
|
|||||||
import argparse
|
|
||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
from clan_cli.clan_uri import ClanURI
|
|
||||||
from clan_cli.custom_logger import setup_logging
|
|
||||||
|
|
||||||
from clan_vm_manager.models.interfaces import ClanConfig
|
|
||||||
|
|
||||||
from .app import MainApplication
|
from .app import MainApplication
|
||||||
|
|
||||||
@@ -12,53 +7,5 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
parser = argparse.ArgumentParser(description="clan-vm-manager")
|
app = MainApplication()
|
||||||
|
return app.run(sys.argv)
|
||||||
parser.add_argument("--debug", action="store_true", help="enable debug mode")
|
|
||||||
|
|
||||||
# Add join subcommand
|
|
||||||
subparser = parser.add_subparsers(
|
|
||||||
title="command",
|
|
||||||
description="command to execute",
|
|
||||||
help="the command to execute",
|
|
||||||
)
|
|
||||||
register_join_parser(subparser.add_parser("join", help="join a clan"))
|
|
||||||
|
|
||||||
register_overview_parser(subparser.add_parser("overview", help="overview screen"))
|
|
||||||
|
|
||||||
# Executed when no command is given
|
|
||||||
parser.set_defaults(func=show_overview)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
if args.debug:
|
|
||||||
setup_logging("DEBUG", root_log_name=__name__.split(".")[0])
|
|
||||||
else:
|
|
||||||
setup_logging("INFO", root_log_name=__name__.split(".")[0])
|
|
||||||
|
|
||||||
log.debug("Debug logging enabled")
|
|
||||||
log.info("Info logging enabled")
|
|
||||||
|
|
||||||
args.func(args)
|
|
||||||
|
|
||||||
|
|
||||||
def show_join(args: argparse.Namespace) -> None:
|
|
||||||
app = MainApplication(
|
|
||||||
config=ClanConfig(url=args.clan_uri, initial_view="list"),
|
|
||||||
)
|
|
||||||
return app.run()
|
|
||||||
|
|
||||||
|
|
||||||
def register_join_parser(parser: argparse.ArgumentParser) -> None:
|
|
||||||
parser.add_argument("clan_uri", type=ClanURI, help="clan URI to join")
|
|
||||||
parser.set_defaults(func=show_join)
|
|
||||||
|
|
||||||
|
|
||||||
def show_overview(args: argparse.Namespace) -> None:
|
|
||||||
app = MainApplication(
|
|
||||||
config=ClanConfig(url=None, initial_view="list"),
|
|
||||||
)
|
|
||||||
return app.run()
|
|
||||||
|
|
||||||
|
|
||||||
def register_overview_parser(parser: argparse.ArgumentParser) -> None:
|
|
||||||
parser.set_defaults(func=show_overview)
|
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any, ClassVar
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
gi.require_version("Gtk", "4.0")
|
gi.require_version("Gtk", "4.0")
|
||||||
gi.require_version("Adw", "1")
|
gi.require_version("Adw", "1")
|
||||||
|
|
||||||
|
from clan_cli.custom_logger import setup_logging
|
||||||
from gi.repository import Adw, Gdk, Gio, Gtk
|
from gi.repository import Adw, Gdk, Gio, Gtk
|
||||||
|
|
||||||
from clan_vm_manager.models.interfaces import ClanConfig
|
from clan_vm_manager.models.interfaces import ClanConfig
|
||||||
|
from clan_vm_manager.models.use_join import GLib, GObject
|
||||||
from clan_vm_manager.models.use_vms import VMS
|
from clan_vm_manager.models.use_vms import VMS
|
||||||
|
|
||||||
from .constants import constants
|
from .constants import constants
|
||||||
@@ -20,15 +22,54 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class MainApplication(Adw.Application):
|
class MainApplication(Adw.Application):
|
||||||
def __init__(self, config: ClanConfig) -> None:
|
__gsignals__: ClassVar = {
|
||||||
|
"join_request": (GObject.SignalFlags.RUN_FIRST, None, [str]),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
application_id=constants["APPID"], flags=Gio.ApplicationFlags.FLAGS_NONE
|
*args,
|
||||||
|
application_id=constants["APPID"],
|
||||||
|
flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE,
|
||||||
|
**kwargs,
|
||||||
)
|
)
|
||||||
self.config = config
|
|
||||||
|
self.add_main_option(
|
||||||
|
"debug",
|
||||||
|
ord("d"),
|
||||||
|
GLib.OptionFlags.NONE,
|
||||||
|
GLib.OptionArg.NONE,
|
||||||
|
"enable debug mode",
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
self.win: Adw.ApplicationWindow | None = None
|
self.win: Adw.ApplicationWindow | None = None
|
||||||
self.connect("shutdown", self.on_shutdown)
|
self.connect("shutdown", self.on_shutdown)
|
||||||
self.connect("activate", self.show_window)
|
self.connect("activate", self.show_window)
|
||||||
|
|
||||||
|
def do_command_line(self, command_line: Any) -> int:
|
||||||
|
log.info("Do command line executed")
|
||||||
|
options = command_line.get_options_dict()
|
||||||
|
# convert GVariantDict -> GVariant -> dict
|
||||||
|
options = options.end().unpack()
|
||||||
|
|
||||||
|
if "debug" in options:
|
||||||
|
setup_logging("DEBUG", root_log_name=__name__.split(".")[0])
|
||||||
|
else:
|
||||||
|
setup_logging("INFO", root_log_name=__name__.split(".")[0])
|
||||||
|
log.debug("Debug logging enabled")
|
||||||
|
|
||||||
|
args = command_line.get_arguments()
|
||||||
|
|
||||||
|
self.activate()
|
||||||
|
|
||||||
|
if len(args) > 1:
|
||||||
|
log.debug(f"Join request: {args[1]}")
|
||||||
|
uri = args[1]
|
||||||
|
self.emit("join_request", uri)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
def on_shutdown(self, app: Gtk.Application) -> None:
|
def on_shutdown(self, app: Gtk.Application) -> None:
|
||||||
log.debug("Shutting down")
|
log.debug("Shutting down")
|
||||||
VMS.use().kill_all()
|
VMS.use().kill_all()
|
||||||
@@ -39,7 +80,7 @@ class MainApplication(Adw.Application):
|
|||||||
def show_window(self, app: Any = None) -> None:
|
def show_window(self, app: Any = None) -> None:
|
||||||
if not self.win:
|
if not self.win:
|
||||||
self.init_style()
|
self.init_style()
|
||||||
self.win = MainWindow(config=self.config)
|
self.win = MainWindow(config=ClanConfig(initial_view="list"))
|
||||||
self.win.set_application(self)
|
self.win.set_application(self)
|
||||||
self.win.present()
|
self.win.present()
|
||||||
|
|
||||||
|
|||||||
BIN
pkgs/clan-vm-manager/clan_vm_manager/assets/cLAN--black.png
Normal file
BIN
pkgs/clan-vm-manager/clan_vm_manager/assets/cLAN--black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 108 KiB |
BIN
pkgs/clan-vm-manager/clan_vm_manager/assets/clan_black.png
Normal file
BIN
pkgs/clan-vm-manager/clan_vm_manager/assets/clan_black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 108 KiB |
BIN
pkgs/clan-vm-manager/clan_vm_manager/assets/clan_white.png
Normal file
BIN
pkgs/clan-vm-manager/clan_vm_manager/assets/clan_white.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 106 KiB |
@@ -2,7 +2,6 @@ from dataclasses import dataclass
|
|||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
from clan_cli.clan_uri import ClanURI
|
|
||||||
|
|
||||||
gi.require_version("Gtk", "4.0")
|
gi.require_version("Gtk", "4.0")
|
||||||
|
|
||||||
@@ -10,7 +9,6 @@ gi.require_version("Gtk", "4.0")
|
|||||||
@dataclass
|
@dataclass
|
||||||
class ClanConfig:
|
class ClanConfig:
|
||||||
initial_view: str
|
initial_view: str
|
||||||
url: ClanURI | None
|
|
||||||
|
|
||||||
|
|
||||||
class VMStatus(StrEnum):
|
class VMStatus(StrEnum):
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ class Join:
|
|||||||
This method can add multiple join requests if called subsequently for each request.
|
This method can add multiple join requests if called subsequently for each request.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if url.get_id() in [item.url.get_id() for item in self.list_store]:
|
||||||
|
log.info(f"Join request already exists: {url}")
|
||||||
|
return
|
||||||
|
|
||||||
def after_join(item: JoinValue, _: Any) -> None:
|
def after_join(item: JoinValue, _: Any) -> None:
|
||||||
self.discard(item)
|
self.discard(item)
|
||||||
Clans.use().refresh()
|
Clans.use().refresh()
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from typing import Any
|
|||||||
|
|
||||||
import gi
|
import gi
|
||||||
from clan_cli import ClanError, history
|
from clan_cli import ClanError, history
|
||||||
|
from clan_cli.clan_uri import ClanURI
|
||||||
|
|
||||||
from clan_vm_manager.models.interfaces import ClanConfig
|
from clan_vm_manager.models.interfaces import ClanConfig
|
||||||
from clan_vm_manager.models.use_join import Join, JoinValue
|
from clan_vm_manager.models.use_join import Join, JoinValue
|
||||||
@@ -47,12 +48,12 @@ class ClanList(Gtk.Box):
|
|||||||
def __init__(self, config: ClanConfig) -> None:
|
def __init__(self, config: ClanConfig) -> None:
|
||||||
super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
||||||
|
|
||||||
|
app = Gio.Application.get_default()
|
||||||
|
app.connect("join_request", self.on_join_request)
|
||||||
|
|
||||||
groups = Clans.use()
|
groups = Clans.use()
|
||||||
join = Join.use()
|
join = Join.use()
|
||||||
|
|
||||||
if config.url:
|
|
||||||
join.push(config.url, self.after_join)
|
|
||||||
|
|
||||||
self.__init_machines = history.add.list_history()
|
self.__init_machines = history.add.list_history()
|
||||||
self.join_boxed_list = create_boxed_list(
|
self.join_boxed_list = create_boxed_list(
|
||||||
model=join.list_store, render_row=self.render_join_row
|
model=join.list_store, render_row=self.render_join_row
|
||||||
@@ -228,6 +229,11 @@ class ClanList(Gtk.Box):
|
|||||||
dialog.set_transient_for(p) # set the parent window of the dialog
|
dialog.set_transient_for(p) # set the parent window of the dialog
|
||||||
dialog.choose()
|
dialog.choose()
|
||||||
|
|
||||||
|
def on_join_request(self, widget: Any, url: str) -> None:
|
||||||
|
log.debug("Join request: %s", url)
|
||||||
|
clan_uri = ClanURI.from_str(url)
|
||||||
|
Join.use().push(clan_uri, self.after_join)
|
||||||
|
|
||||||
def after_join(self, item: JoinValue) -> None:
|
def after_join(self, item: JoinValue) -> None:
|
||||||
# If the join request list is empty disable the shadow artefact
|
# If the join request list is empty disable the shadow artefact
|
||||||
if not Join.use().list_store.get_n_items():
|
if not Join.use().list_store.get_n_items():
|
||||||
|
|||||||
@@ -58,8 +58,9 @@ python3.pkgs.buildPythonApplication {
|
|||||||
desktopItems = [
|
desktopItems = [
|
||||||
(makeDesktopItem {
|
(makeDesktopItem {
|
||||||
name = "clan-vm-manager";
|
name = "clan-vm-manager";
|
||||||
exec = "clan-vm-manager join %u";
|
exec = "clan-vm-manager %u";
|
||||||
desktopName = "CLan VM Manager";
|
icon = ./clan_vm_manager/assets/clan_white.png;
|
||||||
|
desktopName = "cLAN Manager";
|
||||||
startupWMClass = "clan";
|
startupWMClass = "clan";
|
||||||
mimeTypes = [ "x-scheme-handler/clan" ];
|
mimeTypes = [ "x-scheme-handler/clan" ];
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user