Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
ddb9b6402e | |||
c95cef0bbd | |||
48d1cc30a8 | |||
c7035a96c7 | |||
4e875fc716 |
@ -47,6 +47,9 @@ AllowAllParametersOfDeclarationOnNextLine: false
|
|||||||
# no single line functions
|
# no single line functions
|
||||||
AllowShortFunctionsOnASingleLine: None
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
|
||||||
|
# no single line enums
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
|
||||||
# always break before you encounter multi line strings
|
# always break before you encounter multi line strings
|
||||||
AlwaysBreakBeforeMultilineStrings: true
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
|
||||||
|
@ -3,28 +3,32 @@ cmake_minimum_required(VERSION 3.16)
|
|||||||
|
|
||||||
project(kcm_openrc)
|
project(kcm_openrc)
|
||||||
|
|
||||||
set(QT_MIN_VERSION "5.15.0")
|
set(QT_MIN_VERSION "6.4.0")
|
||||||
set(KF5_MIN_VERSION "5.88.0")
|
set(KF_MIN_VERSION "6.4.0")
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
|
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
|
||||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
||||||
set(GENERATE_MOC ON)
|
set(GENERATE_MOC ON)
|
||||||
|
|
||||||
|
|
||||||
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
|
find_package(Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
|
||||||
Core
|
Core
|
||||||
Quick
|
Quick
|
||||||
Svg
|
Svg
|
||||||
DBus
|
DBus
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
|
if (BUILD_TESTING)
|
||||||
|
find_package(Qt6 ${QT_MIN_VERSION} REQUIRED COMPONENTS Test)
|
||||||
|
add_compile_definitions("BUILD_TESTING")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS
|
||||||
I18n
|
I18n
|
||||||
KCMUtils
|
KCMUtils
|
||||||
Declarative
|
|
||||||
Config
|
Config
|
||||||
ConfigWidgets
|
ConfigWidgets
|
||||||
Auth
|
Auth
|
||||||
@ -32,44 +36,58 @@ find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
|
|||||||
|
|
||||||
include(KDEInstallDirs)
|
include(KDEInstallDirs)
|
||||||
include(KDECMakeSettings)
|
include(KDECMakeSettings)
|
||||||
include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
|
include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
set(openrc_kcm_SRCS openrc_kcm.cpp)
|
set(openrc_kcm_SRCS
|
||||||
|
openrc_kcm.cpp
|
||||||
|
openrc_tree_item.cpp
|
||||||
|
openrc_service_model.cpp
|
||||||
|
)
|
||||||
|
|
||||||
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||||
|
|
||||||
|
|
||||||
kconfig_add_kcfg_files(openrc_kcm_SRCS GENERATE_MOC openrckcmsettings.kcfgc)
|
kconfig_add_kcfg_files(openrc_kcm_SRCS GENERATE_MOC openrckcmsettings.kcfgc)
|
||||||
|
kcmutils_add_qml_kcm(kcm_openrc)
|
||||||
|
|
||||||
|
target_sources(kcm_openrc PRIVATE
|
||||||
|
${openrc_kcm_SRCS}
|
||||||
|
)
|
||||||
|
|
||||||
add_library(kcm_openrc MODULE ${openrc_kcm_SRCS})
|
|
||||||
add_executable(openrc-actions-kauth openrc_actions.cpp)
|
add_executable(openrc-actions-kauth openrc_actions.cpp)
|
||||||
target_link_libraries(openrc-actions-kauth
|
target_link_libraries(openrc-actions-kauth
|
||||||
Qt5::Core
|
Qt6::Core
|
||||||
Qt5::DBus
|
Qt6::DBus
|
||||||
KF5::CoreAddons
|
|
||||||
KF5::I18n
|
KF6::CoreAddons
|
||||||
KF5::Auth
|
KF6::I18n
|
||||||
|
KF6::AuthCore
|
||||||
|
|
||||||
rc
|
rc
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
target_link_libraries(kcm_openrc
|
target_link_libraries(kcm_openrc
|
||||||
Qt5::Core
|
Qt6::Core
|
||||||
Qt5::DBus
|
Qt6::DBus
|
||||||
KF5::CoreAddons
|
|
||||||
KF5::I18n
|
KF6::CoreAddons
|
||||||
KF5::QuickAddons
|
KF6::I18n
|
||||||
KF5::ConfigCore
|
KF6::KCMUtilsQuick
|
||||||
KF5::ConfigWidgets
|
KF6::ConfigCore
|
||||||
KF5::Auth
|
KF6::ConfigWidgets
|
||||||
|
KF6::AuthCore
|
||||||
|
|
||||||
rc
|
rc
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS openrc-actions-kauth DESTINATION ${KAUTH_HELPER_INSTALL_DIR})
|
if (BUILD_TESTING)
|
||||||
install(TARGETS kcm_openrc DESTINATION ${KDE_INSTALL_PLUGINDIR}/plasma/kcms/systemsettings)
|
target_link_libraries(kcm_openrc Qt6::Test)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# install(TARGETS openrc-actions-kauth DESTINATION ${KAUTH_HELPER_INSTALL_DIR})
|
||||||
|
# install(TARGETS kcm_openrc DESTINATION ${KDE_INSTALL_PLUGINDIR}/plasma/kcms/systemsettings)
|
||||||
|
|
||||||
kpackage_install_package(package kcm_openrc kcms)
|
|
||||||
kauth_install_helper_files(openrc-actions-kauth tridentu.auth.openrc.service root)
|
kauth_install_helper_files(openrc-actions-kauth tridentu.auth.openrc.service root)
|
||||||
kauth_install_actions(tridentu.auth.openrc.service tridentu.auth.openrc.service.actions)
|
kauth_install_actions(tridentu.auth.openrc.service tridentu.auth.openrc.service.actions)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"KPlugin": {
|
"KPlugin": {
|
||||||
"Description": "Configure OpenRC",
|
"Description": "Configure OpenRC",
|
||||||
"FormFactors": [
|
"FormFactors": [
|
||||||
@ -6,12 +6,11 @@
|
|||||||
"mediacenter"
|
"mediacenter"
|
||||||
],
|
],
|
||||||
"Icon": "system-restart",
|
"Icon": "system-restart",
|
||||||
"Id": "kcm_openrc",
|
|
||||||
"Name": "OpenRC",
|
"Name": "OpenRC",
|
||||||
"ServiceTypes": [
|
"ServiceTypes": [
|
||||||
"KCModule"
|
"KCModule"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"X-KDE-Keywords": "OpenRC",
|
"X-KDE-Keywords": "OpenRC,service",
|
||||||
"X-KDE-System-Settings-Parent-Category" : "system-administration"
|
"X-KDE-System-Settings-Parent-Category" : "system-administration"
|
||||||
}
|
}
|
@ -1,4 +0,0 @@
|
|||||||
[Project]
|
|
||||||
CreatedFrom=CMakeLists.txt
|
|
||||||
Manager=KDevCMakeManager
|
|
||||||
Name=kcm_openrc
|
|
@ -1,12 +1,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "openrc_actions.h"
|
#include "openrc_actions.h"
|
||||||
#include <KAuth/KAuthAction>
|
#include <KAuth/Action>
|
||||||
#include <KAuth/KAuthExecuteJob>
|
#include <KAuth/ExecuteJob>
|
||||||
#include <rc.h>
|
#include <rc.h>
|
||||||
#include <qprocess.h>
|
#include <QProcess>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KAuth::ActionReply OpenRCHelper::removeservice( const QVariantMap& args )
|
KAuth::ActionReply OpenRCHelper::removeservice( const QVariantMap& args )
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
|
#ifndef OPENRC_ACTIONS_H
|
||||||
|
#define OPENRC_ACTIONS_H
|
||||||
|
|
||||||
|
#include <KAuth/ActionReply>
|
||||||
#pragma once
|
#include <KAuth/HelperSupport>
|
||||||
|
|
||||||
#include <KAuth/KAuthActionReply>
|
|
||||||
#include <KAuth/KAuthHelperSupport>
|
|
||||||
|
|
||||||
class OpenRCHelper: public QObject {
|
class OpenRCHelper: public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -13,3 +12,5 @@ public Q_SLOTS:
|
|||||||
KAuth::ActionReply restartservice(const QVariantMap& args);
|
KAuth::ActionReply restartservice(const QVariantMap& args);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif /* OPENRC_ACTIONS_H */
|
||||||
|
@ -1,29 +1,28 @@
|
|||||||
|
|
||||||
#include "openrc_kcm.h"
|
#include "openrc_kcm.h"
|
||||||
|
#include "openrc_service_model.h"
|
||||||
|
|
||||||
#include <KPluginFactory>
|
#include <KPluginFactory>
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
#include "openrckcmsettings.h"
|
#include "openrckcmsettings.h"
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <KAuth/KAuthAction>
|
#include <KAuth/Action>
|
||||||
#include <KAuth/KAuthExecuteJob>
|
#include <KAuth/ExecuteJob>
|
||||||
|
#include <rc.h>
|
||||||
|
|
||||||
K_PLUGIN_CLASS_WITH_JSON(OpenRCKCM, "package/kcm_openrc.json");
|
K_PLUGIN_CLASS_WITH_JSON(OpenRCKCM, "kcm_openrc.json");
|
||||||
|
|
||||||
OpenRCKCM::OpenRCKCM(QObject* parent, const KPluginMetaData& data, const QVariantList& args)
|
OpenRCKCM::OpenRCKCM(QObject *parent, const KPluginMetaData &metaData)
|
||||||
: KQuickAddons::ManagedConfigModule(parent, data, args)
|
: KQuickManagedConfigModule(parent, metaData)
|
||||||
{
|
{
|
||||||
|
constexpr const char *uri = "org.kde.plasma.kcm.openrc";
|
||||||
|
|
||||||
|
qmlRegisterType<OpenRCServiceModel>(uri, 1, 0, "OpenRCServiceModel");
|
||||||
|
|
||||||
setButtons(Help | Apply | Default);
|
setButtons(Help | Apply | Default);
|
||||||
KAboutData * aboutData = new KAboutData(QStringLiteral("kcm_openrc"), i18n("OpenRC Settings"));
|
|
||||||
aboutData->addAuthor(QStringLiteral("Tridentu Group"));
|
|
||||||
aboutData->addLicense(KAboutLicense::LGPL_V2);
|
|
||||||
aboutData->setHomepage(QStringLiteral("https://tridentu.github.io/openrc-settings"));
|
|
||||||
|
|
||||||
setAboutData(aboutData);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList OpenRCKCM::getAllServiceTitles(){
|
const QStringList OpenRCKCM::getAllServiceTitles() {
|
||||||
QStringList list;
|
QStringList list;
|
||||||
{
|
{
|
||||||
RC_STRINGLIST* listS = rc_services_in_runlevel("default");
|
RC_STRINGLIST* listS = rc_services_in_runlevel("default");
|
||||||
@ -39,7 +38,7 @@ QStringList OpenRCKCM::getAllServiceTitles(){
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList OpenRCKCM::getAllServices(){
|
const QStringList OpenRCKCM::getAllServices() {
|
||||||
QStringList list;
|
QStringList list;
|
||||||
{
|
{
|
||||||
RC_STRINGLIST* listS = rc_services_in_runlevel("default");
|
RC_STRINGLIST* listS = rc_services_in_runlevel("default");
|
||||||
|
22
openrc_kcm.h
22
openrc_kcm.h
@ -1,28 +1,28 @@
|
|||||||
|
#ifndef OPENRC_KCM_H
|
||||||
|
#define OPENRC_KCM_H
|
||||||
|
|
||||||
#pragma once
|
#include <KQuickManagedConfigModule>
|
||||||
|
|
||||||
|
|
||||||
#include <KQuickAddons/ManagedConfigModule>
|
|
||||||
#include <rc.h>
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include "openrckcmsettings.h"
|
#include "openrckcmsettings.h"
|
||||||
#include <KAboutData>
|
#include <KAboutData>
|
||||||
|
|
||||||
class OpenRCKCM : public KQuickAddons::ManagedConfigModule {
|
class OpenRCKCM : public KQuickManagedConfigModule {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
OpenRCKCM(QObject* parent, const KPluginMetaData& data, const QVariantList& args);
|
OpenRCKCM(QObject *parent, const KPluginMetaData &metaData);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Q_PROPERTY(QStringList allServiceTitles READ getAllServiceTitles)
|
Q_PROPERTY(QStringList allServiceTitles READ getAllServiceTitles CONSTANT)
|
||||||
Q_PROPERTY(QStringList allServices READ getAllServices)
|
Q_PROPERTY(QStringList allServices READ getAllServices CONSTANT)
|
||||||
|
|
||||||
Q_INVOKABLE void tryDisableService(QString serviceName);
|
Q_INVOKABLE void tryDisableService(QString serviceName);
|
||||||
Q_INVOKABLE void tryStopService(QString serviceName);
|
Q_INVOKABLE void tryStopService(QString serviceName);
|
||||||
QStringList getAllServiceTitles();
|
const QStringList getAllServiceTitles();
|
||||||
QStringList getAllServices();
|
const QStringList getAllServices();
|
||||||
Q_INVOKABLE void tryRestartService(QString serviceName);
|
Q_INVOKABLE void tryRestartService(QString serviceName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif /* OPENRC_KCM_H */
|
149
openrc_service_model.cpp
Normal file
149
openrc_service_model.cpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/* ============================================================
|
||||||
|
* KCMOpenRC - OpenRC Service Manager
|
||||||
|
* Copyright (C) 2025 Juraj Oravec <jurajoravec@mailo.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* ============================================================ */
|
||||||
|
#include "openrc_service_model.h"
|
||||||
|
|
||||||
|
#include <QBrush>
|
||||||
|
#include <QColor>
|
||||||
|
#include <QFont>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <sys/queue.h>
|
||||||
|
|
||||||
|
#ifdef OPENRC_SERVICE_MODEL_DEBUG
|
||||||
|
#include <QAbstractItemModelTester>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OpenRCServiceModel::OpenRCServiceModel(QObject* parent)
|
||||||
|
: QAbstractItemModel(parent)
|
||||||
|
, rootItem(std::make_unique<OpenRCTreeItem>(QVariantList{tr("Service")}))
|
||||||
|
{
|
||||||
|
#ifdef OPENRC_SERVICE_MODEL_DEBUG
|
||||||
|
m_tester = new QAbstractItemModelTester(this, QAbstractItemModelTester::FailureReportingMode::Fatal, this);
|
||||||
|
#endif
|
||||||
|
reload_services();
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenRCServiceModel::~OpenRCServiceModel() noexcept = default;
|
||||||
|
|
||||||
|
int OpenRCServiceModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
return static_cast<OpenRCTreeItem*>(parent.internalPointer())->columnCount();
|
||||||
|
return rootItem->columnCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant OpenRCServiceModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid() || role != Qt::DisplayRole)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const auto *item = static_cast<const OpenRCTreeItem*>(index.internalPointer());
|
||||||
|
return item->data(index.column());
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags OpenRCServiceModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
return index.isValid()
|
||||||
|
? QAbstractItemModel::flags(index) : Qt::ItemFlags(Qt::NoItemFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant OpenRCServiceModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole)) {
|
||||||
|
return rootItem->data(section);
|
||||||
|
}
|
||||||
|
return QVariant{};
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex OpenRCServiceModel::index(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (!hasIndex(row, column, parent))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
OpenRCTreeItem *parentItem = parent.isValid()
|
||||||
|
? static_cast<OpenRCTreeItem*>(parent.internalPointer())
|
||||||
|
: rootItem.get();
|
||||||
|
|
||||||
|
if (auto *childItem = parentItem->child(row))
|
||||||
|
return createIndex(row, column, childItem);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex OpenRCServiceModel::parent(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto *childItem = static_cast<OpenRCTreeItem*>(index.internalPointer());
|
||||||
|
OpenRCTreeItem *parentItem = childItem->parentItem();
|
||||||
|
|
||||||
|
if (parentItem != rootItem.get()) {
|
||||||
|
return createIndex(parentItem->row(), 0, parentItem);
|
||||||
|
}
|
||||||
|
return QModelIndex{};
|
||||||
|
}
|
||||||
|
|
||||||
|
int OpenRCServiceModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (parent.column() > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
const OpenRCTreeItem *parentItem = parent.isValid()
|
||||||
|
? static_cast<const OpenRCTreeItem*>(parent.internalPointer())
|
||||||
|
: rootItem.get();
|
||||||
|
|
||||||
|
return parentItem->childCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenRCServiceModel::reload_services()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
|
||||||
|
m_runlevels.clear();
|
||||||
|
|
||||||
|
RC_STRINGLIST* list_runlevels = rc_runlevel_list();
|
||||||
|
RC_STRING* runlevel;
|
||||||
|
TAILQ_FOREACH(runlevel, list_runlevels, entries) {
|
||||||
|
std::string standard_string_name(runlevel->value);
|
||||||
|
QString runlevelStr = QString::fromStdString(standard_string_name);
|
||||||
|
|
||||||
|
QVariantList columnData;
|
||||||
|
columnData << QStringLiteral("<strong>%1</strong>").arg(runlevelStr);
|
||||||
|
|
||||||
|
rootItem.get()->appendChild(std::make_unique<OpenRCTreeItem>(columnData, rootItem.get()));
|
||||||
|
OpenRCTreeItem *parentItem = rootItem.get()->child(rootItem.get()->childCount() -1);
|
||||||
|
|
||||||
|
RC_STRINGLIST* list_services = rc_services_in_runlevel(runlevel->value);
|
||||||
|
RC_STRING* service;
|
||||||
|
TAILQ_FOREACH(service, list_services, entries) {
|
||||||
|
std::string standard_string_name(service->value);
|
||||||
|
QString serviceStr = QString::fromStdString(standard_string_name);
|
||||||
|
|
||||||
|
QVariantList serviceColumnData;
|
||||||
|
serviceColumnData << serviceStr;
|
||||||
|
|
||||||
|
parentItem->appendChild(std::make_unique<OpenRCTreeItem>(serviceColumnData, parentItem));
|
||||||
|
}
|
||||||
|
rc_stringlist_free(list_services);
|
||||||
|
}
|
||||||
|
rc_stringlist_free(list_runlevels);
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
}
|
89
openrc_service_model.h
Normal file
89
openrc_service_model.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/* ============================================================
|
||||||
|
* KCMOpenRC - OpenRC Service Manager
|
||||||
|
* Copyright (C) 2025 Juraj Oravec <jurajoravec@mailo.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* ============================================================ */
|
||||||
|
#ifndef OPENRC_SERVICE_MODEL_H
|
||||||
|
#define OPENRC_SERVICE_MODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QQmlEngine>
|
||||||
|
|
||||||
|
#include <rc.h>
|
||||||
|
|
||||||
|
#include "openrc_tree_item.h"
|
||||||
|
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
#ifdef BUILD_TESTING
|
||||||
|
#define OPENRC_SERVICE_MODEL_DEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPENRC_SERVICE_MODEL_DEBUG
|
||||||
|
class QAbstractItemModelTester;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class OpenRCServiceModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QML_NAMED_ELEMENT(OpenRCServiceModel)
|
||||||
|
|
||||||
|
public:
|
||||||
|
Q_DISABLE_COPY_MOVE(OpenRCServiceModel)
|
||||||
|
|
||||||
|
OpenRCServiceModel(QObject *parent = nullptr);
|
||||||
|
~OpenRCServiceModel() override;
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex &parent = {}) const override;
|
||||||
|
QModelIndex parent(const QModelIndex &index) const override;
|
||||||
|
int rowCount(const QModelIndex &parent = {}) const override;
|
||||||
|
int columnCount(const QModelIndex &parent = {}) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void reload_services();
|
||||||
|
|
||||||
|
std::unique_ptr<OpenRCTreeItem> rootItem;
|
||||||
|
QStringList m_runlevels;
|
||||||
|
|
||||||
|
#ifdef OPENRC_SERVICE_MODEL_DEBUG
|
||||||
|
QAbstractItemModelTester *m_tester;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
class FALKON_EXPORT AdBlockFilterModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit AdBlockFilterModel(QAbstractItemModel *parent);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void setFilterFixedString(const QString &pattern);
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void startFiltering();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_pattern;
|
||||||
|
QTimer *m_filterTimer;
|
||||||
|
};
|
||||||
|
#endif /* 0 - disabled */
|
||||||
|
|
||||||
|
#endif /* OPENRC_SERVICE_MODEL_H */
|
68
openrc_tree_item.cpp
Normal file
68
openrc_tree_item.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* ============================================================
|
||||||
|
* KCMOpenRC - OpenRC Service Manager
|
||||||
|
* Copyright (C) 2025 Juraj Oravec <jurajoravec@mailo.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* ============================================================ */
|
||||||
|
#include "openrc_tree_item.h"
|
||||||
|
|
||||||
|
OpenRCTreeItem::OpenRCTreeItem(QVariantList data, OpenRCTreeItem *parent)
|
||||||
|
: m_itemData(std::move(data))
|
||||||
|
, m_parentItem(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void OpenRCTreeItem::appendChild(std::unique_ptr<OpenRCTreeItem> &&child)
|
||||||
|
{
|
||||||
|
m_childItems.push_back(std::move(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenRCTreeItem *OpenRCTreeItem::child(int row)
|
||||||
|
{
|
||||||
|
return row >= 0 && row < childCount() ? m_childItems.at(row).get() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OpenRCTreeItem::childCount() const
|
||||||
|
{
|
||||||
|
return int(m_childItems.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
int OpenRCTreeItem::columnCount() const
|
||||||
|
{
|
||||||
|
return int(m_itemData.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant OpenRCTreeItem::data(int column) const
|
||||||
|
{
|
||||||
|
return m_itemData.value(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenRCTreeItem *OpenRCTreeItem::parentItem()
|
||||||
|
{
|
||||||
|
return m_parentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OpenRCTreeItem::row() const
|
||||||
|
{
|
||||||
|
if (m_parentItem == nullptr)
|
||||||
|
return 0;
|
||||||
|
const auto it = std::find_if(m_parentItem->m_childItems.cbegin(), m_parentItem->m_childItems.cend(),
|
||||||
|
[this](const std::unique_ptr<OpenRCTreeItem> &treeItem) {
|
||||||
|
return treeItem.get() == this;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != m_parentItem->m_childItems.cend())
|
||||||
|
return std::distance(m_parentItem->m_childItems.cbegin(), it);
|
||||||
|
Q_ASSERT(false); // should not happen
|
||||||
|
return -1;
|
||||||
|
}
|
44
openrc_tree_item.h
Normal file
44
openrc_tree_item.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* ============================================================
|
||||||
|
* KCMOpenRC - OpenRC Service Manager
|
||||||
|
* Copyright (C) 2025 Juraj Oravec <jurajoravec@mailo.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* ============================================================ */
|
||||||
|
#ifndef OPENRC_TREE_ITEM_H
|
||||||
|
#define OPENRC_TREE_ITEM_H
|
||||||
|
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class OpenRCTreeItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit OpenRCTreeItem(QVariantList data, OpenRCTreeItem *parentItem = nullptr);
|
||||||
|
|
||||||
|
void appendChild(std::unique_ptr<OpenRCTreeItem> &&child);
|
||||||
|
|
||||||
|
OpenRCTreeItem *child(int row);
|
||||||
|
int childCount() const;
|
||||||
|
int columnCount() const;
|
||||||
|
QVariant data(int column) const;
|
||||||
|
int row() const;
|
||||||
|
OpenRCTreeItem *parentItem();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::unique_ptr<OpenRCTreeItem>> m_childItems;
|
||||||
|
QVariantList m_itemData;
|
||||||
|
OpenRCTreeItem *m_parentItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OPENRC_TREE_ITEM_H
|
@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
import QtQuick 2.15
|
|
||||||
import QtQuick.Controls 2.15 as Controls
|
|
||||||
import QtQuick.Layouts 1.11
|
|
||||||
|
|
||||||
import org.kde.kirigami 2.16 as Kirigami
|
|
||||||
import org.kde.kcm 1.4
|
|
||||||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
|
||||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
|
@ -1,117 +0,0 @@
|
|||||||
|
|
||||||
import QtQuick 2.15
|
|
||||||
import QtQuick.Controls 2.15 as Controls
|
|
||||||
import QtQuick.Layouts 1.11
|
|
||||||
|
|
||||||
import org.kde.kirigami 2.16 as Kirigami
|
|
||||||
import org.kde.kcm 1.4
|
|
||||||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
|
||||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
|
||||||
import org.kde.plasma.components 3.0 as PlasmaComponents3
|
|
||||||
|
|
||||||
ScrollViewKCM {
|
|
||||||
id: rootKCM
|
|
||||||
implicitWidth: units.gridUnit * 60
|
|
||||||
implicitHeight: units.gridUnit * 25
|
|
||||||
ColumnLayout{
|
|
||||||
id: root
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: units.gridUnit * 2
|
|
||||||
anchors.rightMargin: units.gridUnit * 2
|
|
||||||
anchors.topMargin: units.gridUnit * 2
|
|
||||||
anchors.bottomMargin: units.gridUnit * 2
|
|
||||||
|
|
||||||
PlasmaExtras.Heading {
|
|
||||||
level: 1
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter;
|
|
||||||
text: i18n("Configure OpenRC")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: openRCPanel
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.fillWidth: true
|
|
||||||
PlasmaExtras.Heading {
|
|
||||||
level: 2
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: i18n("Available Services")
|
|
||||||
}
|
|
||||||
|
|
||||||
ListView {
|
|
||||||
id: serviceView
|
|
||||||
model: serviceModel
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
spacing: units.gridUnit * 1.5
|
|
||||||
|
|
||||||
delegate: Rectangle {
|
|
||||||
implicitWidth: rootKCM.implicitWidth
|
|
||||||
color: "#3b4252"
|
|
||||||
border.color: "#a3be8c"
|
|
||||||
implicitHeight: units.gridUnit * 2
|
|
||||||
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
id: toolbar
|
|
||||||
Layout.minimumWidth: parent.implicitWidth
|
|
||||||
anchors.fill: parent
|
|
||||||
PlasmaComponents3.Label {
|
|
||||||
id: headerItem
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: title
|
|
||||||
Layout.leftMargin: 1 * units.gridUnit
|
|
||||||
}
|
|
||||||
Controls.ToolButton {
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
id: deleteButton
|
|
||||||
icon.name: "delete"
|
|
||||||
text: i18n("Remove")
|
|
||||||
Controls.ToolTip.text: i18n("Removes this service from the default runlevel (for OpenRC).")
|
|
||||||
onClicked: {
|
|
||||||
console.log("Start remove " + name);
|
|
||||||
kcm.tryDisableService(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Controls.ToolButton {
|
|
||||||
id: stopButton
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
icon.name: "delete"
|
|
||||||
text: i18n("Stop")
|
|
||||||
Controls.ToolTip.text: i18n("Stops the current service.")
|
|
||||||
onClicked: {
|
|
||||||
kcm.tryStopService(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Controls.ToolButton {
|
|
||||||
id: restartButton
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
icon.name: "system-restart"
|
|
||||||
text: i18n("Restart")
|
|
||||||
Controls.ToolTip.text: i18n("Restarts the current service.")
|
|
||||||
onClicked: {
|
|
||||||
kcm.tryRestartService(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ListModel {
|
|
||||||
id: serviceModel
|
|
||||||
Component.onCompleted: {
|
|
||||||
for (var i = 0; i < kcm.allServices.length; i++){
|
|
||||||
serviceModel.append({"name": kcm.allServices[i], "title": kcm.allServiceTitles[i]});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
|
|
164
ui/main.qml
Normal file
164
ui/main.qml
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls as Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
import org.kde.kirigami as Kirigami
|
||||||
|
import org.kde.kcmutils as KCMUtils
|
||||||
|
import org.kde.plasma.extras as PlasmaExtras
|
||||||
|
import org.kde.plasma.core as PlasmaCore
|
||||||
|
import org.kde.plasma.components as PlasmaComponents3
|
||||||
|
|
||||||
|
import org.kde.plasma.kcm.openrc
|
||||||
|
|
||||||
|
KCMUtils.ScrollViewKCM {
|
||||||
|
id: rootKCM
|
||||||
|
ColumnLayout{
|
||||||
|
id: root
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
PlasmaExtras.Heading {
|
||||||
|
level: 1
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter;
|
||||||
|
text: i18n("Configure OpenRC")
|
||||||
|
}
|
||||||
|
ColumnLayout {
|
||||||
|
id: openRCPanel
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
PlasmaExtras.Heading {
|
||||||
|
level: 2
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: i18n("Available Services")
|
||||||
|
}
|
||||||
|
|
||||||
|
Controls.Frame {
|
||||||
|
clip: true
|
||||||
|
id: serviceViewFrame
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
Controls.ScrollView {
|
||||||
|
id: serviceScrollArea
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
TreeView {
|
||||||
|
id: treeView
|
||||||
|
clip: true
|
||||||
|
width: openRCPanel.width
|
||||||
|
|
||||||
|
selectionModel: ItemSelectionModel {}
|
||||||
|
|
||||||
|
model: OpenRCServiceModel { }
|
||||||
|
|
||||||
|
delegate: Item {
|
||||||
|
// implicitWidth: openRCPanel.width
|
||||||
|
implicitWidth: treeView.width
|
||||||
|
// implicitWidth: padding + label.x + label.implicitWidth + padding
|
||||||
|
implicitHeight: label.implicitHeight * 1.5
|
||||||
|
|
||||||
|
readonly property real indentation: 20
|
||||||
|
readonly property real padding: 5
|
||||||
|
|
||||||
|
// Assigned to by TreeView:
|
||||||
|
required property TreeView treeView
|
||||||
|
required property bool isTreeNode
|
||||||
|
required property bool expanded
|
||||||
|
required property bool hasChildren
|
||||||
|
required property int depth
|
||||||
|
required property int row
|
||||||
|
required property int column
|
||||||
|
required property bool current
|
||||||
|
|
||||||
|
// Rotate indicator when expanded by the user
|
||||||
|
// (requires TreeView to have a selectionModel)
|
||||||
|
property Animation indicatorAnimation: NumberAnimation {
|
||||||
|
target: indicator
|
||||||
|
property: "rotation"
|
||||||
|
from: expanded ? 0 : 90
|
||||||
|
to: expanded ? 90 : 0
|
||||||
|
duration: 100
|
||||||
|
easing.type: Easing.OutQuart
|
||||||
|
}
|
||||||
|
TableView.onPooled: indicatorAnimation.complete()
|
||||||
|
TableView.onReused: if (current) indicatorAnimation.start()
|
||||||
|
onExpandedChanged: indicator.rotation = expanded ? 90 : 0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: background
|
||||||
|
anchors.fill: parent
|
||||||
|
color: row === treeView.currentRow ? palette.highlight : "black"
|
||||||
|
opacity: (treeView.alternatingRows && row % 2 !== 0) ? 0.3 : 0.1
|
||||||
|
}
|
||||||
|
|
||||||
|
Controls.Label {
|
||||||
|
id: indicator
|
||||||
|
x: padding + (depth * indentation)
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
visible: isTreeNode && hasChildren
|
||||||
|
text: "▶"
|
||||||
|
|
||||||
|
TapHandler {
|
||||||
|
onSingleTapped: {
|
||||||
|
let index = treeView.index(row, column)
|
||||||
|
treeView.selectionModel.setCurrentIndex(index, ItemSelectionModel.NoUpdate)
|
||||||
|
treeView.toggleExpanded(row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controls.Label {
|
||||||
|
id: label
|
||||||
|
x: padding + (isTreeNode ? (depth + 1) * indentation : 0)
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: parent.width - padding - x
|
||||||
|
clip: true
|
||||||
|
text: model.display
|
||||||
|
}
|
||||||
|
|
||||||
|
Controls.ToolButton {
|
||||||
|
id: restartButton
|
||||||
|
anchors.right: parent.right
|
||||||
|
visible: !hasChildren
|
||||||
|
icon.name: "system-restart"
|
||||||
|
text: i18n("Restart")
|
||||||
|
Controls.ToolTip.visible: hovered
|
||||||
|
Controls.ToolTip.text: i18n("Restarts the current service.")
|
||||||
|
onClicked: {
|
||||||
|
kcm.tryRestartService(model.display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Controls.ToolButton {
|
||||||
|
id: stopButton
|
||||||
|
anchors.right: restartButton.left
|
||||||
|
visible: !hasChildren
|
||||||
|
icon.name: "delete"
|
||||||
|
text: i18n("Stop")
|
||||||
|
Controls.ToolTip.visible: hovered
|
||||||
|
Controls.ToolTip.text: i18n("Stops the current service.")
|
||||||
|
onClicked: {
|
||||||
|
kcm.tryStopService(model.display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Controls.ToolButton {
|
||||||
|
id: deleteButton
|
||||||
|
anchors.right: stopButton.left
|
||||||
|
visible: !hasChildren
|
||||||
|
icon.name: "delete"
|
||||||
|
text: i18n("Remove")
|
||||||
|
Controls.ToolTip.visible: hovered
|
||||||
|
Controls.ToolTip.text: i18n("Removes this service from the default runlevel (for OpenRC).")
|
||||||
|
onClicked: {
|
||||||
|
console.log("Start remove " + model.display);
|
||||||
|
kcm.tryDisableService(model.display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user