From f4d01d2d9f7a921f40a3b192637959ddf9129669 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Wed, 8 Jul 2026 22:51:44 +0200 Subject: ... --- .../shell/quickshell-plugins/CMakeLists.txt | 22 + .../shell/quickshell-plugins/ListUnitsEntry.cpp | 41 + .../shell/quickshell-plugins/ListUnitsEntry.hpp | 26 + .../shell/quickshell-plugins/Systemd.cpp | 92 +- .../shell/quickshell-plugins/Systemd.hpp | 46 + .../shell/quickshell-plugins/default.nix | 2 + .../org.freedesktop.systemd1.Manager.xml | 36 +- .../org.freedesktop.systemd1.Service.xml | 1100 ++++++++++++++++++++ .../org.freedesktop.systemd1.Unit.xml | 359 +++++++ 9 files changed, 1707 insertions(+), 17 deletions(-) create mode 100644 accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.cpp create mode 100644 accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.hpp create mode 100644 accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Service.xml create mode 100644 accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Unit.xml (limited to 'accounts/gkleen@sif/shell/quickshell-plugins') diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/CMakeLists.txt b/accounts/gkleen@sif/shell/quickshell-plugins/CMakeLists.txt index 020c0515..6b4f0d48 100644 --- a/accounts/gkleen@sif/shell/quickshell-plugins/CMakeLists.txt +++ b/accounts/gkleen@sif/shell/quickshell-plugins/CMakeLists.txt @@ -114,6 +114,7 @@ qt_add_dbus_interface(DBUS_INTERFACES set_source_files_properties(org.freedesktop.systemd1.Manager.xml PROPERTIES CLASSNAME DBusSystemdManager NO_NAMESPACE TRUE + INCLUDE ListUnitsEntry.hpp ) qt_add_dbus_interface(DBUS_INTERFACES org.freedesktop.systemd1.Manager.xml @@ -138,6 +139,24 @@ qt_add_dbus_interface(DBUS_INTERFACES dbus_logind_session ) +set_source_files_properties(org.freedesktop.systemd1.Unit.xml PROPERTIES + CLASSNAME DBusSystemdUnit + NO_NAMESPACE TRUE +) +qt_add_dbus_interface(DBUS_INTERFACES + org.freedesktop.systemd1.Unit.xml + dbus_systemd_unit +) + +set_source_files_properties(org.freedesktop.systemd1.Service.xml PROPERTIES + CLASSNAME DBusSystemdService + NO_NAMESPACE TRUE +) +qt_add_dbus_interface(DBUS_INTERFACES + org.freedesktop.systemd1.Service.xml + dbus_systemd_service +) + set_source_files_properties(org.freedesktop.DBus.Properties.xml PROPERTIES CLASSNAME DBusProperties NO_NAMESPACE TRUE @@ -148,6 +167,7 @@ qt_add_dbus_interface(DBUS_INTERFACES ) include_directories(${CMAKE_SOURCE_DIR}/build) +include_directories(${QUICKSHELL_SRC}/src) target_compile_features(customplugin PUBLIC cxx_std_26) @@ -162,7 +182,9 @@ target_sources(customplugin PRIVATE FileSelector.cpp FileSelector.hpp KeePassXC.cpp KeePassXC.hpp Systemd.cpp Systemd.hpp + ListUnitsEntry.cpp ListUnitsEntry.hpp ${DBUS_INTERFACES} + ${QUICKSHELL_SRC}/src/core/model.cpp ${QUICKSHELL_SRC}/src/core/model.hpp ) install_qml_module(customplugin) diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.cpp b/accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.cpp new file mode 100644 index 00000000..c1f9537c --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.cpp @@ -0,0 +1,41 @@ +#include "ListUnitsEntry.hpp" + +void ListUnitsEntry::registerMetaType() { + qRegisterMetaType("ListUnitsEntry"); + qDBusRegisterMetaType(); +} + +QDBusArgument& operator<<(QDBusArgument& argument, const ListUnitsEntry& entry) { + argument.beginStructure(); + argument + << entry.primaryName + << entry.description + << entry.loadState + << entry.activeState + << entry.subState + << entry.followingUnit + << entry.unitPath + << entry.jobId + << entry.jobType + << entry.jobPath; + argument.endStructure(); + + return argument; +} +const QDBusArgument& operator>>(const QDBusArgument& argument, ListUnitsEntry& entry) { + argument.beginStructure(); + argument + >> entry.primaryName + >> entry.description + >> entry.loadState + >> entry.activeState + >> entry.subState + >> entry.followingUnit + >> entry.unitPath + >> entry.jobId + >> entry.jobType + >> entry.jobPath; + argument.endStructure(); + + return argument; +} diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.hpp b/accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.hpp new file mode 100644 index 00000000..15d789b9 --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell-plugins/ListUnitsEntry.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +struct ListUnitsEntry { + QString primaryName; + QString description; + QString loadState; + QString activeState; + QString subState; + QString followingUnit; + QDBusObjectPath unitPath; + uint jobId; + QString jobType; + QDBusObjectPath jobPath; + + friend QDBusArgument& operator<<(QDBusArgument& argument, const ListUnitsEntry& entry); + friend const QDBusArgument& operator>>(const QDBusArgument& argument, ListUnitsEntry& entry); + static void registerMetaType(); +}; + +Q_DECLARE_METATYPE(ListUnitsEntry) + +using ListUnitsResult = QList; +Q_DECLARE_METATYPE(ListUnitsResult) diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.cpp b/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.cpp index 308659e9..6376b527 100644 --- a/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.cpp +++ b/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.cpp @@ -8,7 +8,12 @@ #include #include +#include + Systemd::Systemd(QObject* parent) : QObject(parent) { + ListUnitsEntry::registerMetaType(); + qDBusRegisterMetaType(); + this->systemdManager = new DBusSystemdManager( "org.freedesktop.systemd1", "/org/freedesktop/systemd1", @@ -22,8 +27,9 @@ Systemd::Systemd(QObject* parent) : QObject(parent) { this ); + QDBusReply sessionPath = this->logindManager->GetSession("auto"); - qDebug() << sessionPath; + // qDebug() << sessionPath; this->logindSession = new DBusLogindSession( "org.freedesktop.login1", sessionPath.value().path(), @@ -42,6 +48,12 @@ Systemd::Systemd(QObject* parent) : QObject(parent) { QObject::connect(this->logindSession, &DBusLogindSession::Lock, this, &Systemd::lock); QObject::connect(this->logindSession, &DBusLogindSession::Unlock, this, &Systemd::unlock); QObject::connect(this->logindSessionProperties, &DBusProperties::PropertiesChanged, this, &Systemd::onLogindSessionPropertiesChanged); + this->systemdManager->Subscribe(); + QObject::connect(this->systemdManager, &DBusSystemdManager::UnitNew, this, &Systemd::onUserUnitNew); + QObject::connect(this->systemdManager, &DBusSystemdManager::UnitRemoved, this, &Systemd::onUserUnitRemoved); + + for (const auto& unit: this->systemdManager->ListUnits().value()) + this->onUserUnitNew(unit.primaryName, unit.unitPath); } void Systemd::onLogindSessionPropertiesChanged(const QString& interface_name, const QVariantMap& changed_properties, const QStringList& invalidated_properties) { @@ -50,6 +62,82 @@ void Systemd::onLogindSessionPropertiesChanged(const QString& interface_name, co if (changed_properties.contains("LockedHint") || invalidated_properties.contains("LockedHint")) emit this->lockedHintChanged(); } +void Systemd::onUserUnitNew(const QString& id, const QDBusObjectPath& object_path) { + for (auto unit: this->mUserUnits.valueList()) + if (unit->path() == object_path) + return; + + for (const auto& unit: this->systemdManager->ListUnits().value()) + if (unit.unitPath == object_path) { + this->mUserUnits.insertObject(new SystemdUnit(this, object_path, id)); + return; + } +} +void Systemd::onUserUnitRemoved(const QString& id, const QDBusObjectPath& object_path) { + std::set toRemove; + for (auto unit: this->mUserUnits.valueList()) + if (unit->path() == object_path) + toRemove.insert(unit); + + for (auto unit: toRemove) { + this->mUserUnits.removeObject(unit); + delete unit; + } +} + +SystemdUnit::SystemdUnit(QObject* parent, const QDBusObjectPath& path, const QString& id): QObject(parent), mPath(path), mId(id) { + this->mUnitProperties = new DBusProperties( + "org.freedesktop.systemd1", + this->path().path(), + QDBusConnection::sessionBus(), + this + ); +} +std::unique_ptr SystemdUnit::systemdUnit() { + return std::make_unique( + "org.freedesktop.systemd1", + this->path().path(), + QDBusConnection::sessionBus(), + nullptr + ); +} +std::unique_ptr SystemdUnit::systemdService() { + if (!this->id().endsWith(".service")) + return std::unique_ptr(); + + return std::make_unique( + "org.freedesktop.systemd1", + this->path().path(), + QDBusConnection::sessionBus(), + nullptr + ); +} +QList SystemdUnit::runtimeDirectory() { + if (std::unique_ptr systemdService = this->systemdService()) { + if (!this->mRuntimeDirectory) + this->mRuntimeDirectory = systemdService->runtimeDirectory(); + return *this->mRuntimeDirectory; + } + + return QList{}; +} +QString SystemdUnit::activeState() { + if (!this->mActiveState) { + QObject::connect(this->mUnitProperties, &DBusProperties::PropertiesChanged, this, &SystemdUnit::onUnitPropertiesChanged); + this->mActiveState = this->systemdUnit()->activeState(); + } + + return *this->mActiveState; +} + +const QDBusObjectPath& SystemdUnit::path() const { return this->mPath; } +const QString& SystemdUnit::id() const { return this->mId; } +void SystemdUnit::onUnitPropertiesChanged(const QString& interface_name, const QVariantMap& changed_properties, const QStringList& invalidated_properties) { + if (changed_properties.contains("ActiveState") || invalidated_properties.contains("ActiveState")) { + this->mActiveState = this->systemdUnit()->activeState(); + emit this->activeStateChanged(); + } +} void Systemd::stopUserUnit(const QString& unit, const QString& mode) { this->systemdManager->StopUnit(unit, mode); } @@ -63,6 +151,8 @@ void Systemd::lockSession() { this->logindSession->call("Lock"); } void Systemd::suspend() { this->logindManager->Suspend(true); } void Systemd::hibernate() { this->logindManager->Hibernate(true); } +ObjectModel* Systemd::userUnits() { return &this->mUserUnits; } + std::string SystemdInhibitorParams::toString(SystemdInhibitorParams::WhatItem what) { if (what == SystemdInhibitorParams::Shutdown) return "shutdown"; diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.hpp b/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.hpp index 615024d2..98f73d8f 100644 --- a/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.hpp +++ b/accounts/gkleen@sif/shell/quickshell-plugins/Systemd.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -11,8 +12,47 @@ #include "dbus_systemd_manager.h" #include "dbus_logind_manager.h" #include "dbus_logind_session.h" +#include "dbus_systemd_unit.h" +#include "dbus_systemd_service.h" #include "dbus_properties.h" +#include "core/model.hpp" + +class SystemdUnit : public QObject { + Q_OBJECT; + QML_ELEMENT; + QML_UNCREATABLE("SystemdUnits cannot be created directly"); + +public: + explicit SystemdUnit(QObject* parent, const QDBusObjectPath& path, const QString& id); + + Q_PROPERTY(QDBusObjectPath path READ path CONSTANT); + Q_PROPERTY(QString id READ id CONSTANT); + Q_PROPERTY(QList runtimeDirectory READ runtimeDirectory CONSTANT); + Q_PROPERTY(QString activeState READ activeState NOTIFY activeStateChanged); + + const QDBusObjectPath& path() const; + const QString& id() const; + QList runtimeDirectory(); + QString activeState(); + +signals: + void activeStateChanged(); + +private slots: + void onUnitPropertiesChanged(const QString& interface_name, const QVariantMap& changed_properties, const QStringList& invalidated_properties); + +private: + std::unique_ptr systemdUnit(); + std::unique_ptr systemdService(); + + DBusProperties* mUnitProperties; + QDBusObjectPath mPath; + QString mId; + std::optional mActiveState; + std::optional> mRuntimeDirectory; +}; + class Systemd : public QObject { Q_OBJECT; QML_SINGLETON; @@ -23,6 +63,7 @@ public: Q_PROPERTY(bool idleHint READ idleHint WRITE setIdleHint NOTIFY idleHintChanged) Q_PROPERTY(bool lockedHint READ lockedHint WRITE setLockedHint NOTIFY lockedHintChanged) + Q_PROPERTY(UntypedObjectModel* userUnits READ userUnits CONSTANT) Q_INVOKABLE void stopUserUnit(const QString& unit, const QString& mode); Q_INVOKABLE void setBrightness(const QString& subsystem, const QString& name, quint32 brightness); @@ -34,6 +75,7 @@ public: bool idleHint(); bool lockedHint(); + ObjectModel* userUnits(); signals: void shutdown(bool before); @@ -45,12 +87,16 @@ signals: private slots: void onLogindSessionPropertiesChanged(const QString& interface_name, const QVariantMap& changed_properties, const QStringList& invalidated_properties); + void onUserUnitNew(const QString& id, const QDBusObjectPath& objectPath); + void onUserUnitRemoved(const QString& id, const QDBusObjectPath& objectPath); private: DBusSystemdManager* systemdManager; DBusLogindManager* logindManager; DBusLogindSession* logindSession; DBusProperties* logindSessionProperties; + + ObjectModel mUserUnits{this}; }; class SystemdInhibitorParams : public QObject { diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/default.nix b/accounts/gkleen@sif/shell/quickshell-plugins/default.nix index 20a195eb..dfe93bca 100644 --- a/accounts/gkleen@sif/shell/quickshell-plugins/default.nix +++ b/accounts/gkleen@sif/shell/quickshell-plugins/default.nix @@ -5,6 +5,7 @@ , fmt , keepassxc , systemd +, quickshell }: stdenv.mkDerivation rec { @@ -24,6 +25,7 @@ stdenv.mkDerivation rec { cmakeFlags = [ (lib.cmakeFeature "INSTALL_QML_PREFIX" qt6.qtbase.qtQmlPrefix) + (lib.cmakeOptionType "string" "QUICKSHELL_SRC" (toString quickshell.src)) ]; LC_ALL = "C.UTF-8"; diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Manager.xml b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Manager.xml index b4f84a13..1dadbc55 100644 --- a/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Manager.xml +++ b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Manager.xml @@ -562,22 +562,26 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Service.xml b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Service.xml new file mode 100644 index 00000000..316dd080 --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Service.xml @@ -0,0 +1,1100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Unit.xml b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Unit.xml new file mode 100644 index 00000000..a554f513 --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell-plugins/org.freedesktop.systemd1.Unit.xml @@ -0,0 +1,359 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3