From ae9a80c1f012686c1f65fce7ce76fdd1b77b0b71 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Wed, 23 Sep 2026 21:08:35 +0200 Subject: ... --- .../shell/quickshell-plugins/CMakeLists.txt | 190 ++++ .../shell/quickshell-plugins/Chrono.cpp | 83 ++ .../shell/quickshell-plugins/Chrono.hpp | 55 + .../shell/quickshell-plugins/FileSelector.cpp | 102 ++ .../shell/quickshell-plugins/FileSelector.hpp | 52 + .../shell/quickshell-plugins/KeePassXC.cpp | 18 + .../shell/quickshell-plugins/KeePassXC.hpp | 21 + .../shell/quickshell-plugins/ListUnitsEntry.cpp | 41 + .../shell/quickshell-plugins/ListUnitsEntry.hpp | 26 + .../shell/quickshell-plugins/Systemd.cpp | 288 +++++ .../shell/quickshell-plugins/Systemd.hpp | 193 ++++ .../shell/quickshell-plugins/customplugin.h | 7 + .../shell/quickshell-plugins/default.nix | 32 + .../org.freedesktop.DBus.Properties.xml | 28 + .../org.freedesktop.login1.Manager.xml | 445 ++++++++ .../org.freedesktop.login1.Session.xml | 146 +++ .../org.freedesktop.systemd1.Manager.xml | 821 +++++++++++++++ .../org.freedesktop.systemd1.Service.xml | 1100 ++++++++++++++++++++ .../org.freedesktop.systemd1.Unit.xml | 359 +++++++ 19 files changed, 4007 insertions(+) create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/CMakeLists.txt create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/Chrono.cpp create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/Chrono.hpp create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/FileSelector.cpp create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/FileSelector.hpp create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/KeePassXC.cpp create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/KeePassXC.hpp create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/ListUnitsEntry.cpp create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/ListUnitsEntry.hpp create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.cpp create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.hpp create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/customplugin.h create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/default.nix create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.DBus.Properties.xml create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.login1.Manager.xml create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.login1.Session.xml create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.systemd1.Manager.xml create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.systemd1.Service.xml create mode 100644 accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.systemd1.Unit.xml (limited to 'accounts/gkleen@skadhi/shell/quickshell-plugins') diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/CMakeLists.txt b/accounts/gkleen@skadhi/shell/quickshell-plugins/CMakeLists.txt new file mode 100644 index 00000000..6b4f0d48 --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/CMakeLists.txt @@ -0,0 +1,190 @@ +set(INSTALL_QMLDIR "" CACHE STRING "QML install dir") +set(INSTALL_QML_PREFIX "" CACHE STRING "QML install prefix") + +# There doesn't seem to be a standard cross-distro qml install path. +if ("${INSTALL_QMLDIR}" STREQUAL "" AND "${INSTALL_QML_PREFIX}" STREQUAL "") + message(WARNING "Neither INSTALL_QMLDIR nor INSTALL_QML_PREFIX is set. QML modules will not be installed.") +else() + if ("${INSTALL_QMLDIR}" STREQUAL "") + set(QML_FULL_INSTALLDIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_QML_PREFIX}") + else() + set(QML_FULL_INSTALLDIR "${INSTALL_QMLDIR}") + endif() + + message(STATUS "QML install dir: ${QML_FULL_INSTALLDIR}") +endif() + +# Install a given target as a QML module. This is mostly pulled from ECM, as there does not seem +# to be an official way to do it. +# see https://github.com/KDE/extra-cmake-modules/blob/fe0f606bf7f222e36f7560fd7a2c33ef993e23bb/modules/ECMQmlModule6.cmake#L160 +function(install_qml_module arg_TARGET) + if (NOT DEFINED QML_FULL_INSTALLDIR) + return() + endif() + + qt_query_qml_module(${arg_TARGET} + URI module_uri + VERSION module_version + PLUGIN_TARGET module_plugin_target + TARGET_PATH module_target_path + QMLDIR module_qmldir + TYPEINFO module_typeinfo + QML_FILES module_qml_files + RESOURCES module_resources + ) + + set(module_dir "${QML_FULL_INSTALLDIR}/${module_target_path}") + + if (NOT TARGET "${module_plugin_target}") + message(FATAL_ERROR "install_qml_modules called for a target without a plugin") + endif() + + get_target_property(target_type "${arg_TARGET}" TYPE) + if (NOT "${target_type}" STREQUAL "STATIC_LIBRARY") + install( + TARGETS "${arg_TARGET}" + LIBRARY DESTINATION "${module_dir}" + RUNTIME DESTINATION "${module_dir}" + ) + + install( + TARGETS "${module_plugin_target}" + LIBRARY DESTINATION "${module_dir}" + RUNTIME DESTINATION "${module_dir}" + ) + endif() + + install(FILES "${module_qmldir}" DESTINATION "${module_dir}") + install(FILES "${module_typeinfo}" DESTINATION "${module_dir}") + + # Install QML files + list(LENGTH module_qml_files num_files) + if (NOT "${module_qml_files}" MATCHES "NOTFOUND" AND ${num_files} GREATER 0) + qt_query_qml_module(${arg_TARGET} QML_FILES_DEPLOY_PATHS qml_files_deploy_paths) + + math(EXPR last_index "${num_files} - 1") + foreach(i RANGE 0 ${last_index}) + list(GET module_qml_files ${i} src_file) + list(GET qml_files_deploy_paths ${i} deploy_path) + get_filename_component(dst_name "${deploy_path}" NAME) + get_filename_component(dest_dir "${deploy_path}" DIRECTORY) + install(FILES "${src_file}" DESTINATION "${module_dir}/${dest_dir}" RENAME "${dst_name}") + endforeach() + endif() + + # Install resources + list(LENGTH module_resources num_files) + if (NOT "${module_resources}" MATCHES "NOTFOUND" AND ${num_files} GREATER 0) + qt_query_qml_module(${arg_TARGET} RESOURCES_DEPLOY_PATHS resources_deploy_paths) + + math(EXPR last_index "${num_files} - 1") + foreach(i RANGE 0 ${last_index}) + list(GET module_resources ${i} src_file) + list(GET resources_deploy_paths ${i} deploy_path) + get_filename_component(dst_name "${deploy_path}" NAME) + get_filename_component(dest_dir "${deploy_path}" DIRECTORY) + install(FILES "${src_file}" DESTINATION "${module_dir}/${dest_dir}" RENAME "${dst_name}") + endforeach() + endif() +endfunction() + + +cmake_minimum_required(VERSION 3.20) +project(custom LANGUAGES CXX) + +find_package(Qt6 REQUIRED COMPONENTS Core Qml DBus) + +qt_standard_project_setup(REQUIRES 6.6) + +qt6_policy(SET QTP0001 NEW) +qt6_add_qml_module(customplugin + URI "Custom" + PLUGIN_TARGET customplugin +) + +set_source_files_properties(org.keepassxc.KeePassXC.MainWindow.xml PROPERTIES + CLASSNAME DBusKeePassXC + NO_NAMESPACE TRUE +) +qt_add_dbus_interface(DBUS_INTERFACES + org.keepassxc.KeePassXC.MainWindow.xml + dbus_keepassxc +) + +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 + dbus_systemd_manager +) + +set_source_files_properties(org.freedesktop.login1.Manager.xml PROPERTIES + CLASSNAME DBusLogindManager + NO_NAMESPACE TRUE +) +qt_add_dbus_interface(DBUS_INTERFACES + org.freedesktop.login1.Manager.xml + dbus_logind_manager +) + +set_source_files_properties(org.freedesktop.login1.Session.xml PROPERTIES + CLASSNAME DBusLogindSession + NO_NAMESPACE TRUE +) +qt_add_dbus_interface(DBUS_INTERFACES + org.freedesktop.login1.Session.xml + 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 +) +qt_add_dbus_interface(DBUS_INTERFACES + org.freedesktop.DBus.Properties.xml + dbus_properties +) + +include_directories(${CMAKE_SOURCE_DIR}/build) +include_directories(${QUICKSHELL_SRC}/src) + +target_compile_features(customplugin PUBLIC cxx_std_26) + +target_link_libraries(customplugin PRIVATE + Qt6::Core + Qt6::Qml + Qt6::DBus +) + +target_sources(customplugin PRIVATE + Chrono.cpp Chrono.hpp + 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@skadhi/shell/quickshell-plugins/Chrono.cpp b/accounts/gkleen@skadhi/shell/quickshell-plugins/Chrono.cpp new file mode 100644 index 00000000..22b3469b --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/Chrono.cpp @@ -0,0 +1,83 @@ +#include "Chrono.hpp" + +#include +#include +#include + +Chrono::Chrono(QObject* parent): QObject(parent) { + QObject::connect(&this->timer, &QTimer::timeout, this, &Chrono::onTimeout); + this->update(); +} + +bool Chrono::enabled() const { return this->mEnabled; } + +void Chrono::setEnabled(bool enabled) { + if (enabled == this->mEnabled) return; + this->mEnabled = enabled; + emit this->enabledChanged(); + this->update(); +} + +Chrono::Precision Chrono::precision() const { return this->mPrecision; } + +void Chrono::setPrecision(Chrono::Precision precision) { + if (precision == this->mPrecision) return; + this->mPrecision = precision; + emit this->precisionChanged(); + this->update(); +} + +void Chrono::onTimeout() { + this->setTime(this->targetTime); + this->schedule(this->targetTime); +} + +void Chrono::update() { + if (this->mEnabled) { + this->setTime(std::chrono::time_point()); + this->schedule(std::chrono::time_point()); + } else { + this->timer.stop(); + } +} + +void Chrono::setTime(const std::chrono::time_point& targetTime) { + using namespace std::chrono_literals; + + auto currentTime = std::chrono::system_clock::now(); + auto offset = std::chrono::duration_cast(targetTime - currentTime); + this->currentTime = abs(offset) < 500ms ? targetTime : currentTime; + + switch (this->mPrecision) { + case Chrono::Hours: this->currentTime = std::chrono::time_point_cast(this->currentTime); + case Chrono::Minutes: this->currentTime = std::chrono::time_point_cast(this->currentTime); + case Chrono::Seconds: this->currentTime = std::chrono::time_point_cast(this->currentTime); + } + + emit this->dateChanged(); +} + +void Chrono::schedule(const std::chrono::time_point& targetTime) { + using namespace std::chrono_literals; + + auto currentTime = std::chrono::system_clock::now(); + auto offset = std::chrono::duration_cast(targetTime - currentTime); + auto nextTime = abs(offset) < 500ms ? targetTime : currentTime; + + switch (this->mPrecision) { + case Chrono::Hours: nextTime = std::chrono::time_point_cast(nextTime) + 1h; + case Chrono::Minutes: nextTime = std::chrono::time_point_cast(nextTime) + 1min; + case Chrono::Seconds: nextTime = std::chrono::time_point_cast(nextTime) + 1s; + } + + this->targetTime = nextTime; + this->timer.start(std::chrono::duration_cast(nextTime - currentTime)); +} + +QString Chrono::format(const QString& fmt) const { + return QString::fromStdString(std::format(std::runtime_format(fmt.toStdString()), std::chrono::zoned_time(std::chrono::current_zone(), std::chrono::time_point_cast(this->currentTime)))); +} + +QDateTime Chrono::date() const { + return QDateTime::fromStdTimePoint(std::chrono::time_point_cast(this->currentTime)); +} diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/Chrono.hpp b/accounts/gkleen@skadhi/shell/quickshell-plugins/Chrono.hpp new file mode 100644 index 00000000..04080187 --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/Chrono.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include + +#include +#include +#include + +#include + +class Chrono : public QObject { + Q_OBJECT; + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged); + Q_PROPERTY(Chrono::Precision precision READ precision WRITE setPrecision NOTIFY precisionChanged); + Q_PROPERTY(QDateTime date READ date NOTIFY dateChanged) + QML_ELEMENT; + +public: + enum Precision : quint8 { + Hours = 1, + Minutes = 2, + Seconds = 3, + }; + Q_ENUM(Precision); + + explicit Chrono(QObject* parent = nullptr); + + bool enabled() const; + void setEnabled(bool enabled); + + Chrono::Precision precision() const; + void setPrecision(Chrono::Precision precision); + + Q_INVOKABLE QString format(const QString& fmt) const; + + QDateTime date() const; + +signals: + void enabledChanged(); + void precisionChanged(); + void dateChanged(); + +private slots: + void onTimeout(); + +private: + bool mEnabled = true; + Chrono::Precision mPrecision = Chrono::Seconds; + QTimer timer; + std::chrono::time_point currentTime, targetTime; + + void update(); + void setTime(const std::chrono::time_point& targetTime); + void schedule(const std::chrono::time_point& targetTime); +}; diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/FileSelector.cpp b/accounts/gkleen@skadhi/shell/quickshell-plugins/FileSelector.cpp new file mode 100644 index 00000000..d7051d2a --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/FileSelector.cpp @@ -0,0 +1,102 @@ +#include "FileSelector.hpp" + +#include +#include +#include +#include + +#include +#include + +namespace fs = std::filesystem; + +FileSelector::FileSelector(QObject* parent): QObject(parent) { + QObject::connect(&this->timer, &QTimer::timeout, this, &FileSelector::onTimeout); + this->timer.setTimerType(Qt::PreciseTimer); +} + +QString FileSelector::directory() const { + return QString::fromStdString(this->mDirectory->string()); +} +void FileSelector::setDirectory(QString directory) { + this->mDirectory = directory.toStdString(); + if (this->mDirectory && this->mEpoch) + this->update(); + emit this->directoryChanged(); +} + +unsigned int FileSelector::epoch() const { + return std::chrono::duration_cast(*this->mEpoch).count(); +} +void FileSelector::setEpoch(unsigned int epoch) { + this->mEpoch = std::chrono::milliseconds{epoch}; + if (this->mDirectory && this->mEpoch) + this->update(); + emit this->epochChanged(); +} + +QString FileSelector::seed() const { + return this->mSeed; +} +void FileSelector::setSeed(QString seed) { + this->mSeed = seed; + emit this->seedChanged(); + if (this->mDirectory && this->mEpoch) + emit this->selectedChanged(); +} + +QString FileSelector::selected() const { + if (!this->mDirectory || !this->mEpoch) + return QString(); + + std::vector shuffled(this->mFiles.begin(), this->mFiles.end()); + std::sort(shuffled.begin(), shuffled.end()); + + auto currentTime = std::chrono::system_clock::now(); + uint64_t currentEpoch = currentTime.time_since_epoch() / *this->mEpoch; + std::chrono::milliseconds timeInEpoch = std::chrono::duration_cast(currentTime.time_since_epoch()) % *this->mEpoch; + + std::ostringstream seed; + seed << this->mSeed.size() << ";" << this->mSeed.toStdString() << ";"; + seed << *this->mEpoch << ";"; + seed << currentEpoch << ";"; + seed << this->mDirectory->string().size() << ";" << *this->mDirectory << ";"; + seed << this->mFiles.size() << ";"; + for (const fs::path& p: this->mFiles) + seed << p.string().size() << ";" << p << ";"; + + std::vector v; + v.reserve(seed.str().size()); + for (const char& c: seed.str()) + v.push_back(c); + + std::seed_seq engine_seed(v.begin(), v.end()); + std::mt19937 g(engine_seed); + std::shuffle(shuffled.begin(), shuffled.end(), g); + + std::vector::size_type ix = shuffled.size() * timeInEpoch / *this->mEpoch; + return QString::fromStdString((*this->mDirectory / shuffled[ix]).string()); +} + +void FileSelector::onTimeout() { + if (!this->mFiles.size()) + return; + + auto currentTime = std::chrono::system_clock::now(); + uint64_t currentMinorEpoch = currentTime.time_since_epoch() / (*this->mEpoch / this->mFiles.size()); + auto nextTime = std::chrono::time_point((currentMinorEpoch + 1) * (*this->mEpoch / this->mFiles.size())); + this->timer.start(std::chrono::duration_cast(nextTime - currentTime)); + + emit this->selectedChanged(); +} + +void FileSelector::update() { + this->mFiles = std::set{}; + for (const fs::directory_entry& entry: + fs::recursive_directory_iterator(*this->mDirectory, fs::directory_options::follow_directory_symlink)) + { + this->mFiles.insert(fs::relative(entry, *this->mDirectory)); + } + + this->onTimeout(); +} diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/FileSelector.hpp b/accounts/gkleen@skadhi/shell/quickshell-plugins/FileSelector.hpp new file mode 100644 index 00000000..72c4f2a7 --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/FileSelector.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include + +class FileSelector : public QObject { + Q_OBJECT; + Q_PROPERTY(QString directory READ directory WRITE setDirectory NOTIFY directoryChanged REQUIRED); + Q_PROPERTY(unsigned int epoch READ epoch WRITE setEpoch NOTIFY epochChanged REQUIRED); + Q_PROPERTY(QString seed READ seed WRITE setSeed NOTIFY seedChanged); + Q_PROPERTY(QString selected READ selected NOTIFY selectedChanged); + QML_ELEMENT; + +public: + explicit FileSelector(QObject* parent = nullptr); + + QString directory() const; + void setDirectory(QString directory); + + unsigned int epoch() const; + void setEpoch(unsigned int epoch); + + QString seed() const; + void setSeed(QString seed); + + QString selected() const; + +signals: + void directoryChanged(); + void epochChanged(); + void seedChanged(); + void selectedChanged(); + +private slots: + void onTimeout(); + +private: + std::optional mDirectory; + std::optional mEpoch; + std::set mFiles; + QString mSeed; + QTimer timer; + + void update(); +}; diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/KeePassXC.cpp b/accounts/gkleen@skadhi/shell/quickshell-plugins/KeePassXC.cpp new file mode 100644 index 00000000..f6e4dd6e --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/KeePassXC.cpp @@ -0,0 +1,18 @@ +#include "KeePassXC.hpp" + +#include + +KeePassXC::KeePassXC() { + this->service = new DBusKeePassXC(DBusKeePassXC::staticInterfaceName(), "/keepassxc", QDBusConnection::sessionBus(), this); +} +KeePassXC::~KeePassXC() { + if (this->service) + delete this->service; +} + +void KeePassXC::lockAllDatabases() { + if (!this->service) + return; + + this->service->lockAllDatabases(); +} diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/KeePassXC.hpp b/accounts/gkleen@skadhi/shell/quickshell-plugins/KeePassXC.hpp new file mode 100644 index 00000000..c4cd71e0 --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/KeePassXC.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "dbus_keepassxc.h" + +#include +#include + +class KeePassXC : public QObject { + Q_OBJECT; + QML_SINGLETON; + QML_ELEMENT; + +public: + explicit KeePassXC(); + ~KeePassXC(); + + Q_INVOKABLE void lockAllDatabases(); + +private: + DBusKeePassXC* service = nullptr; +}; diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/ListUnitsEntry.cpp b/accounts/gkleen@skadhi/shell/quickshell-plugins/ListUnitsEntry.cpp new file mode 100644 index 00000000..c1f9537c --- /dev/null +++ b/accounts/gkleen@skadhi/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@skadhi/shell/quickshell-plugins/ListUnitsEntry.hpp b/accounts/gkleen@skadhi/shell/quickshell-plugins/ListUnitsEntry.hpp new file mode 100644 index 00000000..15d789b9 --- /dev/null +++ b/accounts/gkleen@skadhi/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@skadhi/shell/quickshell-plugins/Systemd.cpp b/accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.cpp new file mode 100644 index 00000000..6376b527 --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.cpp @@ -0,0 +1,288 @@ +#include "Systemd.hpp" + +#include + +#include +#include +#include +#include +#include + +#include + +Systemd::Systemd(QObject* parent) : QObject(parent) { + ListUnitsEntry::registerMetaType(); + qDBusRegisterMetaType(); + + this->systemdManager = new DBusSystemdManager( + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + QDBusConnection::sessionBus(), + this + ); + this->logindManager = new DBusLogindManager( + "org.freedesktop.login1", + "/org/freedesktop/login1", + QDBusConnection::systemBus(), + this + ); + + + QDBusReply sessionPath = this->logindManager->GetSession("auto"); + // qDebug() << sessionPath; + this->logindSession = new DBusLogindSession( + "org.freedesktop.login1", + sessionPath.value().path(), + QDBusConnection::systemBus(), + this + ); + this->logindSessionProperties = new DBusProperties( + "org.freedesktop.login1", + sessionPath.value().path(), + QDBusConnection::systemBus(), + this + ); + + QObject::connect(this->logindManager, &DBusLogindManager::PrepareForShutdown, this, &Systemd::shutdown); + QObject::connect(this->logindManager, &DBusLogindManager::PrepareForSleep, this, &Systemd::sleep); + 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) { + if (changed_properties.contains("IdleHint") || invalidated_properties.contains("IdleHint")) + emit this->idleHintChanged(); + 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); } + +void Systemd::setBrightness(const QString& subsystem, const QString& name, quint32 brightness) { this->logindSession->SetBrightness(subsystem, name, brightness); } + +bool Systemd::idleHint() { return this->logindSession->idleHint(); } +void Systemd::setIdleHint(bool idle) { this->logindSession->SetIdleHint(idle); } +bool Systemd::lockedHint() { return this->logindSession->lockedHint(); } +void Systemd::setLockedHint(bool locked) { this->logindSession->SetLockedHint(locked); } +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"; + else if (what == SystemdInhibitorParams::Sleep) + return "sleep"; + else if (what == SystemdInhibitorParams::Idle) + return "idle"; + else if (what == SystemdInhibitorParams::HandlePowerKey) + return "handle-power-key"; + else if (what == SystemdInhibitorParams::HandleSuspendKey) + return "handle-suspend-key"; + else if (what == SystemdInhibitorParams::HandleHibernateKey) + return "handle-hibernate-key"; + else if (what == SystemdInhibitorParams::HandleLidSwitch) + return "handle-lid-switch"; + return ""; +} + +std::string SystemdInhibitorParams::toString(SystemdInhibitorParams::What what) { + std::ostringstream res; + bool first = true; + for (const WhatItem& item: SystemdInhibitorParams::allWhatItems) { + if (!(what & item)) + continue; + + if (!first) + res << ":"; + else + first = false; + res << SystemdInhibitorParams::toString(item); + } + return res.str(); +} + +std::string SystemdInhibitorParams::toString(SystemdInhibitorParams::Mode mode) { + if (mode == SystemdInhibitorParams::Block) + return "block"; + else if (mode == SystemdInhibitorParams::BlockWeak) + return "block-weak"; + else if (mode == SystemdInhibitorParams::Delay) + return "delay"; + return ""; +} + +bool SystemdInhibitor::enabled() const { return static_cast(this->activeInhibitor); } +void SystemdInhibitor::setEnabled(bool enabled) { + this->mEnabled = enabled; + + if (enabled) + this->update(); + else + this->release(); +} + +SystemdInhibitorParams::What SystemdInhibitor::what() const { return this->mWhat; } +void SystemdInhibitor::setWhat(SystemdInhibitorParams::What what) { + this->mWhat = what; + this->update(); +} + +QString SystemdInhibitor::who() const { return this->mWho; } +void SystemdInhibitor::setWho(QString who) { + this->mWho = who; + this->update(); +} + +QString SystemdInhibitor::why() const { return this->mWhy; } +void SystemdInhibitor::setWhy(QString why) { + this->mWhy = why; + this->update(); +} + +SystemdInhibitorParams::Mode SystemdInhibitor::mode() const { return this->mMode; } +void SystemdInhibitor::setMode(SystemdInhibitorParams::Mode mode) { + this->mMode = mode; + this->update(); +} + +SystemdInhibitor::ActiveSystemdInhibitor::ActiveSystemdInhibitor(SystemdInhibitorParams::What what_, QString who_, QString why_, SystemdInhibitorParams::Mode mode_): what(what_), who(who_), why(why_), mode(mode_) { + DBusLogindManager logindManager( + "org.freedesktop.login1", + "/org/freedesktop/login1", + QDBusConnection::systemBus() + ); + QDBusReply fd_ = logindManager.Inhibit(QString::fromStdString(SystemdInhibitorParams::toString(what)), who, why, QString::fromStdString(SystemdInhibitorParams::toString(mode))); + if (fd_.error().isValid()) + throw fd_.error(); + this->fd = ::dup(fd_.value().fileDescriptor()); +} +SystemdInhibitor::ActiveSystemdInhibitor::~ActiveSystemdInhibitor() { + if (this->fd != -1) + ::close(this->fd); +} + +void SystemdInhibitor::release() { + if (!this->activeInhibitor) + return; + + this->activeInhibitor.reset(); + emit this->enabledChanged(); +} + +void SystemdInhibitor::update() { + if (!this->mWhat || this->mWho.isEmpty() || this->mWhy.isEmpty() || !this->mMode || !this->mEnabled) + if (this->activeInhibitor) + this->release(); + else + return; + + if (this->activeInhibitor && this->mWhat == this->activeInhibitor->what && this->mWho == this->activeInhibitor->who && this->mWhy == this->activeInhibitor->why && this->mMode == this->activeInhibitor->mode) + return; + + std::unique_ptr otherInhibitor; + try { + otherInhibitor.reset(new SystemdInhibitor::ActiveSystemdInhibitor(this->mWhat, this->mWho, this->mWhy, this->mMode)); + } catch (const QDBusError& err) { + qCritical().noquote() + << err.name().toStdString() << " " << err.message().toStdString(); + return; + } + this->activeInhibitor.swap(otherInhibitor); + + if (!otherInhibitor && this->activeInhibitor) + emit this->enabledChanged(); + if (otherInhibitor && otherInhibitor->what != this->activeInhibitor->what) + emit this->whatChanged(); + if (otherInhibitor && otherInhibitor->who != this->activeInhibitor->who) + emit this->whoChanged(); + if (otherInhibitor && otherInhibitor->why != this->activeInhibitor->why) + emit this->whyChanged(); + if (otherInhibitor && otherInhibitor->mode != this->activeInhibitor->mode) + emit this->modeChanged(); +} diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.hpp b/accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.hpp new file mode 100644 index 00000000..98f73d8f --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/Systemd.hpp @@ -0,0 +1,193 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +#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; + QML_ELEMENT; + +public: + explicit Systemd(QObject* parent = nullptr); + + 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); + Q_INVOKABLE void setIdleHint(bool idle); + Q_INVOKABLE void setLockedHint(bool locked); + Q_INVOKABLE void lockSession(); + Q_INVOKABLE void suspend(); + Q_INVOKABLE void hibernate(); + + bool idleHint(); + bool lockedHint(); + ObjectModel* userUnits(); + +signals: + void shutdown(bool before); + void sleep(bool before); + void lock(); + void unlock(); + void idleHintChanged(); + void lockedHintChanged(); + +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 { + Q_OBJECT; + QML_ELEMENT; + QML_SINGLETON; + +public: + enum WhatItem : uint8_t { + Shutdown = 0b1, + Sleep = 0b10, + Idle = 0b100, + HandlePowerKey = 0b1000, + HandleSuspendKey = 0b10000, + HandleHibernateKey = 0b100000, + HandleLidSwitch = 0b1000000, + }; + Q_ENUM(WhatItem); + Q_DECLARE_FLAGS(What, WhatItem); + + enum Mode : uint8_t { + Block = 1, + BlockWeak = 2, + Delay = 3, + }; + Q_ENUM(Mode); + + Q_INVOKABLE static std::string toString(WhatItem what); + Q_INVOKABLE static std::string toString(What what); + Q_INVOKABLE static std::string toString(Mode mode); + + static constexpr WhatItem allWhatItems[] = { Shutdown, Sleep, Idle, HandlePowerKey, HandleSuspendKey, HandleHibernateKey, HandleLidSwitch }; +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(SystemdInhibitorParams::What) + +class SystemdInhibitor : public QObject { + Q_OBJECT; + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged); + Q_PROPERTY(SystemdInhibitorParams::What what READ what WRITE setWhat NOTIFY whatChanged); + Q_PROPERTY(QString who READ who WRITE setWho NOTIFY whoChanged); + Q_PROPERTY(QString why READ why WRITE setWhy NOTIFY whyChanged); + Q_PROPERTY(SystemdInhibitorParams::Mode mode READ mode WRITE setMode NOTIFY modeChanged); + QML_ELEMENT; + +public: + explicit SystemdInhibitor(QObject* parent = nullptr): QObject(parent) {} + + bool enabled() const; + void setEnabled(bool enabled); + + SystemdInhibitorParams::What what() const; + void setWhat(SystemdInhibitorParams::What what); + + QString who() const; + void setWho(QString who); + + QString why() const; + void setWhy(QString why); + + SystemdInhibitorParams::Mode mode() const; + void setMode(SystemdInhibitorParams::Mode mode); + + Q_INVOKABLE void release(); + +signals: + void enabledChanged(); + void whatChanged(); + void whoChanged(); + void whyChanged(); + void modeChanged(); + +private: + class ActiveSystemdInhibitor { + public: + uint32_t fd = -1; + SystemdInhibitorParams::What what; + QString who; + QString why; + SystemdInhibitorParams::Mode mode; + + ActiveSystemdInhibitor(SystemdInhibitorParams::What what_, QString who_, QString why_, SystemdInhibitorParams::Mode mode_); + ~ActiveSystemdInhibitor(); + }; + + void update(); + + bool mEnabled = true; + std::unique_ptr activeInhibitor; + SystemdInhibitorParams::What mWhat = static_cast(0); + QString mWho; + QString mWhy; + SystemdInhibitorParams::Mode mMode = static_cast(0); +}; + diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/customplugin.h b/accounts/gkleen@skadhi/shell/quickshell-plugins/customplugin.h new file mode 100644 index 00000000..e66ba9e3 --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/customplugin.h @@ -0,0 +1,7 @@ +#include + +class CustomPlugin : public QQmlEngineExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) +}; diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/default.nix b/accounts/gkleen@skadhi/shell/quickshell-plugins/default.nix new file mode 100644 index 00000000..dfe93bca --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/default.nix @@ -0,0 +1,32 @@ +{ lib +, stdenv +, cmake +, qt6 +, fmt +, keepassxc +, systemd +, quickshell +}: + +stdenv.mkDerivation rec { + name = "quickshell-custom"; + + src = ./.; + + prePatch = '' + cp ${keepassxc.src}/src/gui/org.keepassxc.KeePassXC.MainWindow.xml . + ''; + + nativeBuildInputs = [ cmake qt6.wrapQtAppsHook ]; + buildInputs = [ + qt6.qtbase + qt6.qtdeclarative + ]; + + 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@skadhi/shell/quickshell-plugins/org.freedesktop.DBus.Properties.xml b/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.DBus.Properties.xml new file mode 100644 index 00000000..7588e7a5 --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.DBus.Properties.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.login1.Manager.xml b/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.login1.Manager.xml new file mode 100644 index 00000000..120a06d9 --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.login1.Manager.xml @@ -0,0 +1,445 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.login1.Session.xml b/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.login1.Session.xml new file mode 100644 index 00000000..7d6fc8ee --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.login1.Session.xml @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.systemd1.Manager.xml b/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.systemd1.Manager.xml new file mode 100644 index 00000000..1dadbc55 --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.systemd1.Manager.xml @@ -0,0 +1,821 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.systemd1.Service.xml b/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.systemd1.Service.xml new file mode 100644 index 00000000..316dd080 --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.systemd1.Service.xml @@ -0,0 +1,1100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.systemd1.Unit.xml b/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.systemd1.Unit.xml new file mode 100644 index 00000000..a554f513 --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell-plugins/org.freedesktop.systemd1.Unit.xml @@ -0,0 +1,359 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3