quarkai/plugins/systemmonitor/processdialog.cpp

851 lines
30 KiB
C++
Raw Permalink Normal View History

2018-01-04 09:50:32 +08:00
/*
2018-01-17 11:45:16 +08:00
* Copyright (C) 2013 ~ 2018 National University of Defense Technology(NUDT) & Tianjin Kylin Ltd.
2018-01-04 09:50:32 +08:00
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "processdialog.h"
#include "propertiesdialog.h"
#include "processdata.h"
#include "processcategory.h"
2018-02-12 17:38:54 +08:00
#include "renicedialog.h"
2018-01-04 09:50:32 +08:00
#include "util.h"
#include <QStringList>
#include <QCloseEvent>
#include <QBitmap>
#include <QPainter>
#include <QFileDialog>
#include <QDir>
#include <QDebug>
#include <QHeaderView>
#include <QDesktopServices>
#include <QApplication>
#include <QHBoxLayout>
2018-01-04 09:50:32 +08:00
#include <QList>
#include <QProcess>
#include <QStyleFactory>
#include <QToolTip>
2018-01-17 11:45:16 +08:00
#include <QProcess>
2018-01-04 09:50:32 +08:00
#include <unistd.h>
#include <systemd/sd-login.h>
#include <set>
#include <list>
#include <glibtop.h>
#include <glibtop/proclist.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gprintf.h>
#include <glibtop/procstate.h>
#include <glibtop/procmem.h>
#include <glibtop/procmap.h>
#include <glibtop/proctime.h>
#include <glibtop/procuid.h>
#include <glibtop/procargs.h>
#include <glibtop/prockernel.h>
#include <glibtop/sysinfo.h>
#include <pwd.h>
#include <glibtop/mem.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/resource.h> //for setpriority
using std::string;
QDataStream &operator<<(QDataStream &dataStream, const ProcDataPtr &object)
{
auto ptr = object.data();
auto ptrval = reinterpret_cast<qulonglong>(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<ProcData *>(ptrval);
object = ProcDataPtr(ptr);
return dataStream;
}
2018-01-22 16:37:35 +08:00
ProcessDialog::ProcessDialog(QList<bool> toBeDisplayedColumns, int currentSortIndex, bool isSort, QSettings *settings, QWidget *parent)
2018-01-04 09:50:32 +08:00
:QWidget(parent)
,num_cpus(0)
,frequency(0U)
,proSettings(settings)
{
2018-01-17 11:45:16 +08:00
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
2018-01-04 09:50:32 +08:00
setAttribute(Qt::WA_NoMousePropagation);
qRegisterMetaType<ProcDataPtr>();
qRegisterMetaTypeStreamOperators<ProcDataPtr>();
qRegisterMetaType<ProcDataPtrList>();
qRegisterMetaType<QList<ProcData>>();
2018-01-22 16:37:35 +08:00
actionPids = new QList<pid_t>();
m_layout = new QVBoxLayout(this);
m_layout->setContentsMargins(0, 0, 0, 0);
m_layout->setSpacing(0);
2018-01-04 09:50:32 +08:00
2018-01-22 16:37:35 +08:00
m_processListWidget = new ProcessListWidget(toBeDisplayedColumns);
2018-01-04 09:50:32 +08:00
connect(m_processListWidget, SIGNAL(changeColumnVisible(int,bool,QList<bool>)), this, SIGNAL(changeColumnVisible(int,bool,QList<bool>)));
connect(m_processListWidget, SIGNAL(changeSortStatus(int,bool)), this, SIGNAL(changeSortStatus(int,bool)));
2018-01-22 16:37:35 +08:00
connect(m_processListWidget, &ProcessListWidget::rightMouseClickedItems, this, &ProcessDialog::popupMenu, Qt::QueuedConnection);
m_layout->addWidget(m_processListWidget);
2018-01-04 09:50:32 +08:00
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;
}
QWidget *w = new QWidget;
w->setFixedHeight(50);
m_categoryLayout = new QHBoxLayout(w);
m_categoryLayout->setContentsMargins(0, 0, 6, 3);
m_categoryLayout->setSpacing(10);
processCategory = new ProcessCategory(tabIndex);
connect(processCategory, SIGNAL(activeWhoseProcessList(int)), this, SLOT(onActiveWhoseProcess(int)));
m_categoryLayout->addWidget(processCategory, 0, Qt::AlignRight);
m_layout->addWidget(w);
2018-01-04 09:50:32 +08:00
QList<SortFunction> *sortFuncList = new QList<SortFunction>();
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);
2018-01-22 16:37:35 +08:00
m_processListWidget->setProcessSortFunctions(sortFuncList, currentSortIndex, isSort);
2018-01-04 09:50:32 +08:00
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();
2018-02-12 17:38:54 +08:00
m_menu->setObjectName("MonitorMenu");
2018-01-04 09:50:32 +08:00
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);
2018-02-12 17:38:54 +08:00
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->setObjectName("MonitorMenu");
m_priorityMenu->addActions(priorityGroup->actions());
m_priorityMenu->menuAction()->setText(tr("Change Priority"));
2018-01-04 09:50:32 +08:00
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);//杀死
2018-02-12 17:38:54 +08:00
m_menu->addSeparator();
m_menu->addMenu(m_priorityMenu);
2018-01-04 09:50:32 +08:00
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 processCategory;
2018-01-04 09:50:32 +08:00
delete endProcessDialog;
delete killProcessDialog;
delete m_processListWidget;
delete m_stopAction;
delete m_continueAction;
delete m_endAction;
delete m_killAction;
2018-02-12 17:38:54 +08:00
delete veryHighAction;
delete highAction;
delete normalAction;
delete lowAction;
delete veryLowAction;
delete customAction;
delete m_priorityMenu;
2018-01-04 09:50:32 +08:00
delete m_propertiyAction;
delete m_menu;
delete actionPids;
QLayoutItem *child;
while ((child = m_categoryLayout->takeAt(0)) != 0) {
if (child->widget())
child->widget()->deleteLater();
delete child;
}
delete m_layout;
2018-01-04 09:50:32 +08:00
}
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();
}
void ProcessDialog::changeProcPriority(int nice)
{
if (nice == 32) {
//show renice dialog
2018-02-12 17:38:54 +08:00
pid_t cur_pid = -1;
for (pid_t pid : *actionPids) {
cur_pid = pid;
break;
}
if (cur_pid > -1) {
ProcessWorker *info = ProcessWorker::find(cur_pid);
if (!info) {
actionPids->clear();
return;
}
QString name = QString::fromStdString(info->name);
ReniceDialog *w = new ReniceDialog(tr("Change Priority of Process %1 (PID: %2)").arg(name).arg(QString::number(cur_pid)));
w->loadData(info->nice);
connect(w, &ReniceDialog::resetReniceValue, [=] (int value) {
this->changeProcPriority(value);
});
w->exec();
}
2018-01-04 09:50:32 +08:00
}
else {
pid_t cur_pid = -1;
for (pid_t pid : *actionPids) {
cur_pid = pid;
break;
}
if (cur_pid > -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!!!";
2018-02-12 17:38:54 +08:00
/*
* renice: sudo apt install bsdutils
* Maybe: QProcess::startDetached(command)
* QProcess::start()QProcess::execute()start()execute(): execute()=start()+waitforFinished()
*/
if (QFileInfo("/usr/bin/pkexec").exists()) {//sudo apt install policykit-1
QProcess process;
process.execute(QString("pkexec --disable-internal-agent %1 %2 %3").arg("renice").arg(nice).arg(cur_pid));
/*process.start(QString("pkexec --disable-internal-agent %1 %2 %3").arg("renice").arg(nice).arg(cur_pid));
process.waitForStarted(1000);
process.waitForFinished(20*1000);*/
}
else if (QFileInfo("/usr/bin/gksudo").exists()) {//sudo apt install gksu
QProcess process;
process.execute(QString("gksudo \"%1 %2 %3\"").arg("renice").arg(nice).arg(cur_pid));
/*process.start(QString("gksudo \"%1 %2 %3\"").arg("renice").arg(nice).arg(cur_pid));
process.waitForStarted(1000);
process.waitForFinished(20*1000);*/
}
else if (QFileInfo("/usr/bin/gksu").exists()) {//sudo apt install gksu
QProcess process;
process.execute(QString("gksu \"%1 %2 %3\"").arg("renice").arg(nice).arg(cur_pid));
// process.start(QString("gksu \"%1 %2 %3\"").arg("renice").arg(nice).arg(cur_pid));
// process.waitForStarted(1000);
// process.waitForFinished(20*1000);
2018-01-04 09:50:32 +08:00
}
else {
2018-02-12 17:38:54 +08:00
//
2018-01-04 09:50:32 +08:00
}
}
}
}
actionPids->clear();
}
//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);
//---------------start----------------------
typedef std::list<ProcessWorker*> 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<pid_t> 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()) {
addition.remove(info);
ProcessWorker::all.erase(it);
delete info;
}
it = next;
}
QList<ProcessListItem*> items;
for (ProcessWorker::Iterator it(ProcessWorker::begin()); it != ProcessWorker::end(); ++it) {
QString username = QString::fromStdString(it->second->user);
long nice = it->second->nice;
QString name = QString::fromStdString(it->second->name);
QString session;
if (it->second->session) {
session = QString(it->second->session);
}
QString status = formatProcessState(it->second->status);
2018-01-04 09:50:32 +08:00
uint cpu = it->second->pcpu;
long memory = it->second->mem;
pid_t pid = it->second->pid;
/*---------------------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;
2018-01-30 17:09:06 +08:00
desktopFile = getDesktopFileAccordProcName(name, "");
2018-01-04 09:50:32 +08:00
// qDebug() << "****************"<< QString::fromStdString(desktopFile);
QPixmap icon_pixmap;
int iconSize = 24 * qApp->devicePixelRatio();
2018-02-08 10:08:37 +08:00
QIcon defaultExecutableIcon = QIcon::fromTheme("application-x-executable");//gnome-mine-application-x-executable
if (defaultExecutableIcon.isNull()) {
defaultExecutableIcon = QIcon("/usr/share/icons/kylin-icon-theme/48x48/mimetypes/application-x-executable.png");
if (defaultExecutableIcon.isNull())
defaultExecutableIcon = QIcon(":/res/autostart-default.png");
}
QPixmap defaultPixmap = defaultExecutableIcon.pixmap(iconSize, iconSize);
// QPixmap defaultPixmap = QIcon::fromTheme("application-x-executable").pixmap(iconSize, iconSize);
2018-01-04 09:50:32 +08:00
if (desktopFile.size() == 0) {
icon_pixmap = defaultPixmap;
icon_pixmap.setDevicePixelRatio(qApp->devicePixelRatio());
} else {
2018-01-30 17:09:06 +08:00
icon_pixmap = getAppIconFromDesktopFile(desktopFile, 24);
2018-01-04 09:50:32 +08:00
if (icon_pixmap.isNull()) {
icon_pixmap = defaultPixmap;
icon_pixmap.setDevicePixelRatio(qApp->devicePixelRatio());
}
//QPixmap pixmap = QPixmap::fromImage(img).scaled(iconSize, iconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
2018-01-30 17:09:06 +08:00
QString title = getDisplayNameAccordProcName(name, desktopFile);
2018-01-04 09:50:32 +08:00
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);
}
2018-02-12 17:38:54 +08:00
//杀死 SIGSTOP,SIGCONT,SIGTERM,SIGKILL
2018-01-04 09:50:32 +08:00
void ProcessDialog::killProcesses()
{
int error;
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
2018-02-12 17:38:54 +08:00
if(errno == EPERM) {//(kill -s %d %d", sig, pid)
2018-01-04 09:50:32 +08:00
qDebug() << QString("Kill process %1 failed, permission denied.").arg(pid);
2018-02-12 17:38:54 +08:00
if (QFileInfo("/usr/bin/pkexec").exists()) {//sudo apt install policykit-1
QProcess process;
process.execute(QString("pkexec --disable-internal-agent %1 %2 %3").arg("kill").arg(SIGKILL).arg(pid));
/*process.start(QString("pkexec --disable-internal-agent %1 %2 %3").arg("kill").arg(SIGKILL).arg(pid));
process.waitForStarted(1000);
process.waitForFinished(20*1000);*/
}
else if (QFileInfo("/usr/bin/gksudo").exists()) {//sudo apt install gksu
QProcess process;
process.execute(QString("gksudo \"%1 %2 %3\"").arg("kill").arg(SIGKILL).arg(pid));
/*process.start(QString("gksudo \"%1 %2 %3\"").arg("kill").arg(SIGKILL).arg(pid));
process.waitForStarted(1000);
process.waitForFinished(20*1000);*/
}
else if (QFileInfo("/usr/bin/gksu").exists()) {//sudo apt install gksu
QProcess process;
process.execute(QString("gksu \"%1 %2 %3\"").arg("kill").arg(SIGKILL).arg(pid));
// process.start(QString("gksu \"%1 %2 %3\"").arg("kill").arg(SIGKILL).arg(pid));
// process.waitForStarted(1000);
// process.waitForFinished(20*1000);
}
else {
//
2018-01-04 09:50:32 +08:00
}
}
}
}
actionPids->clear();
}
//结束
void ProcessDialog::endProcesses()
{
int error;
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);
2018-02-12 17:38:54 +08:00
if (QFileInfo("/usr/bin/pkexec").exists()) {//sudo apt install policykit-1
QProcess process;
process.execute(QString("pkexec --disable-internal-agent %1 %2 %3").arg("kill").arg(SIGTERM).arg(pid));
/*process.start(QString("pkexec --disable-internal-agent %1 %2 %3").arg("kill").arg(SIGTERM).arg(pid));
process.waitForStarted(1000);
process.waitForFinished(20*1000);*/
}
else if (QFileInfo("/usr/bin/gksudo").exists()) {//sudo apt install gksu
QProcess process;
process.execute(QString("gksudo \"%1 %2 %3\"").arg("kill").arg(SIGTERM).arg(pid));
/*process.start(QString("gksudo \"%1 %2 %3\"").arg("kill").arg(SIGTERM).arg(pid));
process.waitForStarted(1000);
process.waitForFinished(20*1000);*/
}
else if (QFileInfo("/usr/bin/gksu").exists()) {//sudo apt install gksu
QProcess process;
process.execute(QString("gksu \"%1 %2 %3\"").arg("kill").arg(SIGTERM).arg(pid));
// process.start(QString("gksu \"%1 %2 %3\"").arg("kill").arg(SIGTERM).arg(pid));
// process.waitForStarted(1000);
// process.waitForFinished(20*1000);
}
else {
//
}
2018-01-04 09:50:32 +08:00
}
}
}
actionPids->clear();
}
void ProcessDialog::popupMenu(QPoint pos, QList<ProcessListItem*> items)
{
actionPids->clear();
int count = 0;
pid_t cur_pid = -1;
for (ProcessListItem *item : items) {
count ++;
ProcessListItem *procItem = static_cast<ProcessListItem*>(item);
cur_pid = procItem->getPid();
actionPids->append(cur_pid);
}
2018-02-12 17:38:54 +08:00
if (count == 1) {
2018-01-04 09:50:32 +08:00
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);
2018-02-12 17:38:54 +08:00
}
2018-01-04 09:50:32 +08:00
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<const PropertiesDialog*>(widget) != 0) {
PropertiesDialog *dialog = qobject_cast<PropertiesDialog*>(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<ProcessListItem*> items)
{
m_processListWidget->refreshItems(items);
}
/*void ProcessDialog::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
//绘制背景色
// QPainterPath path;
// path.addRect(QRectF(rect()));
// painter.setOpacity(1);
// painter.fillPath(path, QColor("#FFFFFF"));
//绘制圆角矩形
// painter.setPen(QPen(QColor("#0d87ca"), 0));//边框颜色 QColor(255, 255, 255, 153)
// painter.setBrush(QColor("#e9eef0"));//背景色 #0d87ca
painter.setPen(QPen(QColor("#0000FF"), 0));//边框颜色 QColor(255, 255, 255, 153)
painter.setBrush(QColor("#B22222"));//背景色 #0d87ca
painter.setOpacity(1);
// QRectF r(0 / 2.0, 0 / 2.0, width() - 0, height() - 0);//左边 上边 右边 下边
QRectF r(2, 2, width() - 0, height() - 0);//左边 上边 右边 下边
painter.drawRoundedRect(r, 10, 10);
QWidget::paintEvent(event);
}*/