/* * qps.cpp * This file is part of qps -- Qt-based visual process status monitor * * Copyright 1997-1999 Mattias Engdegård * Copyright 2005-2012 fasthyun@magicn.com * Copyright 2015- daehyun.yang@gmail.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; either version 2 of the License, or * (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ // 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 #include #include #include #include #include #include // uname #include #include #include #include //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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif #include #include /* --------------------- Global Variable START ---------------------- */ QList 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 proclist; #include "trayicon.h" TrayIcon *trayicon = NULL; // for Non-ASCII Languages (CJK:chinese,japanese,korean, arabic ...) #include 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"), "&About", 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 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 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 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 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 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::const_iterator it=procview->categories.begin(); QList keys; for ( ; it != procview->categories.end(); it++ ) keys.append((*it).first); #else */ QList 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 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 extern QList 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;iname; 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 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 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 #include #include #include #include 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("

qps " QPS_VERSION " - A Visual Process Manager

" #ifdef SOLARIS #ifdef _LP64 "64-bit " #else "32-bit " #endif "Solaris version " #endif // SOLARIS "using Qt library "); str.append(qVersion()); str.append("

" "Source: https://github.com/lxqt/qps/" "
" "Bugtracker: https://github.com/lxqt/qps/issues" ); label->setText(str); str = ""; str.append("Original Qps by
" "Mattias Engdegård (f91-men@nada.kth.se)

" "Contributors
" "Olivier.Daudel@u-paris10.fr
" "jsanchez@todounix.homeip.net
" "daehyun.yang@gmail.com
" "Luís Pereira (luis.artur.pereira@gmail.com)
" "Alf Gaida (agaida@siduction.org)
" "Paulo Lieuthier (paulolieuthier@gmail.com)
" "Jerome Leclanche (jerome@leclan.ch)
" ); 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( "

QPS Help

" "Updated: May 24 2005
" "http://kldp.net/projects/" "qps
" "" " " " " " Quit" " " " " " " " " " Update" " " " " " " " " "" " " " " "
  CTRL + q , CTRL + x" "
 Space , Enter " "
process Terminate ALT + T , DELETE
process Kill ALT + K
"); 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); } }