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"
2018-01-23 18:44:44 +08:00
# 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>
2018-01-23 18:44:44 +08:00
# 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 > ( ) ;
2018-01-23 18:44:44 +08:00
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 ) ;
2018-01-23 18:44:44 +08:00
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 ;
}
2018-01-23 18:44:44 +08:00
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. \n Are 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. \n Are 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 ;
}
2018-01-23 18:44:44 +08:00
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 ;
2018-01-23 18:44:44 +08:00
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-24 18:30:21 +08:00
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 ) ;
}
2018-01-24 18:30:21 +08:00
/*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 ) ;
} */