Commit 82879c59 authored by Arjen Hiemstra's avatar Arjen Hiemstra

Add a declarative plugin to ProcessCore

Summary:
This adds a QML plugin to ProcessCore that exposes ProcessController
and allows it to be used from QML, along with some changes the were
needed to actually use it from QML and a manual test to verify that
the QML bits work.

This will later on be expanded to also expose other types, including
ProcessDataModel from D27509

Test Plan: The test runs and can send signals to processes.

Reviewers: #plasma, davidedmundson

Reviewed By: #plasma, davidedmundson

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D28140
parent 5cfc09fd
......@@ -20,6 +20,7 @@ ecm_qt_declare_logging_category(ksysguard_LIB_SRCS HEADER processcore_debug.h ID
add_library(processcore ${ksysguard_LIB_SRCS})
add_library(KF5::ProcessCore ALIAS processcore)
add_library(KSysGuard::ProcessCore ALIAS processcore)
target_link_libraries(processcore
PUBLIC
......@@ -49,6 +50,8 @@ target_include_directories(processcore
set_target_properties(processcore PROPERTIES VERSION ${KSYSGUARD_VERSION_STRING} SOVERSION ${KSYSGUARD_SOVERSION} EXPORT_NAME ProcessCore)
install(TARGETS processcore EXPORT libksysguardLibraryTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
add_subdirectory(declarative)
########### install files ###############
install( FILES
......
include_directories(${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/..)
add_library(ProcessPlugin SHARED ProcessPlugin.cpp ProcessEnums.cpp)
target_link_libraries(ProcessPlugin Qt5::Qml KSysGuard::ProcessCore)
install(TARGETS ProcessPlugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/ksysguard/process)
install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/ksysguard/process)
#include "ProcessEnums.h"
#include "moc_ProcessEnums.cpp"
/*
Copyright (C) 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#pragma once
#include <QMetaType>
#include "process.h"
namespace KSysGuardProcess {
Q_NAMESPACE
using ProcessStatus = KSysGuard::Process::ProcessStatus;
Q_ENUM_NS(ProcessStatus);
using IoPriorityClass = KSysGuard::Process::IoPriorityClass;
Q_ENUM_NS(IoPriorityClass);
using Scheduler = KSysGuard::Process::Scheduler;
Q_ENUM_NS(Scheduler);
}
Q_DECLARE_METATYPE(KSysGuard::Process::ProcessStatus)
Q_DECLARE_METATYPE(KSysGuard::Process::IoPriorityClass)
Q_DECLARE_METATYPE(KSysGuard::Process::Scheduler)
/*
Copyright (C) 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "ProcessPlugin.h"
#include <QQmlEngine>
#include "process_controller.h"
#include "process_data_model.h"
#include "process_attribute_model.h"
#include "ProcessEnums.h"
using namespace KSysGuard;
void ProcessPlugin::registerTypes(const char *uri)
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.ksysguard.process"));
qRegisterMetaType<KSysGuard::ProcessController::Signal>();
qRegisterMetaType<KSysGuard::ProcessController::Result>();
qRegisterMetaType<KSysGuardProcess::ProcessStatus>();
qRegisterMetaType<KSysGuardProcess::IoPriorityClass>();
qRegisterMetaType<KSysGuardProcess::Scheduler>();
qmlRegisterType<ProcessController>(uri, 1, 0, "ProcessController");
qmlRegisterUncreatableMetaObject(KSysGuardProcess::staticMetaObject, uri, 1, 0, "Process", QStringLiteral("Contains process enums"));
qmlRegisterType<ProcessDataModel>(uri, 1, 0, "ProcessDataModel");
qmlRegisterUncreatableType<ProcessAttributeModel>(uri, 1, 0, "ProcessAttributeModel", QStringLiteral("Available through ProcessDataModel"));
}
/*
Copyright (C) 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#pragma once
#include <QQmlExtensionPlugin>
class ProcessPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
public:
void registerTypes(const char *uri) override;
};
module org.kde.ksysguard.process
plugin ProcessPlugin
......@@ -23,6 +23,7 @@
#include <functional>
#include <KLocalizedString>
#include <KAuth/KAuthAction>
#include <KAuth/KAuthExecuteJob>
......@@ -43,6 +44,7 @@ public:
ApplyResult applyToPids(const QVector<int> &pids, const std::function<bool(int)> &function);
ProcessController::Result runKAuthAction(const QString &actionId, const QVector<int> &pids, const QVariantMap &options);
QVector<int> listToVector(const QList<long long> &list);
QVector<int> listToVector(const QVariantList &list);
QWidget *widget;
......@@ -98,6 +100,11 @@ KSysGuard::ProcessController::Result KSysGuard::ProcessController::sendSignal(co
return sendSignal(d->listToVector(pids), signal);
}
KSysGuard::ProcessController::Result KSysGuard::ProcessController::sendSignal(const QVariantList &pids, int signal)
{
return sendSignal(d->listToVector(pids), signal);
}
ProcessController::Result ProcessController::setPriority(const QVector<int>& pids, int priority)
{
auto result = d->applyToPids(pids, [this, priority](int pid) { return d->localProcesses->setNiceness(pid, priority); });
......@@ -117,6 +124,11 @@ KSysGuard::ProcessController::Result KSysGuard::ProcessController::setPriority(c
return setPriority(d->listToVector(pids), priority);
}
KSysGuard::ProcessController::Result KSysGuard::ProcessController::setPriority(const QVariantList &pids, int priority)
{
return setPriority(d->listToVector(pids), priority);
}
ProcessController::Result ProcessController::setCPUScheduler(const QVector<int>& pids, Process::Scheduler scheduler, int priority)
{
if (scheduler == KSysGuard::Process::Other || scheduler == KSysGuard::Process::Batch) {
......@@ -142,6 +154,11 @@ KSysGuard::ProcessController::Result KSysGuard::ProcessController::setCPUSchedul
return setCPUScheduler(d->listToVector(pids), scheduler, priority);
}
KSysGuard::ProcessController::Result KSysGuard::ProcessController::setCPUScheduler(const QVariantList &pids, Process::Scheduler scheduler, int priority)
{
return setCPUScheduler(d->listToVector(pids), scheduler, priority);
}
ProcessController::Result ProcessController::setIOScheduler(const QVector<int>& pids, Process::IoPriorityClass priorityClass, int priority)
{
if (!d->localProcesses->supportsIoNiceness()) {
......@@ -175,18 +192,46 @@ KSysGuard::ProcessController::Result KSysGuard::ProcessController::setIOSchedule
return setIOScheduler(d->listToVector(pids), priorityClass, priority);
}
KSysGuard::ProcessController::Result KSysGuard::ProcessController::setIOScheduler(const QVariantList &pids, Process::IoPriorityClass priorityClass, int priority)
{
return setIOScheduler(d->listToVector(pids), priorityClass, priority);
}
QString ProcessController::resultToString(Result result)
{
switch(result) {
case Result::Success:
return i18n("Success");
case Result::InsufficientPermissions:
return i18n("Insufficient permissions.");
case Result::NoSuchProcess:
return i18n("No matching process was found.");
case Result::Unsupported:
return i18n("Not supported on the current system.");
case Result::UserCancelled:
return i18n("The user cancelled.");
case Result::Error:
return i18n("An unspecified error occurred.");
default:
return i18n("An unknown error occurred.");
}
}
ApplyResult KSysGuard::ProcessController::Private::applyToPids(const QVector<int>& pids, const std::function<bool(int)>& function)
{
ApplyResult result;
localProcesses->errorCode = KSysGuard::Processes::Unknown;
for (auto pid : pids) {
auto success = function(pid);
if (!success
&& (localProcesses->errorCode == KSysGuard::Processes::InsufficientPermissions
|| localProcesses->errorCode == KSysGuard::Processes::Unknown)) {
result.unchanged << pid;
result.resultCode = Result::InsufficientPermissions;
} else if (result.resultCode == Result::Success) {
if (!success) {
switch (localProcesses->errorCode) {
case KSysGuard::Processes::InsufficientPermissions:
case KSysGuard::Processes::Unknown:
result.unchanged << pid;
result.resultCode = Result::InsufficientPermissions;
break;
case Processes::InvalidPid:
case Processes::ProcessDoesNotExistOrZombie:
case Processes::InvalidParameter:
......@@ -249,3 +294,10 @@ QVector<int> KSysGuard::ProcessController::Private::listToVector(const QList<lon
std::transform(list.cbegin(), list.cend(), std::back_inserter(vector), [](long long entry) { return entry; });
return vector;
}
QVector<int> KSysGuard::ProcessController::Private::listToVector(const QVariantList &list)
{
QVector<int> vector;
std::transform(list.cbegin(), list.cend(), std::back_inserter(vector), [](const QVariant &entry) { return entry.toInt(); });
return vector;
}
......@@ -25,6 +25,7 @@
#include <memory>
#include <QObject>
#include <QVariant>
#include "process.h"
......@@ -107,6 +108,10 @@ public:
* \overload Result sendSignal(const QVector<int> &pids, int signal)
*/
Q_INVOKABLE Result sendSignal(const QList<long long> &pids, int signal);
/**
* \overload Result sendSignal(const QVector<int> &pids, int signal)
*/
Q_INVOKABLE Result sendSignal(const QVariantList &pids, int signal);
/**
* Set the priority (niceness) of a number of processes.
......@@ -127,6 +132,10 @@ public:
* \overload Result setPriority(const QVector<int> &pids, int priority)
*/
Q_INVOKABLE Result setPriority(const QList<long long> &pids, int priority);
/**
* \overload Result setPriority(const QVector<int> &pids, int priority)
*/
Q_INVOKABLE Result setPriority(const QVariantList &pids, int priority);
/**
* Set the CPU scheduling policy and priority of a number of processes.
......@@ -149,6 +158,10 @@ public:
* \overload Result setCPUScheduler(const QVector<int> &pids, Process::Scheduler scheduler, int priority)
*/
Q_INVOKABLE Result setCPUScheduler(const QList<long long> &pids, Process::Scheduler scheduler, int priority);
/**
* \overload Result setCPUScheduler(const QVector<int> &pids, Process::Scheduler scheduler, int priority)
*/
Q_INVOKABLE Result setCPUScheduler(const QVariantList &pids, Process::Scheduler scheduler, int priority);
/**
* Set the IO scheduling policy and priority of a number of processes.
......@@ -171,6 +184,17 @@ public:
* \overload Result setIOScheduler(const QVector<int> &pids, Process::IoPriorityClass priorityClass, int priority)
*/
Q_INVOKABLE Result setIOScheduler(const QList<long long> &pids, Process::IoPriorityClass priorityClass, int priority);
/**
* \overload Result setIOScheduler(const QVector<int> &pids, Process::IoPriorityClass priorityClass, int priority)
*/
Q_INVOKABLE Result setIOScheduler(const QVariantList &pids, Process::IoPriorityClass priorityClass, int priority);
/**
* Convert a Result value to a user-visible string.
*
*
*/
Q_INVOKABLE QString resultToString(Result result);
private:
class Private;
......
/*
Copyright (C) 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import org.kde.ksysguard.process 1.0 as Process
Pane {
width: 400
height: 400
ColumnLayout {
anchors.fill: parent
TextField {
id: input
Layout.fillWidth: true
placeholderText: "PID"
}
ComboBox {
id: signalCombo
Layout.fillWidth: true
textRole: "key"
model: [
{ key: "Stop", value: Process.ProcessController.StopSignal },
{ key: "Continue", value: Process.ProcessController.ContinueSignal },
{ key: "Hangup", value: Process.ProcessController.HangupSignal },
{ key: "Interrupt", value: Process.ProcessController.InterruptSignal },
{ key: "Terminate", value: Process.ProcessController.TerminateSignal },
{ key: "Kill", value: Process.ProcessController.KillSignal },
{ key: "User 1", value: Process.ProcessController.User1Signal },
{ key: "User 2", value: Process.ProcessController.User2Signal }
]
}
Button {
Layout.fillWidth: true
text: "Send Signal"
onClicked: {
var signalToSend = signalCombo.model[signalCombo.currentIndex]
print("Sending", signalToSend.key, "(%1)".arg(signalToSend.value), "to PID", parseInt(input.text))
var result = controller.sendSignal([parseInt(input.text)], signalToSend.value);
print("Result:", result)
resultLabel.text = controller.resultToString(result)
}
}
Label {
id: resultLabel
Layout.fillWidth: true
}
}
Process.ProcessController {
id: controller
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment