diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/VoidShell/entrypoints/app.py b/VoidShell/entrypoints/app.py deleted file mode 100644 index ecd42f5..0000000 --- a/VoidShell/entrypoints/app.py +++ /dev/null @@ -1,5 +0,0 @@ -import gi -gi.require_version('Gtk', '3.0') -from gi.repository import GLib, Gtk - - diff --git a/pyproject.toml b/pyproject.toml index 31dc340..ff19105 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,3 +23,6 @@ black = "^24.10.0" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" + +[tool.poetry.scripts] +VoidShell = 'voidshell.entrypoints.shell:main' diff --git a/voidshell/__init__.py b/voidshell/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/voidshell/__pycache__/__init__.cpython-312.pyc b/voidshell/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..4d6dc83 Binary files /dev/null and b/voidshell/__pycache__/__init__.cpython-312.pyc differ diff --git a/voidshell/__pycache__/__init__.cpython-313.pyc b/voidshell/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..c2804eb Binary files /dev/null and b/voidshell/__pycache__/__init__.cpython-313.pyc differ diff --git a/voidshell/__pycache__/versions.cpython-312.pyc b/voidshell/__pycache__/versions.cpython-312.pyc new file mode 100644 index 0000000..7d4540f Binary files /dev/null and b/voidshell/__pycache__/versions.cpython-312.pyc differ diff --git a/voidshell/dbus_clients/__init__.py b/voidshell/dbus_clients/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/voidshell/dbus_clients/__pycache__/__init__.cpython-313.pyc b/voidshell/dbus_clients/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..ac6a7e6 Binary files /dev/null and b/voidshell/dbus_clients/__pycache__/__init__.cpython-313.pyc differ diff --git a/voidshell/dbus_clients/systemd_networkd/__init__.py b/voidshell/dbus_clients/systemd_networkd/__init__.py new file mode 100644 index 0000000..280109c --- /dev/null +++ b/voidshell/dbus_clients/systemd_networkd/__init__.py @@ -0,0 +1,6 @@ +from .link import ( + OrgFreedesktopNetwork1DHCPv4ClientInterface as DHCPv4ClientInterface, + OrgFreedesktopNetwork1DHCPv6ClientInterface as DHCPv6ClientInterface, + OrgFreedesktopNetwork1LinkInterface as LinkInterface, +) +from .network1 import OrgFreedesktopNetwork1ManagerInterface as NetworkManagerInterface diff --git a/voidshell/dbus_clients/systemd_networkd/__pycache__/link.cpython-313.pyc b/voidshell/dbus_clients/systemd_networkd/__pycache__/link.cpython-313.pyc new file mode 100644 index 0000000..4140521 Binary files /dev/null and b/voidshell/dbus_clients/systemd_networkd/__pycache__/link.cpython-313.pyc differ diff --git a/voidshell/dbus_clients/systemd_networkd/__pycache__/network1.cpython-313.pyc b/voidshell/dbus_clients/systemd_networkd/__pycache__/network1.cpython-313.pyc new file mode 100644 index 0000000..e995ac7 Binary files /dev/null and b/voidshell/dbus_clients/systemd_networkd/__pycache__/network1.cpython-313.pyc differ diff --git a/voidshell/dbus_clients/systemd_networkd/link.py b/voidshell/dbus_clients/systemd_networkd/link.py new file mode 100644 index 0000000..c289b20 --- /dev/null +++ b/voidshell/dbus_clients/systemd_networkd/link.py @@ -0,0 +1,267 @@ +from __future__ import annotations + +from typing import Any, Dict, List, Tuple + +from sdbus import ( + DbusDeprecatedFlag, + DbusInterfaceCommonAsync, + DbusNoReplyFlag, + DbusPropertyConstFlag, + DbusPropertyEmitsChangeFlag, + DbusPropertyEmitsInvalidationFlag, + DbusPropertyExplicitFlag, + DbusUnprivilegedFlag, + dbus_method_async, + dbus_property_async, + dbus_signal_async, +) + + +class OrgFreedesktopNetwork1DHCPv6ClientInterface( + DbusInterfaceCommonAsync, + interface_name="org.freedesktop.network1.DHCPv6Client", +): + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def state(self) -> str: + raise NotImplementedError + + +class OrgFreedesktopNetwork1DHCPv4ClientInterface( + DbusInterfaceCommonAsync, + interface_name="org.freedesktop.network1.DHCPv4Client", +): + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def state(self) -> str: + raise NotImplementedError + + +class OrgFreedesktopNetwork1LinkInterface( + DbusInterfaceCommonAsync, + interface_name="org.freedesktop.network1.Link", +): + @dbus_method_async( + input_signature="as", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_ntp( + self, + servers: List[str], + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="a(iay)", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_dns( + self, + addresses: List[Tuple[int, bytes]], + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="a(iayqs)", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_dnsex( + self, + addresses: List[Tuple[int, bytes, int, str]], + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="a(sb)", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_domains( + self, + domains: List[Tuple[str, bool]], + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="b", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_default_route( + self, + enable: bool, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="s", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_llmnr( + self, + mode: str, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="s", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_multicast_dns( + self, + mode: str, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="s", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_dnsover_tls( + self, + mode: str, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="s", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_dnssec( + self, + mode: str, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="as", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_dnssecnegative_trust_anchors( + self, + names: List[str], + ) -> None: + raise NotImplementedError + + @dbus_method_async( + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def revert_ntp( + self, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def revert_dns( + self, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def renew( + self, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def force_renew( + self, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def reconfigure( + self, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + result_signature="s", + result_args_names=('json',), + flags=DbusUnprivilegedFlag, + ) + async def describe( + self, + ) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def operational_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def carrier_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def address_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def ipv4_address_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def ipv6_address_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def online_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def administrative_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="(tt)", + ) + def bit_rates(self) -> Tuple[int, int]: + raise NotImplementedError + diff --git a/voidshell/dbus_clients/systemd_networkd/network1.py b/voidshell/dbus_clients/systemd_networkd/network1.py new file mode 100644 index 0000000..7bc7d8c --- /dev/null +++ b/voidshell/dbus_clients/systemd_networkd/network1.py @@ -0,0 +1,318 @@ +from __future__ import annotations + +from typing import Any, Dict, List, Tuple + +from sdbus import ( + DbusDeprecatedFlag, + DbusInterfaceCommonAsync, + DbusNoReplyFlag, + DbusPropertyConstFlag, + DbusPropertyEmitsChangeFlag, + DbusPropertyEmitsInvalidationFlag, + DbusPropertyExplicitFlag, + DbusUnprivilegedFlag, + dbus_method_async, + dbus_property_async, + dbus_signal_async, +) + + +class OrgFreedesktopNetwork1ManagerInterface( + DbusInterfaceCommonAsync, + interface_name="org.freedesktop.network1.Manager", +): + @dbus_method_async( + result_signature="a(iso)", + result_args_names=('links',), + flags=DbusUnprivilegedFlag, + ) + async def list_links( + self, + ) -> List[Tuple[int, str, str]]: + raise NotImplementedError + + @dbus_method_async( + input_signature="s", + result_signature="io", + result_args_names=('ifindex', 'path'), + flags=DbusUnprivilegedFlag, + ) + async def get_link_by_name( + self, + name: str, + ) -> Tuple[int, str]: + raise NotImplementedError + + @dbus_method_async( + input_signature="i", + result_signature="so", + result_args_names=('name', 'path'), + flags=DbusUnprivilegedFlag, + ) + async def get_link_by_index( + self, + ifindex: int, + ) -> Tuple[str, str]: + raise NotImplementedError + + @dbus_method_async( + input_signature="ias", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_link_ntp( + self, + ifindex: int, + servers: List[str], + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="ia(iay)", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_link_dns( + self, + ifindex: int, + addresses: List[Tuple[int, bytes]], + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="ia(iayqs)", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_link_dnsex( + self, + ifindex: int, + addresses: List[Tuple[int, bytes, int, str]], + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="ia(sb)", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_link_domains( + self, + ifindex: int, + domains: List[Tuple[str, bool]], + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="ib", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_link_default_route( + self, + ifindex: int, + enable: bool, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="is", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_link_llmnr( + self, + ifindex: int, + mode: str, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="is", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_link_multicast_dns( + self, + ifindex: int, + mode: str, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="is", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_link_dnsover_tls( + self, + ifindex: int, + mode: str, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="is", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_link_dnssec( + self, + ifindex: int, + mode: str, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="ias", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def set_link_dnssecnegative_trust_anchors( + self, + ifindex: int, + names: List[str], + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="i", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def revert_link_ntp( + self, + ifindex: int, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="i", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def revert_link_dns( + self, + ifindex: int, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="i", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def renew_link( + self, + ifindex: int, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="i", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def force_renew_link( + self, + ifindex: int, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="i", + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def reconfigure_link( + self, + ifindex: int, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + result_args_names=(), + flags=DbusUnprivilegedFlag, + ) + async def reload( + self, + ) -> None: + raise NotImplementedError + + @dbus_method_async( + input_signature="i", + result_signature="s", + result_args_names=('json',), + flags=DbusUnprivilegedFlag, + ) + async def describe_link( + self, + ifindex: int, + ) -> str: + raise NotImplementedError + + @dbus_method_async( + result_signature="s", + result_args_names=('json',), + flags=DbusUnprivilegedFlag, + ) + async def describe( + self, + ) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def operational_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def carrier_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def address_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def ipv4_address_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def ipv6_address_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="s", + flags=DbusPropertyEmitsChangeFlag, + ) + def online_state(self) -> str: + raise NotImplementedError + + @dbus_property_async( + property_signature="t", + flags=DbusPropertyConstFlag, + ) + def namespace_id(self) -> int: + raise NotImplementedError + + @dbus_property_async( + property_signature="u", + ) + def namespace_nsid(self) -> int: + raise NotImplementedError + diff --git a/voidshell/entrypoints/__init__.py b/voidshell/entrypoints/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/voidshell/entrypoints/__pycache__/__init__.cpython-312.pyc b/voidshell/entrypoints/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..3d2603b Binary files /dev/null and b/voidshell/entrypoints/__pycache__/__init__.cpython-312.pyc differ diff --git a/voidshell/entrypoints/__pycache__/shell.cpython-312.pyc b/voidshell/entrypoints/__pycache__/shell.cpython-312.pyc new file mode 100644 index 0000000..4327362 Binary files /dev/null and b/voidshell/entrypoints/__pycache__/shell.cpython-312.pyc differ diff --git a/voidshell/entrypoints/shell.py b/voidshell/entrypoints/shell.py new file mode 100644 index 0000000..df5940c --- /dev/null +++ b/voidshell/entrypoints/shell.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +from .. import versions +from ..utilities.config import Configuration +from gi.repository import Astal, Gio, AstalIO +from gi.events import GLibEventLoopPolicy +from pathlib import Path +import sys +import logging +import asyncio +from sdbus import request_default_bus_name_async, sd_bus_open_user, set_default_bus + +asyncio.set_event_loop_policy(GLibEventLoopPolicy()) + +logger = logging.getLogger(__name__) + + +class App(Astal.Application): + + def do_astal_application_request(self, msg: str, conn: Gio.SocketConnection): + print(msg) + AstalIO.write_sock(conn, "hello") + + def do_activate(self) -> None: + self.hold() + logger.info("Loading configuration") + config = Configuration(Path("~/.config/VoidShell/config").expanduser()) + self.apply_css(str(config.css_file), True) + set_default_bus(sd_bus_open_user()) + asyncio.get_event_loop().create_task( + request_default_bus_name_async("dev.ezri.VoidShell") + ) + logger.info("VoidShell up and running") + # TODO: implement application startup logic + + +def doStartup(app: App): + logging.basicConfig(level=logging.INFO) + app.acquire_socket() + app.run(None) + + +def main(): + app = App(instance_name="VoidShell") + try: + doStartup(app) + except Exception: + print("Error: VoidShell is already running") + sys.exit(1) diff --git a/voidshell/services/__init__.py b/voidshell/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/voidshell/services/network/service.py b/voidshell/services/network/service.py new file mode 100644 index 0000000..f671be2 --- /dev/null +++ b/voidshell/services/network/service.py @@ -0,0 +1,11 @@ +from gi.repository import GObject +from voidshell.dbus_clients.systemd_networkd import ( + NetworkManagerInterface, + LinkInterface, +) + + +class NetworkService(GObject): + """ + Collects and formats network data from a variety of sources + """ diff --git a/VoidShell/services/sway/config.py b/voidshell/services/sway/config.py similarity index 100% rename from VoidShell/services/sway/config.py rename to voidshell/services/sway/config.py diff --git a/VoidShell/services/sway/sway.py b/voidshell/services/sway/sway.py similarity index 100% rename from VoidShell/services/sway/sway.py rename to voidshell/services/sway/sway.py diff --git a/VoidShell/services/sway/tree.py b/voidshell/services/sway/tree.py similarity index 100% rename from VoidShell/services/sway/tree.py rename to voidshell/services/sway/tree.py diff --git a/voidshell/services/workspaces/__init__.py b/voidshell/services/workspaces/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/VoidShell/services/workspaces/backend.py b/voidshell/services/workspaces/backend.py similarity index 94% rename from VoidShell/services/workspaces/backend.py rename to voidshell/services/workspaces/backend.py index 13c80cc..a8674ed 100644 --- a/VoidShell/services/workspaces/backend.py +++ b/voidshell/services/workspaces/backend.py @@ -47,6 +47,11 @@ class AbstractWorkspaceBackend(ABC): """Configure an output""" pass + @abstractmethod + async def disableOutput(self, output: str): + """Disable an output""" + pass + @abstractmethod def onWorkspaceChange(self, callback): """Register a callback to be called when the workspace changes""" @@ -62,6 +67,10 @@ class AbstractWorkspaceBackend(ABC): """Register a callback to be called when the binding mode changes, in compositors that support it""" pass + @abstractmethod + async def getOutputs(self) -> list[OutputAdapter]: + """Get the currently connected outputs""" + @abstractmethod @property def name(self) -> str: diff --git a/VoidShell/services/workspaces/config.py b/voidshell/services/workspaces/config.py similarity index 100% rename from VoidShell/services/workspaces/config.py rename to voidshell/services/workspaces/config.py diff --git a/VoidShell/services/workspaces/scoring.py b/voidshell/services/workspaces/scoring.py similarity index 100% rename from VoidShell/services/workspaces/scoring.py rename to voidshell/services/workspaces/scoring.py diff --git a/VoidShell/services/workspaces/tree.py b/voidshell/services/workspaces/tree.py similarity index 74% rename from VoidShell/services/workspaces/tree.py rename to voidshell/services/workspaces/tree.py index 7410bfe..92c9850 100644 --- a/VoidShell/services/workspaces/tree.py +++ b/voidshell/services/workspaces/tree.py @@ -5,8 +5,9 @@ from sdbus import ( dbus_property_async, dbus_signal_async, ) -from .config import WorkspaceConfig, GroupConfig, ContextConfig, Config -from .backend import getBackend, WorkspaceAdapter +from .config import WorkspaceConfig, GroupConfig, Context as ContextConfig, Config +from .backend import getBackend, WorkspaceAdapter, OutputAdapter +from . import scoring import logging logger = logging.getLogger(__name__) @@ -292,9 +293,11 @@ class Group(GObject.Object): def __init__(self, name: str): super().__init__() if "/" in name: - self._proxify(name) + self._proxify("dev.ezri.voidshell", name) else: - self._proxify(f"/dev/ezri/voidshell/workspaces/group/{name}") + self._proxify( + "dev.ezri.voidshell", f"/dev/ezri/voidshell/workspaces/group/{name}" + ) def __init__(self, definition: GroupConfig): super().__init__() @@ -305,12 +308,124 @@ class Group(GObject.Object): manager._getWorkspaceByCompositorIndex(ws) for ws in definition.get("workspaces") ] + for workspace in self.workspaces: + workspace.addGroup(self) self.output_name = None self.focused = False self._focused_workspace = None self.context = None self._dbusObject = Group.DBusObject(self) + async def configure(self, output: str = None) -> str: + """Configure the group. If no output is provided, the group will be reconfigured on its + current output. If it is not currently active, an output is required.""" + adapter = getBackend() + if output is None: + if self.output_name is None: + return "Output required for inactive group" + output = self.output_name + + self.output_name = output + try: + await adapter.configureOutput(output, self.definition) + except Exception as e: + self.output_name = None + return str(e) + return "OK" + + async def focus(self): + """Focus the group.""" + adapter = getBackend() + if self.output_name is None: + return "Group not active, cannot focus" + try: + await adapter.focusOutput(self.output_name) + except Exception as e: + return str(e) + return "OK" + + async def disable(self): + """Disable the group.""" + adapter = getBackend() + if self.output_name is None: + return "Don't have an output name, cannot disable group." + try: + await adapter.disableOutput(self.output_name) + except Exception as e: + return str(e) + return "OK" + + +class Context( + GObject.Object, +): + + class DBusInterface( + DbusInterfaceCommonAsync, + interface_name="dev.ezri.voidshell.workspaces.Context", + ): + def __init__(self, context: "Context" = None): + super().__init__() + self.context = context + + @dbus_signal_async() + async def Activated(self): + raise NotImplementedError + + @dbus_signal_async() + async def Deactivated(self): + raise NotImplementedError + + @dbus_method_async(input_signature="", result_signature="i") + async def GetCompatabilityScore(self): + raise NotImplementedError + + @dbus_property_async("b") + def Active(self): + raise NotImplementedError + + @dbus_property_async("ao") + def Groups(self): + raise NotImplementedError + + class DBusObject(DBusInterface): + + def __init__(self, context: "Context"): + super().__init__(context) + self.export_to_dbus( + f"/dev/ezri/voidshell/workspaces/context/{context.name}" + ) + + class DBusProxy(DBusInterface): + + def __init__(self, name: str): + super().__init__() + if "/" in name: + self._proxify("dev.ezri.voidshell", name) + else: + self._proxify( + "dev.ezri.voidshell", + f"/dev/ezri/voidshell/workspaces/context/{name}", + ) + + def __init__(self, definition: ContextConfig): + super().__init__() + self.definition = definition + self.name = definition["name"] + self.groups = {group["name"]: Group(group) for group in definition["groups"]} + self.priority = int(self.definition.get("priority", 0)) + + async def score(self, outputs: list[OutputAdapter] = None): + + if outputs is None: + adapter = getBackend() + outputs = await adapter.getOutputs() + + return scoring.computePerfectScore(self.definition, outputs) + + async def activate(self): + pass + class Manager( GObject.Object, @@ -326,7 +441,7 @@ class Manager( self.tree = tree @dbus_signal_async() - def Updated(self): + async def Updated(self): raise NotImplementedError @dbus_method_async(input_signature="s", result_signature="s") diff --git a/voidshell/utilities/__pycache__/config.cpython-312.pyc b/voidshell/utilities/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000..ffcf008 Binary files /dev/null and b/voidshell/utilities/__pycache__/config.cpython-312.pyc differ diff --git a/voidshell/utilities/config.py b/voidshell/utilities/config.py new file mode 100644 index 0000000..8bccfd5 --- /dev/null +++ b/voidshell/utilities/config.py @@ -0,0 +1,32 @@ +""" +Configuration management for VoidShell +""" + +import configparser +from pathlib import Path +from gi.repository import AstalIO + + +class Configuration: + + _scss_file: Path | None + css_file: Path + + def compile_scss(self): + if self._scss_file.is_file(): + AstalIO.Process.execv(["sass", str(self._scss_file), str(self.css_file)]) + + def __init__(self, config_file: Path): + + parser = configparser.ConfigParser() + parser.read(config_file) + + if "style" in parser and "stylesheet" in parser["style"]: + self.css_file = config_file / Path(parser["style"]) + else: + self.css_file = config_file / "style.css" + + if self.css_file.suffix == "scss": + self._scss_file = self.css_file + self.css_file = self._scss_file.with_suffix("css") + self.compile_scss() diff --git a/voidshell/versions.py b/voidshell/versions.py new file mode 100644 index 0000000..f09d7e6 --- /dev/null +++ b/voidshell/versions.py @@ -0,0 +1,13 @@ +import gi + +gi.require_version("AstalIO", "0.1") +gi.require_version("Astal", "3.0") +gi.require_version("Gtk", "3.0") +gi.require_version("Gdk", "3.0") +gi.require_version("Gio", "2.0") +gi.require_version("GObject", "2.0") + +_astal_libs = ["Apps", "Battery", "Bluetooth", "Mpris", "Notifd", "PowerProfiles", "Wp"] + +for lib in _astal_libs: + gi.require_version(f"Astal{lib}", "0.1")