3
0
mirror of https://github.com/Qortal/Brooklyn.git synced 2025-02-12 02:05:54 +00:00
2022-04-02 18:24:21 +05:00

173 lines
5.3 KiB
C++

/*
SPDX-FileCopyrightText: 2009 Jan Gerrit Marker <jangerrit@weiler-marker.com>
SPDX-FileCopyrightText: 2020 Alexander Lohnau <alexander.lohnau@gmx.de>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "killrunner.h"
#include <QAction>
#include <QDebug>
#include <QIcon>
#include <KAuth>
#include <KLocalizedString>
#include <KProcess>
#include <processcore/process.h>
#include <processcore/processes.h>
K_PLUGIN_CLASS_WITH_JSON(KillRunner, "plasma-runner-kill.json")
KillRunner::KillRunner(QObject *parent, const KPluginMetaData &metaData, const QVariantList &args)
: Plasma::AbstractRunner(parent, metaData, args)
, m_processes(nullptr)
{
setObjectName(QStringLiteral("Kill Runner"));
auto *sigterm = new QAction(QIcon::fromTheme(QStringLiteral("application-exit")), i18n("Send SIGTERM"), this);
sigterm->setData(15);
auto *sigkill = new QAction(QIcon::fromTheme(QStringLiteral("process-stop")), i18n("Send SIGKILL"), this);
sigkill->setData(9);
m_actionList = {sigterm, sigkill};
connect(this, &Plasma::AbstractRunner::prepare, this, &KillRunner::prep);
connect(this, &Plasma::AbstractRunner::teardown, this, &KillRunner::cleanup);
m_delayedCleanupTimer.setInterval(50);
m_delayedCleanupTimer.setSingleShot(true);
connect(&m_delayedCleanupTimer, &QTimer::timeout, this, &KillRunner::cleanup);
}
KillRunner::~KillRunner() = default;
void KillRunner::reloadConfiguration()
{
KConfigGroup grp = config();
m_triggerWord.clear();
if (grp.readEntry(CONFIG_USE_TRIGGERWORD, true)) {
m_triggerWord = grp.readEntry(CONFIG_TRIGGERWORD, i18n("kill")) + QLatin1Char(' ');
}
m_hasTrigger = !m_triggerWord.isEmpty();
m_sorting = (Sort)grp.readEntry(CONFIG_SORTING, static_cast<int>(Sort::NONE));
QList<Plasma::RunnerSyntax> syntaxes;
syntaxes << Plasma::RunnerSyntax(m_triggerWord + QStringLiteral(":q:"), i18n("Terminate running applications whose names match the query."));
setSyntaxes(syntaxes);
if (m_hasTrigger) {
setTriggerWords({m_triggerWord});
setMinLetterCount(minLetterCount() + 2); // Requires two characters after trigger word
} else {
setMinLetterCount(2);
setMatchRegex(QRegularExpression());
}
}
void KillRunner::prep()
{
m_delayedCleanupTimer.stop();
}
void KillRunner::cleanup()
{
if (!m_processes) {
return;
}
if (m_prepLock.tryLockForWrite()) {
delete m_processes;
m_processes = nullptr;
m_prepLock.unlock();
} else {
m_delayedCleanupTimer.stop();
}
}
void KillRunner::match(Plasma::RunnerContext &context)
{
QString term = context.query();
m_prepLock.lockForRead();
if (!m_processes) {
m_prepLock.unlock();
m_prepLock.lockForWrite();
if (!m_processes) {
suspendMatching(true);
m_processes = new KSysGuard::Processes();
m_processes->updateAllProcesses();
suspendMatching(false);
}
}
m_prepLock.unlock();
term = term.right(term.length() - m_triggerWord.length());
QList<Plasma::QueryMatch> matches;
const QList<KSysGuard::Process *> processlist = m_processes->getAllProcesses();
for (const KSysGuard::Process *process : processlist) {
if (!context.isValid()) {
return;
}
const QString name = process->name();
if (!name.contains(term, Qt::CaseInsensitive)) {
continue;
}
const quint64 pid = process->pid();
Plasma::QueryMatch match(this);
match.setText(i18n("Terminate %1", name));
match.setSubtext(i18n("Process ID: %1", QString::number(pid)));
match.setIconName(QStringLiteral("application-exit"));
match.setData(pid);
match.setId(name);
match.setActions(m_actionList);
// Set the relevance
switch (m_sorting) {
case Sort::CPU:
match.setRelevance((process->userUsage() + process->sysUsage()) / 100);
break;
case Sort::CPUI:
match.setRelevance(1 - (process->userUsage() + process->sysUsage()) / 100);
break;
case Sort::NONE:
match.setRelevance(name.compare(term, Qt::CaseInsensitive) == 0 ? 1 : 9);
break;
}
matches << match;
}
context.addMatches(matches);
}
void KillRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match)
{
Q_UNUSED(context)
const quint64 pid = match.data().toUInt();
int signal;
if (match.selectedAction()) {
signal = match.selectedAction()->data().toInt();
} else {
signal = 9; // default: SIGKILL
}
const QStringList args = {QStringLiteral("-%1").arg(signal), QString::number(pid)};
int returnCode = KProcess::execute(QStringLiteral("kill"), args);
if (returnCode == 0) {
return;
}
KAuth::Action killAction = QStringLiteral("org.kde.ksysguard.processlisthelper.sendsignal");
killAction.setHelperId(QStringLiteral("org.kde.ksysguard.processlisthelper"));
killAction.addArgument(QStringLiteral("pid0"), pid);
killAction.addArgument(QStringLiteral("pidcount"), 1);
killAction.addArgument(QStringLiteral("signal"), signal);
killAction.execute();
}
#include "killrunner.moc"