/*
* Copyright (C) 2013 ~ 2018 National University of Defense Technology(NUDT) & Tianjin Kylin Ltd.
*
* Authors:
* Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.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; version 3.
*
* 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 .
*/
#include "processdialog.h"
#include "propertiesdialog.h"
#include "processdata.h"
#include "util.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include //for setpriority
using std::string;
QDataStream &operator<<(QDataStream &dataStream, const ProcDataPtr &object)
{
auto ptr = object.data();
auto ptrval = reinterpret_cast(ptr);
auto var = QVariant::fromValue(ptrval);
dataStream << var;
return dataStream;
}
QDataStream &operator>>(QDataStream &dataStream, ProcDataPtr &object)
{
QVariant var;
dataStream >> var;
qulonglong ptrval = var.toULongLong();
auto ptr = reinterpret_cast(ptrval);
object = ProcDataPtr(ptr);
return dataStream;
}
ProcessDialog::ProcessDialog(QList toBeDisplayedColumns, int currentSortIndex, bool isSort, QSettings *settings, QWidget *parent)
:QWidget(parent)
,num_cpus(0)
,frequency(0U)
,proSettings(settings)
{
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
setAttribute(Qt::WA_NoMousePropagation);
qRegisterMetaType();
qRegisterMetaTypeStreamOperators();
qRegisterMetaType();
qRegisterMetaType>();
actionPids = new QList();
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
m_processListWidget = new ProcessListWidget(toBeDisplayedColumns);
connect(m_processListWidget, SIGNAL(changeColumnVisible(int,bool,QList)), this, SIGNAL(changeColumnVisible(int,bool,QList)));
connect(m_processListWidget, SIGNAL(changeSortStatus(int,bool)), this, SIGNAL(changeSortStatus(int,bool)));
connect(m_processListWidget, &ProcessListWidget::rightMouseClickedItems, this, &ProcessDialog::popupMenu, Qt::QueuedConnection);
layout->addWidget(m_processListWidget);
whose_processes = "user";
proSettings->beginGroup("PROCESS");
whose_processes = proSettings->value("WhoseProcesses", whose_processes).toString();
proSettings->endGroup();
int tabIndex = 1;
if (whose_processes == "active") {
tabIndex = 0;
}
else if (whose_processes == "all") {
tabIndex = 2;
}
else {
tabIndex = 1;
}
QList *sortFuncList = new QList();
sortFuncList->append(&ProcessListItem::sortByName);
sortFuncList->append(&ProcessListItem::sortByUser);
sortFuncList->append(&ProcessListItem::sortByStatus);
sortFuncList->append(&ProcessListItem::sortByCPU);
sortFuncList->append(&ProcessListItem::sortByPid);
sortFuncList->append(&ProcessListItem::sortByCommand);
sortFuncList->append(&ProcessListItem::sortByMemory);
sortFuncList->append(&ProcessListItem::sortByPriority);
m_processListWidget->setProcessSortFunctions(sortFuncList, currentSortIndex, isSort);
m_processListWidget->setSearchFunction(&ProcessListItem::doSearch);
endProcessDialog = new MyDialog(QString(tr("End process")), QString(tr("Ending a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be ended.\nAre you sure to continue?")));
endProcessDialog->setWindowFlags(endProcessDialog->windowFlags() | Qt::WindowStaysOnTopHint);
endProcessDialog->addButton(QString(tr("Cancel")), false);
endProcessDialog->addButton(QString(tr("End process")), true);
connect(endProcessDialog, &MyDialog::buttonClicked, this, &ProcessDialog::endDialogButtonClicked);
killProcessDialog = new MyDialog(QString(tr("Kill process")), QString(tr("Killing a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be killed.\nAre you sure to continue?")));
killProcessDialog->setWindowFlags(killProcessDialog->windowFlags() | Qt::WindowStaysOnTopHint);
killProcessDialog->addButton(QString(tr("Cancel")), false);
killProcessDialog->addButton(QString(tr("Kill process")), true);
connect(killProcessDialog, &MyDialog::buttonClicked, this, &ProcessDialog::killDialogButtonClicked);
m_menu = new QMenu();
m_stopAction = new QAction(tr("Stop process"), this);
connect(m_stopAction, &QAction::triggered, this, &ProcessDialog::stopProcesses);
m_continueAction = new QAction(tr("Continue process"), this);
connect(m_continueAction, &QAction::triggered, this, &ProcessDialog::continueProcesses);
m_endAction = new QAction(tr("End process"), this);
connect(m_endAction, &QAction::triggered, this, &ProcessDialog::showEndProcessDialog);
m_killAction = new QAction(tr("Kill process"), this);
connect(m_killAction, &QAction::triggered, this, &ProcessDialog::showKillProcessDialog);
// priorityGroup = new MyActionGroup(this);
// veryHighAction = new MyActionGroupItem(this, priorityGroup, "very_high_action", -20);
// highAction = new MyActionGroupItem(this, priorityGroup, "high_action", -5);
// normalAction = new MyActionGroupItem(this, priorityGroup, "normal_action", 0);
// lowAction = new MyActionGroupItem(this, priorityGroup, "low_action", 5);
// veryLowAction = new MyActionGroupItem(this, priorityGroup, "very_low_action", 19);
// customAction = new MyActionGroupItem(this, priorityGroup, "custom_action", 32);
// {
// QAction *sep = new QAction(priorityGroup);
// sep->setSeparator(true);
// }
// veryHighAction->change(tr("Very High"));
// highAction->change(tr("High"));
// normalAction->change(tr("Normal"));
// lowAction->change(tr("Low"));
// veryLowAction->change(tr("Very Low"));
// customAction->change(tr("Custom"));
// connect(priorityGroup, SIGNAL(activated(int)), this, SLOT(changeProcPriority(int)));
// m_priorityMenu = new QMenu();
// m_priorityMenu->addActions(priorityGroup->actions());
// m_priorityMenu->menuAction()->setText(tr("Change Priority"));
m_propertiyAction = new QAction(tr("Properties"), this);
connect(m_propertiyAction, &QAction::triggered, this, &ProcessDialog::showPropertiesDialog);
m_menu->addAction(m_stopAction);//停止
m_menu->addAction(m_continueAction);//继续进程
m_menu->addAction(m_endAction);//结束
m_menu->addAction(m_killAction);//杀死
// m_menu->addSeparator();
// m_menu->addMenu(m_priorityMenu);
m_menu->addSeparator();
m_menu->addAction(m_propertiyAction);
glibtop_init();
this->num_cpus = glibtop_get_sysinfo()->ncpu;
this->refreshProcessList();
timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(refreshProcessList()));
timer->start(3000);
}
ProcessDialog::~ProcessDialog()
{
glibtop_close();
this->clearOriginProcList();
if (timer != NULL) {
disconnect(timer,SIGNAL(timeout()),this,SLOT(refreshProcessList()));
if(timer->isActive()) {
timer->stop();
}
delete timer;
timer = NULL;
}
delete endProcessDialog;
delete killProcessDialog;
delete m_processListWidget;
delete m_stopAction;
delete m_continueAction;
delete m_endAction;
delete m_killAction;
// delete veryHighAction;
// delete highAction;
// delete normalAction;
// delete lowAction;
// delete veryLowAction;
// delete customAction;
// delete m_priorityMenu;
delete m_propertiyAction;
delete m_menu;
delete actionPids;
}
void ProcessDialog::displayAllProcess()
{
timer->stop();
this->clearOriginProcList();
whose_processes = "all";
this->refreshProcessList();
timer->start(3000);
}
void ProcessDialog::displayActiveProcess()
{
timer->stop();
this->clearOriginProcList();
whose_processes = "active";
this->refreshProcessList();
timer->start(3000);
}
void ProcessDialog::displayCurrentUserProcess()
{
timer->stop();
this->clearOriginProcList();
whose_processes = "user";
this->refreshProcessList();
timer->start(3000);
}
void ProcessDialog::onActiveWhoseProcess(int index)
{
if (index == 0) {
if (this->whose_processes != "active")
this->displayActiveProcess();
} else if (index == 1) {
if (this->whose_processes != "user")
this->displayCurrentUserProcess();
} else {
if (this->whose_processes != "all")
this->displayAllProcess();
}
proSettings->beginGroup("PROCESS");
proSettings->setValue("WhoseProcesses", whose_processes);
proSettings->endGroup();
proSettings->sync();
}
void ProcessDialog::clearOriginProcList()
{
for (ProcessWorker::Iterator it(ProcessWorker::begin()); it != ProcessWorker::end(); ++it)
delete it->second;
ProcessWorker::all.clear();
}
QString rootCommand(QString command, int value, pid_t pid)
{
return QString("gksu \"%1 %1 %1\"").arg(command, value, pid);
}
void startRenice(QString command, int value, pid_t pid)
{
QProcess::startDetached(rootCommand(command, value, pid));
}
void ProcessDialog::changeProcPriority(int nice)
{
if (nice == 32) {
//show renice dialog
}
else {
pid_t cur_pid = -1;
for (pid_t pid : *actionPids) {
cur_pid = pid;
qDebug() << "******************"< -1) {
ProcessWorker *info = ProcessWorker::find(cur_pid);
if (!info) {
actionPids->clear();
return;
}
if (info->nice == nice) {
actionPids->clear();
return;
}
int saved_errno;
int error = setpriority(PRIO_PROCESS, cur_pid, nice);
//success
if(error != -1) {
actionPids->clear();
return;
}
saved_errno = errno;
//need to be root
if(errno == EPERM || errno == EACCES) {
qDebug() << "Change priority need to be root!!!";
//kobe test
//startRenice("renice", nice, cur_pid);
bool success = false;
QString command = QString("renice %1 %1").arg(nice).arg(cur_pid);
QFile file("/usr/bin/pkexec");
if(file.exists()) {
// gint *exit_status = NULL;
// GError *error = NULL;
QString cmd = QString("pkexec --disable-internal-agent /usr/lib/gnome-system-monitor/gnome-system-monitor/gsm-%1").arg(command);//gsm-renice
qDebug() << "cmd="<message);
// g_error_free(error);
// }
// else
// {
// g_debug("pkexec did fine\n");
// ret = TRUE;
// }
}
else {
qDebug() << "change to root failed......";
}
/*gboolean success;
success = procdialog_create_root_password_dialog (
PROCMAN_ACTION_RENICE, args->app, info->pid,
nice);
if(success) return;
if(errno) {
saved_errno = errno;
}*/
// static char *
// procman_action_to_command(ProcmanActionType type,
// gint pid,
// gint extra_value)
// {
// switch (type) {
// case PROCMAN_ACTION_KILL:
// return g_strdup_printf("kill -s %d %d", extra_value, pid);
// case PROCMAN_ACTION_RENICE:
// return g_strdup_printf("renice %d %d", extra_value, pid);
// default:
// g_assert_not_reached();
// }
// }
// gboolean procdialog_create_root_password_dialog(ProcmanActionType type,
// GsmApplication *app,
// gint pid,
// gint nice)
// {
// char * command;
// gboolean ret = FALSE;
// command = g_strdup_printf("renice %d %d", nice, pid);
// //command = procman_action_to_command(type, pid, nice);
// procman_debug("Trying to run '%s' as root", command);
// if (g_file_test("/usr/bin/pkexec", G_FILE_TEST_EXISTS)) {
// gboolean ret = FALSE;
// gint *exit_status = NULL;
// GError *error = NULL;
// gchar *command_line = g_strdup_printf("pkexec --disable-internal-agent %s/gsm-%s",
// GSM_LIBEXEC_DIR, command);
// if (!g_spawn_command_line_sync(command_line, NULL, NULL, exit_status, &error)) {
// g_critical("Could not run pkexec(\"%s\") : %s\n",
// command, error->message);
// g_error_free(error);
// }
// else
// {
// g_debug("pkexec did fine\n");
// ret = TRUE;
// }
// g_free (command_line);
// return ret;
// }
// if (procman_has_pkexec())
// ret = gsm_pkexec_create_root_password_dialog(command);
// else if (procman_has_gksu())
// ret = gsm_gksu_create_root_password_dialog(command);
// else if (procman_has_gnomesu())
// ret = gsm_gnomesu_create_root_password_dialog(command);
// g_free(command);
// return ret;
// }
}
}
}
actionPids->clear();
// static void
// renice_scale_changed (GtkAdjustment *adj, gpointer data)
// {
// GtkWidget *label = GTK_WIDGET (data);
// new_nice_value = int(gtk_adjustment_get_value (adj));
// gchar* text = g_strdup(procman::get_nice_level_with_priority (new_nice_value));
// gtk_label_set_text (GTK_LABEL (label), text);
// g_free(text);
// }
// static void
// renice_dialog_button_pressed (GtkDialog *dialog, gint id, gpointer data)
// {
// GsmApplication *app = static_cast(data);
// if (id == 100) {
// if (new_nice_value == -100)
// return;
// renice(app, new_nice_value);
// }
// gtk_widget_destroy (GTK_WIDGET (dialog));
// renice_dialog = NULL;
// }
//renice_scale_changed
//renice_dialog_button_pressed
}
//void ProcessDialog::onCloseButtonClicked()
//{
// this->close();
//}
//void ProcessDialog::closeEvent(QCloseEvent *event)
//{
// event->accept();
//}
void ProcessDialog::refreshProcessList()
{
pid_t* pid_list;
glibtop_proclist proclist;
glibtop_cpu cpu;
int which = 0;
int arg = 0;
if (whose_processes == "all") {
which = GLIBTOP_KERN_PROC_ALL;
arg = 0;
} else if (whose_processes == "active") {
which = GLIBTOP_KERN_PROC_ALL | GLIBTOP_EXCLUDE_IDLE;
arg = 0;
} else if (whose_processes == "user") {
which = GLIBTOP_KERN_PROC_UID;
arg = getuid();
}
pid_list = glibtop_get_proclist(&proclist, which, arg);
/* FIXME: total cpu time elapsed should be calculated on an individual basis here
** should probably have a total_time_last gint in the ProcInfo structure */
glibtop_get_cpu(&cpu);
this->frequency = cpu.frequency;
this->cpu_total_time = MAX(cpu.total - this->cpu_total_time_last, 1);
this->cpu_total_time_last = cpu.total;
// FIXME: not sure if glibtop always returns a sorted list of pid
// but it is important otherwise refresh_list won't find the parent
std::sort(pid_list, pid_list + proclist.number);
// qDebug() << "proclist.number="< ProcList;
ProcList addition;
guint i;
for(i = 0; i < proclist.number; ++i) {
ProcessWorker *info = ProcessWorker::find(pid_list[i]);
if (!info) {//不存在时创建该进程的对象
info = new ProcessWorker(pid_list[i], this->num_cpus, this->cpu_total_time);
ProcessWorker::all[info->pid] = info;
}
//当进程对象存在时,更新该进程对象的相关数据信息
glibtop_proc_state procstate;
glibtop_proc_uid procuid;
glibtop_proc_time proctime;
glibtop_get_proc_state (&procstate, info->pid);
info->status = procstate.state;
glibtop_get_proc_uid (&procuid, info->pid);
glibtop_get_proc_time (&proctime, info->pid);
glibtop_proc_mem procmem;
glibtop_get_proc_mem(&procmem, info->pid);
info->mem = procmem.resident - procmem.share;
glibtop_get_proc_state(&procstate, info->pid);
info->status = procstate.state;
info->set_user(procstate.uid);
guint64 difference = proctime.rtime - info->cpu_time;
if (difference > 0)
info->status = GLIBTOP_PROCESS_RUNNING;
info->pcpu = difference * 100 / this->cpu_total_time;
info->pcpu = MIN(info->pcpu, 100);
//CPU 百分比使用 Solaris 模式,工作在“Solaris 模式”,其中任务的 CPU 使用量将被除以总的 CPU 数目。否则它将工作在“Irix 模式”。
info->pcpu *= this->num_cpus;
info->frequency = this->frequency;
ProcessWorker::cpu_times[info->pid] = info->cpu_time = proctime.rtime;
info->nice = procuid.nice;
}
// Remove dead processes from the process list and from the
// tree. children are queued to be readded at the right place
// in the tree.
const std::set pids(pid_list, pid_list + proclist.number);
ProcessWorker::Iterator it(ProcessWorker::begin());
while (it != ProcessWorker::end()) {
ProcessWorker * const info = it->second;
ProcessWorker::Iterator next(it);
++next;
if (pids.find(info->pid) == pids.end()) {
// qDebug() << "ripping ====" << info->pid;
addition.remove(info);
ProcessWorker::all.erase(it);
delete info;
}
it = next;
}
QList items;
for (ProcessWorker::Iterator it(ProcessWorker::begin()); it != ProcessWorker::end(); ++it) {
//qDebug() <<"it->second->pid="<< it->second->pid;
QString username = QString::fromStdString(it->second->user);
//qDebug() << "username=" << username;
long nice = it->second->nice;
// QString session = "c2";
QString name = QString::fromStdString(it->second->name);
// qDebug() << "pcpu="<second->pcpu;
// qDebug() << "mem="<second->mem;
QString session;
if (it->second->session) {
session = QString(it->second->session);
}
QString status = formatProcessState(it->second->status);
// qDebug() <<"status="<second->status;
// qDebug() <<"name================"<second->pcpu;
long memory = it->second->mem;
pid_t pid = it->second->pid;
// if (pid == 16280) {
// qDebug() << "--------------------------"<second->pid << "===" << it->second->uid;
// }
// if (pid == 6924) {
// qDebug() << "--------------------------"<second->mem;
// }
/*---------------------kobe test string---------------------
//QString to std:string
QString test_QString = "lixiang";
std::string test_string = test_QString.toStdString();
//std::string to QString
QString result = QString::fromStdString(test_string)
QString::fromStdString(test_QString.toStdString());
----------------------------------------------------------*/
std::string desktopFile;
desktopFile = getDesktopFileFromName(pid, name, "");
// qDebug() << "****************"<< QString::fromStdString(desktopFile);
QPixmap icon_pixmap;
int iconSize = 24 * qApp->devicePixelRatio();
QPixmap defaultPixmap = QIcon::fromTheme("application-x-executable").pixmap(iconSize, iconSize);
if (desktopFile.size() == 0) {
icon_pixmap = defaultPixmap;
icon_pixmap.setDevicePixelRatio(qApp->devicePixelRatio());
} else {
icon_pixmap = getDesktopFileIcon(desktopFile, 24);
if (icon_pixmap.isNull()) {
icon_pixmap = defaultPixmap;
icon_pixmap.setDevicePixelRatio(qApp->devicePixelRatio());
}
//QPixmap pixmap = QPixmap::fromImage(img).scaled(iconSize, iconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
QString title = getDisplayNameFromName(name, desktopFile);
QString displayName;
if (whose_processes == "all") {
displayName = QString("[%1] %2").arg(username).arg(title);
} else {
displayName = title;
}
ProcData info;
// info.pidt = it->second->pid;
info.user = username;
info.iconPixmap = icon_pixmap;
info.displayName = displayName;
info.cpu = cpu;
info.m_memory = memory;
info.pid = pid;
info.m_status = status;
info.m_nice = nice;
info.m_session = session;
info.cpu_duration_time = formatDurationForDisplay(100 * it->second->cpu_time / this->frequency);
info.processName = QString::fromStdString(it->second->name);
info.commandLine = QString::fromStdString(it->second->arguments);
ProcessListItem *item = new ProcessListItem(info);
items << item;
}
this->updateStatus(items);
g_free (pid_list);
//---------------end----------------------
}
ProcessListWidget* ProcessDialog::getProcessView()
{
return m_processListWidget;
}
void ProcessDialog::endDialogButtonClicked(int index, QString)
{
if (index == 1) {//cancel:0 ok:1
endProcesses();
}
}
void ProcessDialog::killDialogButtonClicked(int index, QString)
{
if (index == 1) {//cancel:0 ok:1
killProcesses();
}
}
void ProcessDialog::focusProcessView()
{
QTimer::singleShot(100, m_processListWidget, SLOT(setFocus()));
}
void ProcessDialog::onSearch(QString text)
{
m_processListWidget->doSearch(text);
}
//杀死
void ProcessDialog::killProcesses()
{
int error;
// int saved_errno;
for (pid_t pid : *actionPids) {
// Resume process first, otherwise kill process too slow.
kill(pid, SIGCONT);
// if (kill(pid, SIGKILL) != 0) {
// qDebug() << QString("Kill process %1 failed, permission denied.").arg(pid);
// }
error = kill(pid, SIGKILL);
if(error != -1) {
qDebug() << "success.....";
}
else {
//need to be root
if(errno == EPERM) {
qDebug() << QString("Kill process %1 failed, permission denied.").arg(pid);
/*gboolean success;
success = procdialog_create_root_password_dialog (
PROCMAN_ACTION_KILL, args->app, info->pid,
args->arg_value);
if(success) {
actionPids->clear();
return;
}
if(errno) {
saved_errno = errno;
}*/
}
}
}
actionPids->clear();
}
//结束
void ProcessDialog::endProcesses()
{
int error;
// int saved_errno;
for (pid_t pid : *actionPids) {
// if (kill(pid, SIGTERM) != 0) {
// qDebug() << QString("Kill process %1 failed, permission denied.").arg(pid);
// }
error = kill(pid, SIGTERM);
if(error != -1) {
qDebug() << "success.....";
}
else {
//need to be root
if(errno == EPERM) {
qDebug() << QString("End process %1 failed, permission denied.").arg(pid);
/*gboolean success;
success = procdialog_create_root_password_dialog (
PROCMAN_ACTION_KILL, args->app, info->pid,
args->arg_value);
if(success) {
actionPids->clear();
return;
}
if(errno) {
saved_errno = errno;
}*/
}
}
}
actionPids->clear();
}
void ProcessDialog::popupMenu(QPoint pos, QList items)
{
actionPids->clear();
int count = 0;
pid_t cur_pid = -1;
for (ProcessListItem *item : items) {
count ++;
ProcessListItem *procItem = static_cast(item);
cur_pid = procItem->getPid();
// qDebug() << "HAHAHAH===========" << cur_pid;
actionPids->append(cur_pid);
}
/*if (count == 1) {
ProcessWorker *info = ProcessWorker::find(cur_pid);
if (!info) {
priorityGroup->setActionsEnabled(false);
}
else {
priorityGroup->setActionsEnabled(true);
gint nice = info->nice;
int priority;
if (nice < -7)
priority = -20;
else if (nice < -2)
priority = -5;
else if (nice < 3)
priority = 0;
else if (nice < 7)
priority = 5;
else
priority = 19;
priorityGroup->setChecked(priority);
}
}
else {
priorityGroup->setActionsEnabled(false);
}*/
m_menu->exec(pos);
}
void ProcessDialog::continueProcesses()
{
for (pid_t pid : *actionPids) {
if (kill(pid, SIGCONT) != 0) {
qDebug() << QString("Resume process %1 failed, permission denied.").arg(pid);
}
}
actionPids->clear();
}
void ProcessDialog::showPropertiesDialog()
{
for (pid_t pid : *actionPids) {
foreach (QWidget *widget, QApplication::topLevelWidgets()) {
// Show attribute dialog if it has create, avoid create attribute dialog duplicate.
if (qobject_cast(widget) != 0) {
PropertiesDialog *dialog = qobject_cast(widget);
if (dialog->getPid() == pid) {
dialog->show();
actionPids->clear();
return;
}
}
}
PropertiesDialog *dialog = new PropertiesDialog(this, pid);
dialog->show();
}
actionPids->clear();
}
void ProcessDialog::showKillProcessDialog()
{
killProcessDialog->exec();
}
void ProcessDialog::showEndProcessDialog()
{
endProcessDialog->exec();
}
//停止
void ProcessDialog::stopProcesses()
{
pid_t currentPid = getpid();
for (pid_t pid : *actionPids) {
if (pid != currentPid) {
if (kill(pid, SIGSTOP) != 0) {
qDebug() << QString("Stop process %1 failed, permission denied.").arg(pid);
}
}
}
actionPids->clear();
}
void ProcessDialog::updateStatus(QList items)
{
m_processListWidget->refreshItems(items);
}