00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "processinfo.h"
00021 #include "detail.h"
00022
00023
00024 #include <opie2/olistview.h>
00025 #include <qpe/qpeapplication.h>
00026
00027
00028 #include <qcombobox.h>
00029 #include <qdir.h>
00030 #include <qlayout.h>
00031 #include <qmessagebox.h>
00032 #include <qpushbutton.h>
00033 #include <qtextview.h>
00034 #include <qtimer.h>
00035 #include <qwhatsthis.h>
00036
00037
00038 #include <sys/types.h>
00039 #include <signal.h>
00040
00041 using namespace Opie::Ui;
00042 ProcessInfo::ProcessInfo( QWidget* parent, const char* name, WFlags fl )
00043 : QWidget( parent, name, fl )
00044 {
00045 QGridLayout *layout = new QGridLayout( this );
00046 layout->setSpacing( 4 );
00047 layout->setMargin( 4 );
00048
00049
00050 ProcessView = new OListView( this, "ProcessView" );
00051 int colnum = ProcessView->addColumn( tr( "PID" ) );
00052 ProcessView->setColumnAlignment( colnum, Qt::AlignRight );
00053 colnum = ProcessView->addColumn( tr( "Command" ),96 );
00054 colnum = ProcessView->addColumn( tr( "Status" ) );
00055 colnum = ProcessView->addColumn( tr( "Time" ) );
00056 ProcessView->setColumnAlignment( colnum, Qt::AlignRight );
00057 ProcessView->setAllColumnsShowFocus( TRUE );
00058 QPEApplication::setStylusOperation( ProcessView->viewport(), QPEApplication::RightOnHold );
00059 connect( ProcessView, SIGNAL( rightButtonPressed(QListViewItem*,const QPoint&,int) ),
00060 this, SLOT( viewProcess(QListViewItem*) ) );
00061 layout->addMultiCellWidget( ProcessView, 0, 0, 0, 1 );
00062 QWhatsThis::add( ProcessView, tr( "This is a list of all the processes on this handheld device.\n\nClick and hold on a process to see additional information about the process, or to send a signal to it." ) );
00063
00064 SignalCB = new QComboBox( FALSE, this, "SignalCB" );
00065 SignalCB->insertItem( " 1: SIGHUP" );
00066 SignalCB->insertItem( " 2: SIGINT" );
00067 SignalCB->insertItem( " 3: SIGQUIT" );
00068 SignalCB->insertItem( " 5: SIGTRAP" );
00069 SignalCB->insertItem( " 6: SIGABRT" );
00070 SignalCB->insertItem( " 9: SIGKILL" );
00071 SignalCB->insertItem( "14: SIGALRM" );
00072 SignalCB->insertItem( "15: SIGTERM" );
00073 SignalCB->insertItem( "18: SIGCONT" );
00074 SignalCB->insertItem( "19: SIGSTOP" );
00075 layout->addWidget( SignalCB, 1, 0 );
00076 QWhatsThis::add( SignalCB, tr( "Select a signal here and then click the Send button to the right to send to this process." ) );
00077
00078 SendButton = new QPushButton( this, "SendButton" );
00079 SendButton->setMinimumSize( QSize( 50, 24 ) );
00080 SendButton->setMaximumSize( QSize( 50, 24 ) );
00081 SendButton->setText( tr( "Send" ) );
00082 connect( SendButton, SIGNAL( clicked() ), this, SLOT( slotSendClicked() ) );
00083 layout->addWidget( SendButton, 1, 1 );
00084 QWhatsThis::add( SendButton, tr( "Click here to send the selected signal to this process." ) );
00085
00086 QTimer *t = new QTimer( this );
00087 connect( t, SIGNAL( timeout() ), this, SLOT( updateData() ) );
00088 t->start( 5000 );
00089
00090 updateData();
00091
00092 ProcessDtl = new Detail();
00093 QWhatsThis::add( ProcessDtl->detailView, tr( "This area shows detailed information about this process." ) );
00094 }
00095
00096 ProcessInfo::~ProcessInfo()
00097 {}
00098
00099 void ProcessInfo::updateData()
00100 {
00101 int pid, ppid, pgrp, session, tty, tpgid, utime, stime, cutime, cstime, counter, priority, starttime,
00102 signal, blocked, sigignore, sigcatch;
00103 uint flags, minflt, cminflt, majflt, cmajflt, timeout, itrealvalue, vsize, rss, rlim, startcode,
00104 endcode, startstack, kstkesp, kstkeip, wchan;
00105 char state;
00106 char comm[64];
00107
00108 QString selectedpid;
00109 OListViewItem *curritem = static_cast<OListViewItem*>( ProcessView->currentItem() );
00110 if ( curritem )
00111 {
00112 selectedpid = curritem->text( 0 );
00113 }
00114
00115 ProcessView->clear();
00116
00117 OListViewItem *newitem;
00118 OListViewItem *selecteditem = 0x0;
00119 QDir *procdir = new QDir("/proc", 0, QDir::Name, QDir::Dirs);
00120 QFileInfoList *proclist = new QFileInfoList(*(procdir->entryInfoList()));
00121 if ( proclist )
00122 {
00123 QFileInfoListIterator it(*proclist);
00124 QFileInfo *f;
00125 while ( ( f = it.current() ) != 0 )
00126 {
00127 ++it;
00128 QString processnum = f->fileName();
00129 if ( processnum >= "1" && processnum <= "99999" )
00130 {
00131 FILE *procfile = fopen( ( QString ) ( "/proc/" + processnum + "/stat"), "r");
00132
00133 if ( procfile )
00134 {
00135 fscanf( procfile,
00136 "%d %s %c %d %d %d %d %d %u %u %u %u %u %d %d %d %d %d %d %u %u %d %u %u %u %u %u %u %u %u %d %d %d %d %u",
00137 &pid, comm, &state, &ppid, &pgrp, &session,&tty, &tpgid, &flags, &minflt, &cminflt,
00138 &majflt, &cmajflt, &utime, &stime, &cutime, &cstime, &counter, &priority, &timeout,
00139 &itrealvalue, &starttime, &vsize, &rss, &rlim, &startcode, &endcode, &startstack,
00140 &kstkesp, &kstkeip, &signal, &blocked, &sigignore, &sigcatch, &wchan );
00141 processnum = processnum.rightJustify( 5, ' ' );
00142 QString processcmd = QString( comm ).replace( QRegExp( "[()]" ), "" );
00143 QString processstatus = QChar(state);
00144 QString processtime = QString::number( ( utime + stime ) / 100 );
00145 processtime = processtime.rightJustify( 9, ' ' );
00146 fclose( procfile );
00147
00148 newitem = new OListViewItem( ProcessView, processnum, processcmd, processstatus, processtime );
00149 if ( processnum == selectedpid )
00150 {
00151 selecteditem = newitem;
00152 }
00153 }
00154 }
00155 }
00156 ProcessView->setCurrentItem( selecteditem );
00157 }
00158
00159 delete proclist;
00160 delete procdir;
00161 }
00162
00163 void ProcessInfo::slotSendClicked()
00164 {
00165 OListViewItem *currprocess = static_cast<OListViewItem*>( ProcessView->currentItem() );
00166 if ( !currprocess )
00167 {
00168 return;
00169 }
00170
00171 QString capstr = tr( "Really want to send %1\nto this process?" ).arg( SignalCB->currentText() );
00172
00173
00174 if ( QMessageBox::warning( this, currprocess->text( 1 ), capstr,
00175 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape ) == QMessageBox::Yes )
00176 {
00177 currprocess = static_cast<OListViewItem*>( ProcessView->currentItem() );
00178 if ( currprocess )
00179 {
00180 QString sigstr = SignalCB->currentText();
00181 sigstr.truncate(2);
00182 int sigid = sigstr.toUInt();
00183 kill( currprocess->text( 0 ).stripWhiteSpace().toUInt(), sigid );
00184 }
00185 }
00186
00187 }
00188
00189 void ProcessInfo::viewProcess( QListViewItem* process ) {
00190 if ( !process )
00191 return;
00192 viewProcess( static_cast<OListViewItem*>( process ) );
00193 }
00194
00195 void ProcessInfo::viewProcess( OListViewItem *process )
00196 {
00197 QString pid= process->text( 0 ).stripWhiteSpace();
00198 QString command = process->text( 1 );
00199 ProcessDtl->setCaption( pid + " - " + command );
00200 FILE *statfile = fopen( ( QString ) ( "/proc/" + pid + "/status"), "r");
00201 if ( statfile )
00202 {
00203 char line[81];
00204 fgets( line, 81, statfile );
00205 ProcessDtl->detailView->setText( line );
00206 while ( fgets( line, 81, statfile ) )
00207 {
00208 ProcessDtl->detailView->append( line );
00209 }
00210 fclose( statfile );
00211 }
00212 QPEApplication::showWidget( ProcessDtl );
00213 }