You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
qps-packaging/src/qps.cpp

2476 lines
67 KiB

// qps -- Qt-based visual process status monitor
// This program is free software. See the file COPYING for details.
// Author: Mattias Engdeg?rd, 1997-1999
// fasthyun@magicn.com 2005-2012
// daehyun.yang@gmail.com 2015-
// TODO & MEMO
/*
*
* For easy maintance
* 1. F_CMDLINE should be rightmost field
* 2. F_PROCESSNAME shoud be leftmost field and NEVER removed!
*
*
*
*/
// . Memory Hole or Qt's string allocate bug?
// . clipboard copy [CMDLINE,PID,USERNAME...]
// . [klog] table cache.
// . save sort of tree, linear
// . watchdog showmsg substitude
// . history system
// . cmd [w] analsys: [IDLE] [WHAT]
// . ExecWindow - [running] finish.
// . UNIX Domain SOCKET
// . COLOR : orange FF5d00
// . P_MEM -> P_%MEM or P_PMEM
#include "../icon/icon.xpm"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/utsname.h> // uname
#include <signal.h>
#include <errno.h>
#include <sched.h>
#include <unistd.h> //for sleep
#include "qps.h"
#include "qpsapp.h"
#include "dialogs.h"
#include "commanddialog.h"
#include "commandutils.h"
#include "watchcond.h"
#include "watchdogdialog.h"
#include "lookup.h"
#include "misc.h"
#ifndef USING_PCH
#include <QBitmap>
#include <QTimerEvent>
#include <QVBoxLayout>
#include <QShortcut>
#include <QMenuBar>
#include <QFont>
#include <QFontComboBox>
#include <QToolTip>
#include <QTabWidget>
#include <QApplication>
#include <QCheckBox>
#include <QToolButton>
#include <QMessageBox>
#include <QSessionManager>
#include <QTextEdit>
#include <QSystemTrayIcon>
#include <QSplitter>
#endif
#include <QDockWidget>
#include <QSplitter>
/* --------------------- Global Variable START ---------------------- */
QList<Command *> commands;
bool previous_flag_show_thread_prev = false; // previous state
bool flag_show_thread = false; // to see informations at the thread level
int flag_thread_ok = true; // we presume a kernel 2.6.x using NPTL
bool flag_session_start = false;
bool flag_start_mini = false; // Need for Xorg.Session
bool flag_refresh = true; // DEL
bool flag_xcompmgr = false; // DEL test.compiz..
bool flag_devel = false;
bool flag_schedstat = false;
bool flag_smallscreen = false;
bool flag_firstRun = true; // test
Qps *qps;
// ControlBar *controlbar=NULL;
SearchBox *search_box = NULL;
TFrame *infobox = NULL; // testing
// DEL Screenshot *screenshot=NULL;
QFontComboBox *font_cb = NULL;
WatchdogDialog *watchdogDialog = NULL;
/// PDisplay *pdisplay;
QList<Procview *> proclist;
#include "trayicon.h"
TrayIcon *trayicon = NULL;
// for Non-ASCII Languages (CJK:chinese,japanese,korean, arabic ...)
#include <QTextCodec>
QTextCodec *codec = NULL;
#define UniString(str) str // codec->toUnicode(str)
/* ------------------------ END global variables -------------------------- */
// default values of settings, overridden by $HOME/.qpsrc if present
bool Qps::flag_show =
true; // window state of last run : mini(iconic) or normal window
bool Qps::flag_exit = true;
bool Qps::flag_qps_hide = true; // TEST
bool Qps::flag_useTabView = false;
bool Qps::show_file_path = false;
bool Qps::show_cmd_path = true;
bool Qps::show_infobar = true;
bool Qps::show_ctrlbar = true;
bool Qps::show_cpu_bar = true;
bool Qps::show_load_graph = true; // DEL
bool Qps::show_statusbar = true;
bool Qps::load_in_icon = true;
bool Qps::auto_save_options = true;
#ifdef LINUX
bool Qps::hostname_lookup = true;
bool Qps::service_lookup = true;
#endif
bool Qps::pids_to_selection = true;
bool Qps::vertical_cpu_bar = false; // not used
#ifdef SOLARIS
bool Qps::normalize_nice = true;
bool Qps::use_pmap = true;
#endif
bool Qps::tree_gadgets = true;
bool Qps::tree_lines = true;
int Qps::swaplimit = 5; // default: warn when less than 10% swap left
bool Qps::swaplim_percent = true;
QThread *thread_main = 0;
Qps::Qps()
{
setObjectName("qps_main_window");
timer_id = 0;
field_win = 0;
prefs_win = 0;
command_win = 0;
default_icon = 0;
default_icon_set = false;
setIconSize(24, 24); // Important!!
// setMouseTracking(true); // no need?
if (flag_devel)
{
thread_main = thread(); // Test
printf("qps thread =%p , qApp thread =%p\n", thread(),
QApplication::instance()->thread());
}
// watchdogDialog = new WatchdogDialog; //Memory Leak
// font_cb=new QFontComboBox(this); // preload
// font_cb->setWritingSystem ( QFontDatabase::Latin );
// font_cb->hide();
make_signal_popup_menu();
// MOVETO Pstable !!
m_headpopup = new QMenu("header_popup", this);
m_headpopup->addAction("Remove Field", this, SLOT(menu_remove_field()));
m_fields = new QMenu("Add Field", this);
m_headpopup->addMenu(m_fields);
// connect(m_fields, SIGNAL(activated(int)),
// SLOT(add_fields_menu(int)));
// m_headpopup->addAction("Select Field", this, SLOT(menu_custom()) );
m_command = new QMenu("Command", this); // filled in later
QAction *act;
m_view = new QMenu("View", this);
act = m_view->addAction("Process"); // act->setData(Procview::CUSTOM);
act = m_view->addAction("Log"); // act->setData(Procview::CUSTOM);
// m_view->hide();
m_field = new QMenu("Field", this);
act = m_field->addAction("Custom Fields");
act->setData(Procview::CUSTOM);
act = m_field->addAction("Basic Fields ");
act->setData(Procview::USER);
act = m_field->addAction("Jobs Fields ");
act->setData(Procview::JOBS);
act = m_field->addAction("Memory Fields ");
act->setData(Procview::MEM);
#ifdef LINUX
act = m_field->addAction("Scheduling Fields ");
act->setData(Procview::SCHED);
#endif
m_field->addSeparator();
act = m_field->addAction(QIcon::fromTheme(QStringLiteral("edit-find-replace")),
"Select Custom Fields...", this,
SLOT(menu_custom()));
act->setData(MENU_CUSTOM);
connect(m_field, SIGNAL(triggered(QAction *)), this,
SLOT(view_menu(QAction *)));
connect(m_field, SIGNAL(aboutToShow()), SLOT(update_menu_status()));
/// connect(m_view, SIGNAL(triggered(QAction *)),this,
/// SLOT(view_menu(QAction
/// *)));
/// connect(m_view, SIGNAL(aboutToShow ()), SLOT(update_menu_status()));
m_options = new QMenu("Option", this);
m_options->addAction("Update Period...", this, SLOT(menu_update()));
m_options->addSeparator();
act = m_options->addAction("", /* MENU_PATH */ this,
SLOT(menu_toggle_path()));
act->setData(QVariant(MENU_PATH));
act = m_options->addAction("", this, SLOT(menu_toggle_infobar()));
act->setData(QVariant(MENU_INFOBAR));
act = m_options->addAction("", this, SLOT(menu_toggle_ctrlbar()));
act->setData(QVariant(MENU_CTRLBAR));
act = m_options->addAction("Show Status bar", this,
SLOT(menu_toggle_statusbar()));
act->setData(QVariant(MENU_STATUS));
act = m_options->addAction("", this, SLOT(menu_toggle_cumul()));
act->setData(QVariant(MENU_CUMUL));
m_options->addSeparator();
m_options->addAction(QIcon::fromTheme(QStringLiteral("preferences-system")),
"Preferences...", this,
SLOT(menu_prefs())); // MENU_PREFS
connect(m_options, SIGNAL(aboutToShow()), SLOT(update_menu_status()));
QMenu *m_help = new QMenu("Help", this);
// m_help->addAction("FAQ", this, SLOT(license()));
m_help->addAction(QIcon::fromTheme("help-about"), "Feedback", this,
SLOT(about()));
// menu = new QMenuBar(this);
menubar = new QMenuBar;
menubar->addMenu(m_command);
// am_view=menubar->addMenu(m_view);
menubar->addMenu(m_field);
menubar->addMenu(m_options);
menubar->addSeparator();
menubar->addMenu(m_help);
ctrlbar = new ControlBar(this);
// controlbar=ctrlbar;
connect(ctrlbar, SIGNAL(need_refresh()), SLOT(refresh()));
connect(ctrlbar, SIGNAL(viewChange(QAction *)),
SLOT(view_menu(QAction *))); //?????
context_col = -1;
procview = new Procview(); // refresh() only not rebuild()
/// procview = new Procview("localhost"); // refresh() only not rebuild()
/// procview->refresh(); // TODO
/// proclist.append(procview);
/// procview->start(); // thread start
#ifdef HTABLE2
pstable = new Pstable2(this, procview); //
#else
pstable = new Pstable(this, procview); // no refresh()
#endif
PDisplay *display = new PDisplay(this);
infobar = display->addSystem(procview);
//. infobar = new Infobar(this,procview); // graph_bar
// infobar = new Infobar(procview); // graph_bar
statusBar = new StatusBar(this);
if (!read_settings())
{
// printf("default value\n");
set_update_period(1300); // default
resize(640, 370); // default initial size
}
set_table_mode(procview->treeview); // Pstable::refresh() occur
make_command_menu(); // after qpsrc reading
// misc. accelerators
QShortcut *c1 =
new QShortcut(Qt::CTRL + Qt::Key_Q, this, SLOT(save_quit()));
QShortcut *c3 = new QShortcut(Qt::CTRL + Qt::Key_Space,
ctrlbar->pauseButton, SLOT(click()));
QShortcut *c2 =
new QShortcut(Qt::CTRL + Qt::Key_L, pstable, SLOT(repaintAll()));
// MOVETO : pstable better? hmmm...
// where is leftClick?
connect(pstable, SIGNAL(doubleClicked(int)), SLOT(open_details(int)));
connect(pstable, SIGNAL(rightClicked(QPoint)), this,
SLOT(show_popup_menu(QPoint)));
connect(pstable->header(), SIGNAL(rightClicked(QPoint, int)), this,
SLOT(context_heading_menu(QPoint, int)));
// connect(netable, SIGNAL(rightClicked(QPoint)), this,
// SLOT(context_row_menu(QPoint)));
selection_items_enabled = true; // ????
update_load_time = 0;
//// update_menu_status();
QVBoxLayout *vlayout = new QVBoxLayout;
vlayout->setMargin(0);
if (flag_useTabView)
vlayout->setSpacing(0);
else
vlayout->setSpacing(1);
// vlayout->addWidget(menu);
vlayout->setMenuBar(menubar);
vlayout->addWidget(display);
// vlayout->addWidget( infobar);
vlayout->addWidget(ctrlbar);
/// vlayout->addSpacing(5);
// if(flag_devel){
if (0)
{
if (0)
{
QSplitter *splitter = new QSplitter(Qt::Vertical);
QDockWidget *dock = new QDockWidget(tr("Detail"), this);
dock->setFeatures(QDockWidget::DockWidgetClosable);
// dock->setWidget();
// dock->setAllowedAreas(Qt::LeftDockWidgetArea |
// Qt::RightDockWidgetArea);
// customerList = new QListWidget(dock);
// vlayout->addStretch();
splitter->addWidget(pstable);
splitter->addWidget(dock);
vlayout->addWidget(splitter);
vlayout->addWidget(statusBar);
setLayout(vlayout);
}
}
logbox = new QTextEdit(this);
logbox->setReadOnly(true);
if (0) // if(flag_smallscreen==false)
{
//
}
else
{
vlayout->addWidget(pstable);
vlayout->addWidget(logbox);
logbox->hide();
}
vlayout->addWidget(statusBar);
setLayout(vlayout);
infobox = new TFrame(this);
// setAttribute(Qt::WA_ShowWithoutActivating);
if (update_period != eternity)
Qps::update_timer(); // startTimer(update_period);
/// setFocusPolicy (Qt::WheelFocus);
bar_visibility(); // need
// testing
popupx = new QMenu("test", this);
popupx->addAction("Copied to Clipboard");
}
// explicit destructor needed for gcc
Qps::~Qps() {}
void Qps::tabChanged(int idx)
{
/*
for(int i; i<1024;i++)
{
QFont font;
if(font_cb)
font=font_cb->currentFont();
//font=font_cb->currentFont();
QApplication::setFont(font);
}
printf("tab\n");
*/
if (idx == 0)
{
procview->viewproc = Procview::ALL;
pstable->refresh();
// pstable->update();
}
else if (idx == 1)
{
// procview->viewproc=Procview::NETWORK;
// netable->refresh();
// netable->update();
}
}
// return true if all selected processes are stopped
bool Qps::all_selected_stopped()
{
for (int i = 0; i < procview->linear_procs.size(); i++)
{
Procinfo *p = procview->linear_procs[i];
if (p->selected && p->state != 'T')
return false;
}
return true;
}
// Adjust menu to contain Stop or Continue
void Qps::adjust_popup_menu(QMenu *m, bool cont)
{
// int idx = m->indexOf(MENU_DETAILS);
if (procview->treeview == true)
{
// m->setItemVisible (MENU_PARENT,false);
// m->setItemVisible (MENU_CHILD,false);
// m->setItemVisible (MENU_DYNASTY,false);
}
else
{
// m->setItemVisible (MENU_PARENT,true);
// m->setItemVisible (MENU_CHILD,true);
// m->setItemVisible (MENU_DYNASTY,true);
}
if (procview->viewproc == Procview::HIDDEN)
{
// m->setItemVisible (MENU_ADD_HIDDEN,false);
// m->setItemVisible (MENU_REMOVE_HIDDEN,true);
}
else
{
// m->setItemVisible (MENU_ADD_HIDDEN,true);
// m->setItemVisible (MENU_REMOVE_HIDDEN,false);
}
}
//
void Qps::adjust_popup_menu()
{
bool allstop = all_selected_stopped();
QList<QAction *> list = m_popup->actions();
// printf("adjust_popup_menu () size=%d \n",list.size());
if (allstop)
for (int i = 0; i < list.size() - 1; i++)
{
QAction *act = list[i];
int id = act->data().toInt();
if (id == MENU_SIGCONT)
act->setVisible(true);
if (id == MENU_SIGSTOP)
act->setVisible(false);
}
else
for (int i = 0; i < list.size() - 1; i++)
{
QAction *act = list[i];
int id = act->data().toInt();
if (id == MENU_SIGCONT)
act->setVisible(false);
if (id == MENU_SIGSTOP)
act->setVisible(true);
}
}
// build signal menu (used in two places)
QMenu *Qps::make_signal_popup_menu()
{
// move to pstable?
QAction *act; // show_popup_menu() callback
m_popup = new QMenu("context popup", this);
m_popup->addAction("Renice...", this, SLOT(menu_renice()));
m_popup->addAction("Scheduling...", this, SLOT(menu_sched()));
m_popup->addSeparator();
m_popup->addAction("Terminate", this, SLOT(sig_term()),
Qt::Key_Delete); // better
m_popup->addAction("Hangup", this, SLOT(sig_hup()), Qt::ALT + Qt::Key_H);
m_popup->addAction("Kill", this, SLOT(sig_kill()), Qt::ALT + Qt::Key_K);
act = m_popup->addAction("Stop", this, SLOT(sig_stop()));
act->setData(MENU_SIGSTOP);
act = m_popup->addAction("Continue", this, SLOT(sig_cont()));
act->setData(MENU_SIGCONT);
// connect(m_popup, SIGNAL(aboutToShow ()),this,
// SLOT(adjust_popup_menu()));
/// m_popup->addAction("Find Parent", this,
/// SLOT(menu_parent()),0,MENU_PARENT);
/// m_popup->addAction("Find Children", this,
/// SLOT(menu_children()),0,MENU_CHILD);
/// m_popup->addAction("Find Descendants", this,
/// SLOT(menu_dynasty()),0,MENU_DYNASTY);
QMenu *m = new QMenu("Other Signals");
act = m->addAction("SIGINT (interrupt)");
act->setData(SIGINT);
act = m->addAction("SIGCONT (continue)");
act->setData(SIGCONT);
act = m->addAction("SIGSTOP (stop)");
act->setData(SIGSTOP);
act = m->addAction("SIGQUIT (quit)");
act->setData(SIGQUIT);
act = m->addAction("SIGILL (illegal instruction)");
act->setData(SIGILL);
act = m->addAction("SIGABRT (abort)");
act->setData(SIGABRT);
act = m->addAction("SIGFPE (floating point exception)");
act->setData(SIGFPE);
act = m->addAction("SIGSEGV (segmentation violation)");
act->setData(SIGSEGV);
act = m->addAction("SIGPIPE (broken pipe)");
act->setData(SIGPIPE);
act = m->addAction("SIGALRM (timer signal)");
act->setData(SIGALRM);
act = m->addAction("SIGUSR1 (user-defined 1)");
act->setData(SIGUSR1);
act = m->addAction("SIGUSR2 (user-defined 2)");
act->setData(SIGUSR2);
act = m->addAction("SIGCHLD (child death)");
act->setData(SIGCHLD);
act = m->addAction("SIGTSTP (stop from tty)");
act->setData(SIGTSTP);
act = m->addAction("SIGTTIN (tty input)");
act->setData(SIGTTIN);
act = m->addAction("SIGTTOU (tty output)");
act->setData(SIGTTOU);
connect(m, SIGNAL(triggered(QAction *)), SLOT(signal_menu(QAction *)));
m_popup->addMenu(m);
m_popup->addSeparator();
m_popup->addAction("View Details", this, SLOT(Action_Detail()));
return m;
}
void Qps::signal_menu(QAction *act)
{
int signal = act->data().toInt();
send_to_selected(signal);
}
#ifdef MOSIX
// build migrate menu
static int intcmp(const int *a, const int *b) { return *a - *b; }
QMenu *Qps::make_migrate_menu()
{
QString buf;
QMenu *m = new QMenu;
Svec<int> lst = Procinfo::mosix_nodes();
lst.sort(intcmp); /// sort
m->insertItem("Home", 1);
m->insertItem("Find Best", 0);
for (int i = 0; i < lst.size(); i++)
{
buf.sprintf("to node %d", lst[i]);
m->insertItem(buf, lst[i] + 1);
}
return m;
}
#endif // MOSIX
// update the visibility of the {info, control, status} bar
void Qps::bar_visibility()
{
if (show_infobar)
infobar->show();
else
infobar->hide();
if (show_ctrlbar)
ctrlbar->show();
else
ctrlbar->hide();
if (show_statusbar)
statusBar->show();
else
statusBar->hide();
if (flag_useTabView)
{
// DEL tbar->showTab(true);
/// am_view->setVisible(false);
}
else
{
// DEL tbar->showTab(false);
// am_view->setVisible(true);
}
}
void Qps::timerEvent(QTimerEvent *e) { Qps::refresh(); }
//
// dialogs.cpp: qps->update_timer();
void Qps::update_timer()
{
if (timer_id)
killTimer(timer_id);
timer_id = startTimer(update_period); // *** important !!!
}
// change the update period, recomputing the averaging factor
void Qps::set_update_period(int milliseconds)
{
if (milliseconds == 0)
{
qDebug("DEBUG: set_update_period(): update= %dms \n", milliseconds);
milliseconds = 1000;
}
update_period = milliseconds;
Proc::update_msec = milliseconds; // testing transfer...
Procview::avg_factor = exp(-(float)update_period / Procview::cpu_avg_time);
}
void Qps::refresh()
{
if (flag_refresh == false)
return;
procview->refresh(); // important
// infobar->update_load(); // add_point and drawGraphOnPixmap();
infobar->updatePixmap(); // add_point and drawGraphOnPixmap();
if (isVisible())
{ // infobar->isVisible()
// printf("paint\n");
// if(search_box and !search_box->hasFocus())
// search_box->setFocus(Qt::OtherFocusReason);
pstable->refresh();
// if(netable and netable->isVisible())netable->refresh();
if (show_infobar) // if(Qps::show_load_graph)
infobar->update(); // TODO: thread update or
// infobar->repaint();
//==> pdisplay->update();
// DEL update_menu_selection_status(); // update pop menu
}
if (trayicon)
update_icon(); // make icon for systray
refresh_details();
}
// make next timer_refresh happen a little earlier to remove processes that
// might have died after a signal
void Qps::earlier_refresh()
{
const int delay = 500; // wait no more than this period (ms)
if (update_period > delay && update_period != eternity)
{
}
}
void Qps::resizeEvent(QResizeEvent *e)
{
// DEBUG("Qps::resize() w=%d\n",e->size().width());
// QWidget::resizeEvent(event);
int w;
return;
// search_box->isVisible(true); // imidiate
w = ctrlbar->sizeHint().width();
if (!search_box->isVisible())
w += search_box->sizeHint().width();
if (e->size().width() < w)
{
// ctrlbar->
search_box->hide();
}
// else search_box->show();
return;
if (e->size().width() < 639)
{
// tbar->setDrawBase (false);
flag_smallscreen = true;
statusBar->hide();
// void QTabWidget::setTabEnabled ( int index, bool enable
//)
}
else
{
flag_smallscreen = false;
statusBar->show();
}
}
/*
Description :
1. called when visible() or hide() state. QT4
2. called when clicked WINDOW_EXIT_X_BUTTON
3. NOT called when user logout (session manager)
*/
void Qps::closeEvent(QCloseEvent *e)
{
// DEBUG("DEBUG: closeEvent()....\n");
// sleep(2);
if ((Qps::flag_exit == false) and trayicon->hasSysTray())
{
e->ignore(); // dont close window!
hide();
return;
}
e->accept(); // ok. I will be exit Now !!
save_quit();
}
// call by void Qps::make_command_menu()
// void signal_handler(int sig)
void Qps::save_quit() // will be removed !
{
// printf("DEBUG: save_quit()....\n");
close(); // if another window exists, then no exit. // occurs
// QCoseEvent!
save_settings();
qApp->quit(); // MACRO
}
// NEW Version !
// : write geometry, visible fields and other settings to $HOME/.qpsrc
void Qps::save_settings()
{
if (Qps::auto_save_options)
write_settings();
}
void Qps::leaveEvent(QEvent *event)
{
// printf("out!xx\n"); //works well
}
void Qps::enterEvent(QEvent *event)
{
// printf("in!\n"); // works well
}
void Qps::showEvent(QShowEvent *event)
{
// printf("showEvent()\n");
// event->accept();
}
void Qps::mouseMoveEvent(QMouseEvent *event)
{
// printf("Qps::mouseMoveEvent\n"); //work in child surface without
// setMouseTracking(true);
}
// setFocusPolicy() should on
void Qps::focusInEvent(QFocusEvent *event)
{
// printf("focusIn\n"); // not work in compiz,Metacity
// infobar->showup();
// event->accept();
}
void Qps::focusOutEvent(QFocusEvent *event)
{
// printf("focusOut\n"); // not work in compiz,Metacity
// event->accept();
}
void Qps::keyPressEvent(QKeyEvent *event)
{
// printf("Qps::key\n"); // not work in compiz
if (search_box)
{
if (!search_box->hasFocus())
search_box->setFocus(Qt::OtherFocusReason);
search_box->keyPressEvent(event);
}
// search_box->setFocusProxy(pstable);
}
void Qps::moveEvent(QMoveEvent *event)
{
////infobar->refresh();
// printf("move\n");
}
void Qps::paintEvent(QPaintEvent *event)
{
// printf("paintEvent : Qps\n");
// update_icon();
}
void Qps::update_icon()
{
if (load_in_icon)
set_load_icon(); // always true
else
set_default_icon();
}
// called by update_icon()
void Qps::set_default_icon()
{
if (!default_icon_set)
{
if (!default_icon)
default_icon = new QPixmap((const char **)icon_xpm);
setWindowIcon(*default_icon);
default_icon_set = true;
}
}
void Qps::set_load_icon()
{
QPixmap *pm = infobar->load_icon(icon_width, icon_height);
if (!pm->mask())
{
// avoid a fvwm/Qt 1.30 problem and create a filled mask for the
// icon
// (without mask, Qt would attempt to use a heuristically
// created mask)
QBitmap bm(pm->size());
bm.fill(Qt::color1);
pm->setMask(bm);
}
// QApplication::setWindowIcon(*pm);
if (trayicon->hasSysTray())
{
trayicon->setIcon(*pm);
// str.sprintf("Qps %2.2f%",Procinfo::loadQps);
// trayicon->setToolTip(str);
// trayicon->showMessage("str",str);
}
// else
setWindowIcon(*pm);
// QApplication::setWindowIcon(*pm);
default_icon_set = false;
}
QPixmap *Qps::get_load_icon()
{
return infobar->load_icon(icon_width, icon_height);
}
//
void Qps::refresh_details()
{
//// details.first();
////Details d;
#ifdef LINUX
// Proc::invalidate_sockets();
#endif
for (int i = 0; i < details.size(); ++i)
{
/////Details *d=details[i]
////if(details[i].isVisible())
/////details[i].refresh();
}
/*
while((d = details.current()) != 0) {
if(d->isVisible())
d->refresh();
details.next();
} */
}
// called by
// 1.void Qps::field_removed(int index)
// ====> QMenu::aboutToShow ()
void Qps::update_menu_status()
{
// printf("update_menu_status\n");
update_menu_selection_status();
// ctrlbar->view->setCurrentItem (procview->viewproc); //???
// Field Menu
QList<QAction *> list = m_field->actions();
for (int i = 0; i < list.size() - 1; i++)
{
QAction *act = list[i];
act->setCheckable(true);
int id = act->data().toInt();
if (id == procview->viewfields)
act->setChecked(true);
else
act->setChecked(false);
}
// View Menu temporary
/*
QString str=tbar->tabText(tbar->currentIndex());
list=m_view->actions();
for(int i =0 ;i< list.size() ;i++)
{
QAction *act=list[i];
act->setCheckable(true);
if(act->text()==str)
{
act->setChecked(true);
}
else
act->setChecked(false);
} */
// Option Menu
list = m_options->actions();
for (int i = 0; i < list.size() - 1; i++)
{
QAction *act = list[i];
int id = act->data().toInt();
if (id == MENU_PATH)
{
act->setCheckable(true);
act->setChecked(Procview::flag_show_file_path);
act->setText("Show File Path");
// act->setText(Procview::flag_show_file_path?
//"Hide File Path" :
//"Show File Path");
}
else if (id == MENU_INFOBAR)
{
act->setCheckable(true);
act->setChecked(show_infobar);
act->setText("Show Graph");
// act->setText(show_infobar ? "Hide Graph" : "Show
// Graph");
}
else if (id == MENU_CTRLBAR)
{
act->setCheckable(true);
act->setChecked(show_ctrlbar);
act->setText("Show Control Bar");
// act->setText(show_ctrlbar ? "Hide Control bar" :
// "Show Control
// Bar");
}
else if (id == MENU_STATUS)
{
act->setCheckable(true);
act->setChecked(show_statusbar);
}
else if (id == MENU_CUMUL)
{
act->setCheckable(true);
act->setChecked(Procview::flag_cumulative);
act->setText("Include Child Times");
// act->setText(Procview::flag_cumulative ?
// "Exclude Child Times" :
// "Include Child Times");
}
}
}
// need to change name , redesign
void Qps::view_menu(QAction *act)
{
int id = act->data().toInt();
if (act->text() == "Process")
{
// tbar->setCurrentIndex(0);
return;
}
if (act->text() == "Log")
{
// tbar->setCurrentIndex(1);
return;
}
int state = id;
if (id >= Procview::ALL && id <= Procview::HIDDEN)
{
if (procview->viewproc != state)
{
procview->viewproc = state;
}
}
if (id >= Procview::USER && id <= Procview::CUSTOM)
{
if (procview->viewfields != state)
{
procview->viewfields = state;
procview->set_fields();
}
}
pstable->refresh(); // layout
/// update_menu_status();
}
// called when selection changed & update time
// void Qps::update_menu_status()
// void Qps::make_command_menu()
// DEL.
// -> show_popup_menu()
void Qps::update_menu_selection_status()
{
// bool enabled = (pstable->numSelected() > 0);
// if(enabled)
if (0)
{
bool cont = all_selected_stopped();
adjust_popup_menu(m_popup, cont);
}
for (int i = 0; i < commands.size(); i++)
{
/* if (commands[i]->IsNeedProc()==false)
m_command->setItemEnabled(MENU_FIRST_COMMAND + i, true);
else m_command->setItemEnabled(MENU_FIRST_COMMAND + i, enabled);
*/}
}
// call by SearchBox::keyPressEvent
// slot
void Qps::sig_term() { send_to_selected(SIGTERM); }
void Qps::sig_hup() { send_to_selected(SIGHUP); }
// need
void Qps::sig_stop()
{
send_to_selected(SIGSTOP);
// test
for (int i = 0; i < procview->linear_procs.size(); i++)
{
Procinfo *p = procview->linear_procs[i];
if (p->selected)
{
p->test_stop = 1; // who ??
// sendsig(p, sig);
}
}
}
void Qps::sig_cont()
{
send_to_selected(SIGCONT);
// test
for (int i = 0; i < procview->linear_procs.size(); i++)
{
Procinfo *p = procview->linear_procs[i];
if (p->selected)
p->test_stop = 0;
}
}
void Qps::sig_kill() { send_to_selected(SIGKILL); }
void Qps::menu_custom()
{
//// view_menu(Procview::CUSTOM); // should !!
if (field_win)
{
field_win->show();
field_win->raise();
}
else
{
field_win = new FieldSelect(procview);
setWindowGroup(field_win);
field_win->show();
connect(field_win, SIGNAL(added_field(int)), this,
SLOT(field_added(int)));
connect(field_win, SIGNAL(removed_field(int)), this,
SLOT(field_removed(int)));
}
}
// MOVE TO PSTABlE ? hmmm wait...
// Interface for reading_setting()
// SLOT:
//
// called by
// 1.click Tree_checkbox
// 2.void Qps::view_menu(int id)
void Qps::set_table_mode(bool treemode)
{
// qDebug("set_table_mode()\n");
ctrlbar->setMode(treemode); // toggle checkbox
pstable->setTreeMode(treemode); // first pstable->refresh();
}
// Slot:
// SEGFAULT CODE: MOVETO Pstable
// called by
// 1. void Qps::add_fields_menu(int id)
// 2. field_win
void Qps::field_added(int field_id)
{
int where = -1;
where = pstable->clickedColumn();
procview->addField(field_id, where);
pstable->refresh(); // pstable->update(); // repaint
// update_menu_status();
}
// MOVETO Proview
// what this hell? SEGFAULT!
// call by
// 1. FieldSelect
// 2. void Qps::menu_remove_field()
void Qps::field_removed(int index)
{
/// printf("field_removed() index=%d\n",index);
procview->removeField(index);
if (procview->treeview and index == F_CMD)
set_table_mode(false);
// should be changed to linear mode !!
/// update_menu_status(); // ???
// pstable->update(); // no
pstable->refresh();
context_col = -1; // *** important **** : right clicked column removed
return;
}
// moveto command?
void Qps::menu_edit_cmd()
{
if (command_win)
{
command_win->show();
command_win->raise();
}
else
{
command_win = new CommandDialog();
setWindowGroup(command_win);
command_win->show();
connect(command_win, SIGNAL(command_change()),
SLOT(make_command_menu()));
}
}
// init command menu
// callback by CommandDialog::add_new()
void Qps::make_command_menu()
{
// should clear SIGNAL!!!
QAction *act;
m_command->clear();
m_command->disconnect();
if (flag_devel)
{
m_command->addAction("WatchDog", watchdogDialog,
SLOT(show())); //, m_event);
// m_command->addAction("ScreenShot", screenshot,
// SLOT(show()) );
act = m_command->addAction("Edit Commands...", this,
SLOT(menu_edit_cmd()));
// act->setEnabled(false);
}
// if(commands.size()) m_command->addSeparator();
add_default_command();
for (int i = 0; i < commands.size(); i++)
{
// commands[i]->menu = m_command->insertItem(commands[i]->name,
// MENU_FIRST_COMMAND + i);
// commands[i]->menu =
act = m_command->addAction(commands[i]->name);
// connect(act, SIGNAL(triggered(bool )),
// SLOT(signal_menu(bool)));
}
connect(m_command, SIGNAL(triggered(QAction *)),
SLOT(run_command(QAction *)));
update_menu_selection_status(); // DEL
//#ifdef SOLARIS
/* Solaris CDE don't have a tray, so we need a method to terminate */
m_command->addSeparator();
m_command->addAction(QIcon::fromTheme(QStringLiteral("application-exit")), "&Quit", this,
SLOT(save_quit()), Qt::ALT + Qt::Key_Q);
//#endif
}
// run by MENU_ID ? qt slot?
// void Qps::run_command(int command_id)
void Qps::run_command(QAction *act)
{
int command_id;
int i, j, idx = -1;
// FUNC_START
// printf("%s\n",qPrintable(act->text()));
AddLog(act->text());
// find_command
for (i = 0; i < commands.size(); i++)
{
// if(commands[i]->menu==command_id)
if (commands[i]->name == act->text())
{
if (commands[idx]->IsNeedProc() == false)
{
commands[idx]->call(NULL);
return;
}
for (int i = 0; i < procview->linear_procs.size(); i++)
{
Procinfo *p = procview->linear_procs[i];
if (p->selected)
commands[idx]->call(p);
}
break;
}
}
return;
}
// detail
void Qps::Action_Detail()
{
for (int i = 0; i < procview->linear_procs.size(); i++)
{
Procinfo *p = procview->linear_procs[i];
if (p->selected)
open_details(i);
}
}
// MOVETO : pstable.cpp
void Qps::open_details(int row)
{
Procinfo *p = procview->linear_procs[row];
if (p->detail)
{
// p->detail->raise();
p->detail->show();
printf("show detail \n");
}
else
{
Details *d = new Details(p, procview);
// details.append(*d);
// setWindowGroup(d);
d->show();
/// connect(d, SIGNAL(closed(Details *)), this,
/// SLOT(details_closed(Details
///*)));
}
}
void Qps::details_closed(Details *d)
{
// printf("details_closed()\n");
// disconnect
// This is potentially dangerous, since this is called in response to a
// signal sent by the widget that is about to be deleted here. Better
// hope
// that nobody references the object down the call chain!
// what ??????
//////details.removeAt(*d); // deletes window
// details.removeAt(*d); // deletes window
}
// find parents of selected processes
void Qps::menu_parent() { locate_relatives(&Procinfo::ppid, &Procinfo::pid); }
void Qps::menu_children() { locate_relatives(&Procinfo::pid, &Procinfo::ppid); }
// Find processes whose attribute b is equal to the attribute a of
// selected processes. Center around topmost found.
// This is quadratic in worst case (shouldn't be a problem)
// called by
// 1.menu_children()
// 2.menu_parent()
void Qps::locate_relatives(int Procinfo::*a, int Procinfo::*b)
{
QList<int> relatives;
const int infinity = 2000000000;
int topmost = infinity;
for (int i = 0; i < procview->linear_procs.size(); i++)
{
Procinfo *p = procview->linear_procs[i];
if (p->selected)
{
pstable->setSelected(i, false);
for (int j = 0; j < procview->linear_procs.size(); j++)
{
Procinfo *q = procview->linear_procs[j];
if (p->*a == q->*b)
{
relatives.append(j);
if (j < topmost)
topmost = j;
}
}
}
}
for (int i = 0; i < relatives.size(); i++)
pstable->setSelected(relatives[i], true);
/// if(topmost < infinity) pstable->centerVertically(topmost);
//// pstable->selectionNotify();
}
// select all (direct and indirect) offsprings of currently selected
// processes, without deselecting them
void Qps::menu_dynasty()
{
QList<int> family;
for (int i = 0; i < procview->linear_procs.size(); i++)
if (pstable->isSelected(i))
family.append(i);
for (int i = 0, j = family.size(); i < j;)
{
for (int k = 0; k < procview->linear_procs.size(); k++)
{
Procinfo *p = procview->linear_procs[k];
for (int m = i; m < j; m++)
{
Procinfo *q = procview->linear_procs[family[m]];
if (q->pid == p->ppid)
family.append(k);
}
}
i = j;
j = family.size();
}
const int infinity = 2000000000;
int topmost = infinity;
for (int i = 0; i < family.size(); i++)
{
pstable->setSelected(family[i], true);
if (family[i] < topmost)
topmost = family[i];
}
////if(topmost < infinity) pstable->centerVertically(topmost);
////pstable->selectionNotify();
}
// CALLBACK: called when right button is clicked in table
void Qps::show_popup_menu(QPoint p)
{
#ifdef MOSIX
bool may_migrate = false;
for (int i = 0; i < procview->linear_procs.size(); i++)
{
Procinfo *p = procview->linear_procs[i];
if (p->selected && p->cantmove.isEmpty())
{
may_migrate = true;
break;
}
}
m_popup->setItemEnabled(POPUP_MIGRATE, may_migrate);
#endif
adjust_popup_menu();
m_popup->popup(p);
}
// called when right button is clicked in heading
//
void Qps::context_heading_menu(QPoint p, int col)
{
context_col = col; // ****
////printf("context_col=%d\n",col);
static int init = 0;
// rebuild the submenu: only include non-displayed fields
int ncats = procview->categories.size();
if (init == 0)
{
/* #ifdef SHash
SHash<int,Category *>::const_iterator it=procview->categories.begin();
QList<int> keys;
for ( ; it != procview->categories.end(); it++ )
keys.append((*it).first);
#else
*/ QList<int> keys = procview->categories.keys();
// #endif
for (int i = 0; i < ncats; i++)
{
Category *cat = procview->categories[keys.takeFirst()];
QAction *act = m_fields->addAction(cat->name);
act->setData(cat->id); // index==key
}
connect(m_fields, SIGNAL(triggered(QAction *)), this,
SLOT(add_fields_menu(QAction *)));
init = 1;
}
QBitArray displayed(64); // MAX_FIELDS
displayed.fill(false);
// printf("categories.size=%d cats.size=%d\n",ncats,
// procview->cats.size());
for (int i = 0; i < procview->cats.size(); i++)
{
// printf("cat id=%d \n",procview->cats[i]->id);
displayed.setBit(procview->cats[i]->id);
}
QList<QAction *> la = m_fields->actions();
for (int j = 0; j < la.size(); j++)
{
QAction *act = la[j];
int id = act->data().toInt();
if (!displayed.testBit(id))
act->setVisible(true);
else
act->setVisible(false);
}
m_headpopup->popup(p);
}
void Qps::add_fields_menu(QAction *act)
{
// act->text();
int id = act->data().toInt();
field_added(id);
// add_fields_menu(id);
}
// called when field is added from heading context menu
// called by 1. context_heading_menu
void Qps::add_fields_menu(int cat_id)
{
field_added(cat_id);
context_col = -1;
// if(field_win) field_win->update_boxes(); // change to showEvent. !!!!
}
//
void Qps::menu_remove_field()
{
if (context_col < 0)
return;
/// printf("cats.size=%d , context_col=%d
/// \n",procview->cats.size(),context_col);
field_removed(procview->cats[context_col]->index);
}
void Qps::menu_update()
{
QString txt;
if (update_period == eternity)
txt = "1 s";
else if (update_period % 1000 == 0)
txt.sprintf("%d s", update_period / 1000);
else
txt.sprintf("%d ms", update_period);
IntervalDialog id(txt.toUtf8().data(), update_period != eternity);
id.exec();
/// save_settings();
return;
}
void Qps::menu_toggle_path()
{
Procview::flag_show_file_path = !Procview::flag_show_file_path;
/// table refresh() !
}
void Qps::menu_toggle_infobar()
{
show_infobar = !show_infobar;
bar_visibility();
}
void Qps::menu_toggle_ctrlbar()
{
show_ctrlbar = !show_ctrlbar;
bar_visibility();
}
void Qps::menu_toggle_statusbar()
{
show_statusbar = !show_statusbar;
bar_visibility();
}
void Qps::menu_toggle_cumul()
{
Procview::flag_cumulative = !Procview::flag_cumulative;
// refresh() !!
}
void Qps::menu_prefs()
{
if (prefs_win)
{
prefs_win->show();
prefs_win->raise();
}
else
{
prefs_win = new Preferences();
setWindowGroup(prefs_win);
prefs_win->show();
prefs_win->raise();
connect(prefs_win, SIGNAL(prefs_change()), this, SLOT(config_change()));
/// connect(infobar, SIGNAL(config_change()), prefs_win,
/// SLOT(update_boxes())); // doesnt need !! --> aboutToShow()
}
}
// if "Preferences" changed
void Qps::config_change()
{
write_settings();
bar_visibility();
// DEL infobar->configure();
/// resizeEvent(0); // in case it caused geometry change
for (int i = 0; i < details.size(); ++i)
{
///// details[i].config_change();
}
/* while((d = details.current()) != 0) {
d->config_change();
details.next();
} */
}
void Qps::menu_renice()
{
// if(pstable->hasSelection() == 0) return;
int defnice = -1000;
// use nice of first selected process as default, and check permission
bool possible = true;
int euid = geteuid();
Procinfo *p = 0;
for (int i = 0; i < procview->linear_procs.size(); i++)
{
p = procview->linear_procs[i];
if (p->selected)
{
if (defnice == -1000)
defnice = p->nice;
if (euid != 0 && euid != p->uid && euid != p->euid)
possible = false;
}
}
if (!possible)
{
QString s;
s.sprintf("You do not have permission to renice the\n"
"selected process%s.\n"
"Only the process owner and the super-user\n"
"are allowed to do that.",
(pstable->hasSelection() == 1) ? "" : "es");
QMessageBox::warning(this, "Permission denied", s);
return;
}
int new_nice;
for (;;)
{
SliderDialog sd(defnice, -20, 19); // Linux kernel : -20 ~ 19
if (!sd.exec())
return;
bool ok;
new_nice = sd.ed_result.toInt(&ok);
if (ok && new_nice >= -20 && new_nice <= 19)
break;
}
int nicecol = procview->findCol(F_NICE);
int statcol = procview->findCol(F_STAT);
#ifdef LINUX
int tmscol = procview->findCol(F_TMS);
#endif
// do the actual renicing
for (int i = 0; i < procview->linear_procs.size(); i++)
{
Procinfo *p = procview->linear_procs[i];
if (p->selected)
{
if (setpriority(PRIO_PROCESS, p->pid, new_nice) < 0)
{
QString s;
switch (errno)
{
case EPERM:
// this shouldn't happen, but (e)uid
// could be changed...
s.sprintf("You do not have permission "
"to renice"
" process %d (",
p->pid);
s.append(p->command);
s.append(").\n"
"Only the process owner and "
"the super-user are"
" allowed to do that.");
QMessageBox::warning(this, "Permission denied", s);
break;
case EACCES:
QMessageBox::warning(this, "Permission denied",
"Only the super-user may lower"
" the nice value of a process.");
return;
}
}
else
{
p->nice = new_nice; // don't wait for update
#ifdef LINUX
p->tms = p->get_tms(); // ditto
#endif
}
}
}
}
void Qps::menu_sched()
{
// if(pstable->hasSelection()==false) return;
if (geteuid() != 0)
{
QMessageBox::warning(this, "Permission denied",
"Only the super-user may change the\n"
"scheduling policy and static priority.");
return;
}
// provide reasonable defaults (first selected process)
Procinfo *p = 0;
for (int i = 0; i < procview->linear_procs.size(); i++)
{
p = procview->linear_procs[i];
if (p->selected)
break;
}
int pol = p->get_policy();
int pri = p->get_rtprio();
SchedDialog sd(pol, pri);
if (!sd.exec())
return;
if (sd.out_policy == SCHED_OTHER)
sd.out_prio = 0; // only allowed value
int plcycol = procview->findCol(F_PLCY);
int rpricol = procview->findCol(F_RPRI);
#ifdef LINUX
int tmscol = procview->findCol(F_TMS);
#endif
for (int i = 0; i < procview->linear_procs.size(); i++)
{
Procinfo *p = procview->linear_procs[i];
if (p->selected)
{
struct sched_param sp;
sp.sched_priority = sd.out_prio;
if (sched_setscheduler(p->pid, sd.out_policy, &sp) < 0)
{
QString s;
if (errno == EPERM)
{
s.sprintf("You do not have permission to "
"change the\n"
"scheduling and/or priority of"
" process %d (",
p->pid);
s.append(p->command);
s.append(").\n"
"Only the super-user may do that.");
QMessageBox::warning(this, "Permission denied", s);
break;
}
}
else
{
p->policy = sd.out_policy; // don't wait for update
p->rtprio = sd.out_prio;
#ifdef LINUX
p->tms = p->get_tms();
#endif
}
}
}
}
#ifdef MOSIX
void Qps::mig_menu(int id) { migrate_selected(id - 1); }
void Qps::migrate_selected(int migto)
{
// User wants to migrate a process somewhere
// Write destination into /proc/XX/goto
int warnremote = 0;
for (int i = 0; i < procview->linear_procs.size(); i++)
{
Procinfo *p = procview->linear_procs[i];
if (p->selected)
{
if (p->isremote)
++warnremote;
char buf[80];
sprintf(buf, "/proc/%d/goto", p->pid);
FILE *f = fopen(buf, "w");
if (f)
{
fprintf(f, "%d", migto);
fclose(f);
}
}
}
if (warnremote)
QMessageBox::warning(this, "Remote migration attempt",
"You can only migrate an immigrated process "
"using qps on the home node.");
earlier_refresh();
}
#else
// Since this is a slot, at least a stub must be defined even when it isn't
// used (moc ignores preprocessor directives)
void Qps::mig_menu(int) {}
#endif // MOSIX
void Qps::send_to_selected(int sig)
{
for (int i = 0; i < procview->linear_procs.size(); i++)
{
Procinfo *p = procview->linear_procs[i];
if (p->selected)
sendsig(p, sig);
}
earlier_refresh(); // in case we killed one
}
void Qps::sendsig(Procinfo *p, int sig)
{
if (kill(p->pid, sig) < 0)
{
// if the process is gone, do nothing - no need to alert the
// user
if (errno == EPERM)
{
QString s;
s.sprintf("You do not have permission to send a signal to"
" process %d (",
p->pid);
s.append(p->command);
s.append(").\n"
"Only the super-user and the owner of the process"
" may send signals to it.");
QMessageBox::warning(this, "Permission denied", s);
// PermissionDialog *pd = new
// PermissionDialog(s,supasswd);
// pd->exec();
}
}
}
// write geometry, visible fields and other settings to $HOME/.qps-settings
#define SETTINGS_FILE ".qpsrc"
// If the file format is changed in any way (including adding new
// viewable fields), QPS_FILE_VERSION must be incremented to prevent
// version mismatches and core dumps
#ifdef LINUX
#define QPS_FILE_VERSION 40 // version of .qps-linux file format
#endif
#ifdef SOLARIS
#define QPS_FILE_VERSION 24 // version of .qps-solaris file format
#endif
struct Sflagvar
{
const char *name;
bool *var;
};
static Sflagvar flagvars[] = {{"ExitOnClose", &Qps::flag_exit},
{"TabView", &Qps::flag_useTabView},
{"SingleCPU", &Procview::flag_pcpu_single},
{"devel", &flag_devel},
{"cmdpath", &Procview::flag_show_file_path},
{"infobar", &Qps::show_infobar},
{"ctrlbar", &Qps::show_ctrlbar},
{"statbar", &Qps::show_statusbar},
{"autosave", &Qps::auto_save_options},
{"cpubar", &Qps::show_cpu_bar},
{"loadgraph", &Qps::show_load_graph},
{"loadicon", &Qps::load_in_icon},
{"selectpids", &Qps::pids_to_selection},
{"tree", &Procview::treeview},
{"cumulative", &Procview::flag_cumulative},
#ifdef LINUX
{"hostname", &Qps::hostname_lookup},
{"service", &Qps::service_lookup}
#endif
#ifdef SOLARIS
{"normalize", &Qps::normalize_nice},
{"pmap", &Qps::use_pmap}
#endif
,
{0, 0}};
char *settings_path(char *name)
{
char *home = getenv("HOME");
if (!home)
return 0;
strcpy(name, home);
strcat(name, "/" SETTINGS_FILE);
return name;
}
#include <QSettings>
extern QList<watchCond *> watchlist;
// 1.Procview should be contstructed !
// 2.
bool Qps::read_settings()
{
char path[512];
if (settings_path(path) == NULL)
{
return false;
}
QSettings set(path, QSettings::NativeFormat);
int v = set.value("version", 0).toInt();
if (v == 0)
return false;
int x, y, w, h;
x = set.value("geometry/x").toInt();
y = set.value("geometry/y").toInt();
w = set.value("geometry/width").toInt();
h = set.value("geometry/height").toInt();
// set.value("geometry/visiable",isVisible());
Qps::flag_show = true;
setGeometry(x, y, w, h);
if (set.value("font/name") != QVariant() and
set.value("font/size") != QVariant())
{
QString fname = set.value("font/name").toString();
int fsize = set.value("font/size").toInt(); // if not exist then 0
QFont font;
font.setFamily(fname);
font.setPointSize(fsize);
QApplication::setFont(font);
}
// Field
procview->cats.clear();
QStringList sl = set.value("field").toStringList();
for (int i = 0; i < sl.size(); i++)
{
QString str = sl[i];
procview->addField(str.toUtf8().data());
}
/// procview->saveCOMMANDFIELD(); // TMP
// procview->idxF_CMD=set.value("F_CMD").toInt();
if (sl.size() ==
0) // *** for safe , if there is no field. this happen when no qpsrc
{
procview->viewfields = Procview::USER;
procview->set_fields(); ///
}
else
{
procview->viewfields = Procview::CUSTOM;
}
QString str = set.value("sort/field").toString(); // procview->sortcat->name
int fid = procview->field_id_by_name(str.toUtf8().data());
int col = procview->findCol(fid);
if (col >= 0)
// pstable->setSortColumn(col); // Pstable::refresh()
procview->setSortColumn(col); // Pstable::refresh()
// pstable -> procview
procview->reversed = set.value("sort/reversed").toBool(); // tmp
sl = set.value("flags").toStringList();
// for(int i=0;i<sl.size();i++)
for (Sflagvar *fs = flagvars; fs->name; fs++)
{
if (sl.contains(fs->name))
*(fs->var) = true;
else
*(fs->var) = false;
}
// procview->treeview=set.value("treeview").toBool();
int i = set.value("interval").toInt();
set_update_period(i);
i = set.value("viewproc").toInt();
procview->viewproc = i;
ctrlbar->view->setCurrentIndex(
i); // procview->viewproc=set.value("viewproc").toInt();
int size = set.beginReadArray("watchdog");
for (int i = 0; i < size; i++)
{
set.setArrayIndex(i);
watchCond *w = new watchCond;
w->putstring(set.value("cat").toString());
watchlist.append(w);
}
set.endArray();
size = set.beginReadArray("commands");
for (int i = 0; i < size; i++)
{
set.setArrayIndex(i);
Command *c = new Command;
c->putString(set.value("cmd").toString());
commands.append(c);
}
set.endArray();
return true;
/*
} else if(strcmp(buf, "swaplim") == 0) {
swaplimit = atoi(p);
swaplim_percent = false;
if(swaplimit < 0) {
swaplimit = -swaplimit;
swaplim_percent = true;
}
fclose(f); */
return true;
}
// USING :
// write geometry, visible fields and other settings to $HOME/.qps-settings
void Qps::write_settings() // save setting
{
char path[512];
if (settings_path(path) == NULL)
{
return;
}
QSettings set(path, QSettings::NativeFormat);
set.setValue("version", QPS_FILE_VERSION);
// set.beginGroup("");
// set.endGroup();
set.setValue("geometry/x",
geometry().x()); // if hide then, wrong value saved!!
set.setValue("geometry/y", geometry().y());
set.setValue("geometry/width", geometry().width());
set.setValue("geometry/height", geometry().height());
set.setValue("geometry/visiable",
isVisible()); // isVisible() ? "show":"hide");
set.setValue("viewproc",
procview->viewproc); // All, your , running process...
/// set.setValue("treeview",procview->treeview);
QStringList sl;
// printf("procview cats.size=%d\n",procview->cats.size());
procview->update_customfield();
set.setValue("field", procview->customfields);
// set.setValue("F_CMD",procview->idxF_CMD);
if (procview->sortcat) // sometimes, sortcat==NULL.
{
set.setValue("sort/field", procview->sortcat->name);
set.setValue("sort/reversed", procview->reversed);
}
// return;
sl.clear();
for (Sflagvar *fs = flagvars; fs->name; fs++)
{
if (*(fs->var))
sl.append(fs->name); // fprintf(f, " %s", fs->name);
}
set.setValue("flags", sl);
// fprintf(f, "swaplim: %d\n" "interval: %d\n",
// swaplim_percent ? -swaplimit :
// swaplimit,
// update_period);
sl.clear();
set.setValue("font/name", QApplication::font().family());
set.setValue("font/size", QApplication::font().pointSize());
set.setValue("interval", update_period);
set.beginWriteArray("watchdog");
for (int i = 0; i < watchlist.size(); i++)
{
set.setArrayIndex(i);
set.setValue("cat", watchlist[i]->getstring());
}
set.endArray();
set.beginWriteArray("commands");
for (int i = 0; i < commands.size(); i++)
{
set.setArrayIndex(i);
set.setValue("cmd", commands[i]->getString());
}
set.endArray();
/*
fprintf(f, "hidden_process:");
for(int i = 0; i < hidden_process.size(); i++) {
if(i!=0) fprintf(f,",");
fprintf(f,"%s",(const char *)hidden_process[i]);
}
*/
/// printf("Qps: setting saved !\n");
}
// set the window_group hint to that of the main (qps) window
// DELETE ? -> need function , why?
void Qps::setWindowGroup(QWidget *w)
{
/*
XWMHints wmh;
wmh.flags = WindowGroupHint;
wmh.window_group = handle();
XSetWMHints(w->x11Display(), w->handle(), &wmh);
*/
}
// DEL
void Qps::setCommand(int argc, char **argv)
{
// bug: argv[0] should really be frobbed into an absolute path name here
/// XSetCommand(x11Display(), handle(), argv, argc);
}
// return host name with domain stripped
QString short_hostname()
{
//// int gethostname(char *name, size_t len); // hyun?
struct utsname u;
uname(&u);
char *p = strchr(u.nodename, '.');
if (p)
*p = '\0';
QString s(u.nodename);
return s;
}
bool opt_eq(const char *arg, const char *opt)
{
if (arg[0] == '-')
arg++;
if (arg[0] == '-')
arg++;
return strncmp(arg, opt, strlen(opt)) == 0;
}
// print some help to stdout and exit
void print_help(char *cmdname)
{
fprintf(stderr, "Usage: qps [options]\n"
"Options:\n"
" -version\t\tversion\n"
" -mini \t\tstart Minimized\n");
}
/// #include <QX11Info>
QByteArray geo;
void Qps::clicked_trayicon()
{
// QT 4.5 bug : hide(), then show() window's pos will be changed a
// little.
if (isMinimized() or (isVisible() == false)) // if hidden
{
// printf("showNormal\n");
// show(); // works..
showNormal(); // works..
return;
}
// METACITY- focus stealing prevention : XRaiseWindow() not work.
// Compiz works well !!
if (isActiveWindow() == false) // if lower than other windows
{
raise();
activateWindow(); // for WindowMaker
return;
}
hide();
}
void Qps::clicked_trayicon(QSystemTrayIcon::ActivationReason r)
{
// printf("ActivationReason = %d\n",r);
if (r == QSystemTrayIcon::Trigger)
{
if (!isHidden())
{
hide();
}
else
{
showNormal();
}
}
if (r == QSystemTrayIcon::Context)
{
}
}
//
void Qps::hideEvent(QHideEvent *event)
{
// printf("hideEvent()\n");
if (trayicon->hasSysTray())
{
// event->accept();
}
// geo=saveGeometry();
}
#include <signal.h>
void signal_handler(int sig)
{
// if(sig==SIGINT) printf("DEBUG: catched SIGINT \n");
// if(sig==SIGTERM)printf("DEBUG: catched SIGTERM \n");
qps->save_quit();
// printf("Qps: suiciding.... wait \n");
printf("Qps: terminating...\n");
}
int main(int argc, char **argv, char **envp)
{
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGKILL, signal_handler);
Lookup::initproctitle(argv, envp); // will be REMOVEd
for (int i = 1; i < argc; i++)
{
if (opt_eq(argv[i], "version"))
{
fprintf(stderr,
"qps version " QPS_VERSION ", using Qt library %s\n",
qVersion());
exit(1);
}
else if (opt_eq(argv[i], "help") || opt_eq(argv[i], "h"))
{
print_help(argv[0]);
exit(1);
}
else if (opt_eq(argv[i], "session") or opt_eq(argv[i], "sm"))
{
flag_session_start = true;
sleep(2); // **** important !! maybe systray runs later
}
else if (opt_eq(argv[i], "min")) // mini
{
flag_start_mini = true;
}
else if (strstr(argv[i], "screen"))
{
// int screenshot_main(int argc, char **argv);
// screenshot_main(argc,argv);
// return 1;
}
}
// codec = QTextCodec::codecForLocale(); // for Local locale
check_system_requirement(); // check kernel version.. etc in proc.cpp
check_qps_running(); // check already qps running. in misc.cpp
QpsApp app(argc, argv);
init_misc(0); // init misc, some test code runs ...
qps = new Qps();
// sleep(20);
QString caption = "";
caption.append(getenv("USER"));
caption.append("@");
caption.append(short_hostname()); // geteuid()
qps->setWindowTitle(UniString(caption));
qps->setWindowIcon(QPixmap((const char **)icon_xpm));
// MOVETO Systray
QMenu *menu = new QMenu(qps);
/// menu->addAction( UniString("About"), qps, SLOT(about()) );
menu->addAction("Show", qps, SLOT(showNormal()));
menu->addAction("Hide", qps, SLOT(hide()));
menu->addSeparator();
if (flag_devel)
menu->addAction("ScreenShot", qps, SLOT(start_screenshot()));
menu->addAction("&Quit", qps, SLOT(save_quit()), Qt::ALT + Qt::Key_Q);
trayicon = new TrayIcon(QPixmap((const char **)icon_xpm /* init icon */),
"qps", menu);
QObject::connect(trayicon, SIGNAL(clicked(const QPoint &)), qps,
SLOT(clicked_trayicon()));
QObject::connect(trayicon, SIGNAL(doubleClicked(const QPoint &)), qps,
SLOT(clicked_trayicon()));
QObject::connect(trayicon,
SIGNAL(activated(QSystemTrayIcon::ActivationReason)), qps,
SLOT(clicked_trayicon(QSystemTrayIcon::ActivationReason)));
trayicon->sysInstall(); // ok
if (flag_session_start or flag_start_mini)
{
if (trayicon->hasSysTray())
{
qps->hide(); // qps->setHidden(true);
}
else
{
qps->showMinimized();
}
}
else
{
qps->show();
}
// Testing
// app.setStyleSheet(" QToolTip { opacity: 100;" "border-width:
// 1px;
// border-style: solid; border-color: rgb(50,110,80); border-radius:
// 4px ;"
//"background-color : rgba(0,0,0); padding: 3px; color: rgb(0,255,150);
//}");
QString str;
str.append("Qps ");
str.append(QPS_VERSION);
str.append(" launched.");
AddLog(str);
return app.exec();
}
#include <QDialog>
#include <QTextBrowser>
#include <QDesktopServices>
#include <QDialogButtonBox>
#include <QClipboard>
void Qps::test_popup(const QUrl &link)
{
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(link.toString(), QClipboard::Clipboard);
popupx->popup(QCursor::pos());
}
void Qps::about()
{
QDialog *diag = new QDialog(this);
diag->setWindowTitle("About");
QVBoxLayout *lay = new QVBoxLayout(diag);
QLabel *label = new QLabel(diag);
// label->setMinimumSize( 400,200 );
label->setOpenExternalLinks(true);
// QLabel::setOpenExternalLinks ( bool open );
QTextBrowser *browser = new QTextBrowser(diag);
browser->setOpenExternalLinks(false);
browser->setOpenLinks(false);
connect(browser, SIGNAL(anchorClicked(const QUrl &)), this,
SLOT(test_popup(const QUrl &)));
lay->addWidget(label);
lay->addWidget(browser);
// QDesktopServices::openUrl(QUrl("file:///", QUrl::TolerantMode));
//
QString str("<h2> qps " QPS_VERSION " - A Visual Process Manager </h2> "
#ifdef SOLARIS
#ifdef _LP64
"64-bit "
#else
"32-bit "
#endif
"Solaris version "
#endif // SOLARIS
"using Qt library ");
str.append(qVersion());
// s.append(url);
str.append(""
"<br>"
"<A "
"HREF=\"http://kldp.net/projects/qps\">http://kldp.net/projects/"
"qps</A>");
label->setText(str);
str = "";
str.append("<center><b> Bug, Complains, Opinion, Patch to </b></center>"
"<center><a href=\"mail://daehyun.yang@gmail.com\" > "
"daehyun.yang@gmail.com </a></center>"
"<br>"
"<center> Contributors </center>"
"<center><i>Olivier.Daudel@u-paris10.fr </i></center>"
"<center><i>jsanchez@todounix.homeip.net </i></center>"
"<center><i>\
Vince Schiavoni (hlingler@verizon.net)\
</i></center>"
"<br>"
"<center>Original Qps by</center>"
"<center><i>"
" Mattias Engdeg?rd\n" //"(f91-men@nada.kth.se)\n"
"</i></center>");
// QPushButton *contribut = new QPushButton(tr("&More"));
// moreButton->setCheckable(true);
// moreButton->setAutoDefault(false);
browser->setText(str);
QDialogButtonBox *bbox =
new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, diag);
lay->addWidget(bbox);
connect(bbox, SIGNAL(accepted()), diag, SLOT(accept()));
diag->exec();
// mb.setIconPixmap(QPixmap((const char **)icon_xpm));
}
void Qps::license() // -> help()
{
QDialog *diag = new QDialog(this);
diag->setWindowTitle("Quick Help");
// diag->setSizeGripEnabled(true) ;
QHBoxLayout *lay = new QHBoxLayout(diag);
QTextBrowser *browser = new QTextBrowser(diag);
browser->setMinimumSize(400, 200);
lay->addWidget(browser);
// QDesktopServices::openUrl(QUrl("file:///", QUrl::TolerantMode));
// QLabel::setOpenExternalLinks ( bool open );
browser->setOpenExternalLinks(true);
browser->setOpenLinks(true);
browser->setText(
"<H1>QPS Help</H1>"
"Updated: May 24 2005<BR>"
"<A "
"HREF=\"http://kldp.net/projects/qps\">http://kldp.net/projects/"
"qps</"
"A><HR>"
"<table style=\"text-align: center; width: 100%;\" border=\"1\""
" cellpadding=\"1\" cellspacing=\"0\">"
" <tbody>"
" <tr>"
" <td"
" style=\"vertical-align: top; background-color: rgb(204, 204, "
"204);\">Quit"
" </td>"
" <td >&nbsp; CTRL + q , CTRL + x"
" </td>"
" </tr>"
" <tr>"
" <td"
" style=\"vertical-align: top; background-color: rgb(204, 204, "
"204);\">Update"
" </td>"
" <td>&nbsp;Space , Enter "
" </td>"
" </tr>"
" <tr><td> process Terminate </td> <td> ALT + T , DELETE </td> "
"</tr>"
" <tr><td> process Kill </td> <td> ALT + K </td> </tr>"
" </tbody>"
"</table>");
diag->exec();
}
// slot
void Qps::start_screenshot() {}
// MOVETO qps::keyPressEvent()
void SearchBox::keyPressEvent(QKeyEvent *e)
{
if (e->key() == Qt::Key_Delete)
{
qps->sig_term();
return;
}
if (e->key() == Qt::Key_Escape)
{
clear(); // clear searchbox
qps->pstable->clearAllSelections(); // TEMP
// xb->setDown(true);
// event_xbutton_clicked();
// xb->setDown(false);
}
else
QLineEdit::keyPressEvent(e);
qps->procview->filterstr = text();
qps->pstable->refresh(); /// qps->refresh(); // better ?
}
void STATUSBAR_COUNT_UPDATE() {}
void STATUSBAR_SETCOUNT(int n)
{
if (qps)
qps->statusBar->update(n);
}
void PSTABLE_SETTREEMODE(bool mode)
{
if (qps)
qps->pstable->setTreeMode(mode);
}
void QPS_SHOW()
{
if (qps)
qps->showNormal();
}
// TESTING
int QPS_PROCVIEW_CPU_NUM()
{
if (qps)
return qps->procview->num_cpus;
else
return 0;
}
void AddLog(QString str)
{
qDebug() << qps;
if (qps && qps->logbox)
{
qps->logbox->append(str);
}
}