/* * pstable.cpp * This file is part of qps -- Qt-based visual process status monitor * * Copyright 1997-1999 Mattias EngdegÄrd * * 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. */ // ** toooo complex,so need new Design ... should be more simple.. (by // fasthyun@magicn.com) #include "proc.h" #include "pstable.h" #include "misc.h" ///#include #include #include #include // When a subtree is folded away, selections inside it disappear to prevent // unexpected behaviour static void clear_subtree_selections(Procinfo *p) { for (int i = 0; i < p->table_children.size(); i++) { Procinfo *c = p->table_children[i]; c->selected = false; clear_subtree_selections(c); } } // SLOT : // connect(this, SIGNAL(titleClicked(int)), SLOT(setSortColumn(int))); void Pstable::setSortColumn(int col) { procview->setSortColumn(col, false); setSortedCol(col); // void HeadedTable::setSortedCol(int col) refresh(); // rebuild table } // AWKWARD // sync Procview and HeadedTable set sorted column of table to procview->sortcol // called by 1. Pstable::moveCol(int col, int place) void Pstable::set_sortcol() { for (int i = 0; i < procview->cats.size(); i++) { if (procview->cats[i] == procview->sortcat) { HeadedTable::setSortedCol(i); // HeadedTable return; } } setSortedCol(-1); } // for Optimization int Pstable::sizeHintForColumn(int col) const { // int aw=fontMetrics().averageCharWidth(); int aw = fontMetrics().width("0"); int cat_idx = procview->cats[col]->index; // if(col==0) printf("col.idx=%d // %s\n",cat_idx,procview->cats[col]->name); switch (cat_idx) { // only COMMON Field // case F_PID : case F_RSS: case F_SIZE: case F_TTY: return aw * 6; case F_MEM: case F_START: case F_CPU: // PCPU return aw * 6 + 2; case F_TIME: return aw * 5; case F_WCPU: case F_NICE: return aw * 5; case F_CMD: return -(aw * 20); case F_USER: // case F_USER : return aw*10; case F_CMDLINE: default: return -1; } return -1; } // inner QString Pstable::title(int col) { if (col >= procview->cats.size()) { qDebug("Qps Bug!: title() over col !! %d\n", col); return ""; } return procview->cats[col]->name; } // TESTING void Pstable::overpaintCell(QPainter *p, int row, int col, int xpos) { if (col != 0) return; if (procview->cats[col]->id != F_CMD) return; int w; Procinfo *pi = procview->linear_procs[row]; int n = pi->nthreads; if (n == 1) return; #ifdef LINUX if (pi->pid != pi->tgid) return; // LINUX #endif w = p->fontMetrics().width(text(row, col)); QFont font = p->font(); int size = font.pointSize(); // point size if (size <= 0) return; // saver! int h = body->cellHeight(); h = p->fontMetrics().height(); // return pixel int msize = h * 3.0 / 8.0; // printf("DEBUG: height=%d, msize=%d\n",h,msize); if (h <= 11) return; // saver! if (msize < 6) msize = 6; // font.setPointSize(msize); // not pixel! font.setPixelSize(msize); // not pixel! p->setFont(font); p->drawText(xpos + w + 2, msize + msize / 3, QString::number(n)); font.setPointSize(size); p->setFont(font); } // QString Pstable::text(int row, int col) { if (col >= procview->cats.size()) { qDebug("Qps Bug!: text() over col !! %d\n", col); return ""; } return procview->cats[col]->string(procview->linear_procs[row]); } int Pstable::totalRow() //??? { return procview->linear_procs.size(); } int Pstable::colWidth(int col) { // this is -1 for variable width fields, htable keeps track of it if (col >= procview->cats.size()) { qDebug("Qps Bug!: colWidth() over col !! %d\n", col); return -1; } return procview->cats[col]->width(); } int Pstable::alignment(int col) { // qDebug("debug:alignment()\n"); Category *cat = procview->cats[col]; return cat->alignment(); } // virtual of HeadedTable void Pstable::setSelected(int row, bool flag) { /// qDebug("debug:Pstable::setSelected()\n"); Procinfo *pi = procview->linear_procs[row]; if (pi->selected != flag) { pi->selected = flag; // body->repaintRow(row); // TEMP trick.. } } // virtual bool Pstable::isSelected(int row) { Procinfo *pi = procview->linear_procs[row]; return pi->selected; // VALGRIND } int Pstable::rowDepth(int row) { Procinfo *pi = procview->linear_procs[row]; if (pi) return pi->level; // VALGRIND segfault qDebug("Qps bug: over row %d!!!\n", row); return 0; } bool Pstable::lastChild(int row) { Procinfo *pi = procview->linear_procs[row]; if (pi) return pi->lastchild; qDebug("Qps bug: over row %d!!!\n", row); return 0; } // Segfault !!!! // return not PPID ! just virtual parent in tree int Pstable::parentRow(int row) { return procview->linear_procs[row]->parent_row; /* int ppid= procview->linear_procs[row]->ppid; Procinfo *pi= procview->getProcinfoByPID(ppid); if(pi) return ppid; else return -1; */ } // DRAFT tooltip QString Pstable::tipText(int col) { Category *cat = procview->cats[col]; QString s(cat->help); // trick if (cat->index == F_STAT) s.append("\n(R =Running, S =Sleeping, T =sTopped, Z=Zombie)"); if (cat->index == F_PLCY) s.append("\n(TS =Time Sharing)"); // if(cat->index == F_RSS); // s.append("\nRSS = CODE + DATA + SHARE\n" // "RSS = TRS + DRS + SHARE\n"); /// s.append("\n(RSS = TRS + DRS)"); if (cat == procview->sortcat) s.append(procview->reversed ? "\n(sorted backwards)" : "\n(sorted)"); // printf("size=%d\n",s.capacity()); return s; } void Pstable::showTip(QPoint p, int idx) { QToolTip::showText(p, tipText(idx)); } extern TFrame *infobox; // testing // SLOT void Pstable::mouseOutOfCell() { infobox->hide(); } // TEST void Pstable::mouseOnCell(int row, int col) { // printf("cursor on (%d,%d)\n",row,col); Category *cat = procview->cats[col]; QString s = ""; return; // below TEST code! if (cat->index == F_USER) { Procinfo *pi = procview->linear_procs[row]; s = pi->username; } else { infobox->hide(); return; } if (infobox != NULL) { // p.setY(p.y() + geometry().y()); // p.setY(QCursor::pos().y() - geometry().y()); // p.setY(QCursor::pos().y() - frameGeometry().y()); // p.setX(QCursor::pos().x() - frameGeometry().x()); // QPoint p=QCursor::pos(); // if(htable->numSelected()>=2) infobox->show(); infobox->setPos(); if (s > 0) { infobox->setText(s); } else infobox->hide(); } // char *str=htable->total_selectedRow(col); } void Pstable::leaveEvent(QEvent *) {} // DRAFT who call? // void TableBody::mouseMoveEvent(QMouseEvent *e) char *Pstable::total_selectedRow(int col) { static char buff[48]; char mem_str[48]; std::string name; int index; if (procview->cats.size() <= col or col < 0) return 0; // col == -1 index = procview->cats[col]->index; switch (index) { case F_SIZE: name = "total SIZE: "; break; case F_RSS: name = "total RSS: "; break; #ifdef LINUX case F_TRS: name = "total Text: "; break; case F_DRS: name = "total Data: "; break; case F_STACK: name = "total STACK: "; break; #endif default: return 0; } int total = 0; int rows = procview->linear_procs.size(); for (int i = 0; i < rows; i++) if (procview->linear_procs[i]->selected) { switch (index) { case F_SIZE: total += procview->linear_procs[i]->size; break; case F_RSS: total += procview->linear_procs[i]->resident; break; #ifdef LINUX case F_TRS: total += procview->linear_procs[i]->trs; break; case F_DRS: total += procview->linear_procs[i]->drs; break; case F_STACK: total += procview->linear_procs[i]->stack; break; #endif } } mem_string(total, mem_str); // misc.h strcpy(buff, name.c_str()); strcat(buff, mem_str); // sqDebug(buff,"total:%s",total); return buff; } // col // colMoved(col, place); Pstable::Pstable(QWidget *parent, Procview *pv) : HeadedTable(parent, 0) { procview = pv; // connect(this, SIGNAL(selectionChanged(const Svec //*)),SLOT(selection_update(const Svec *))); //DEL? // connect(this, // SIGNAL(selectionChanged()),SLOT(selection_update())); // // when procinfo clicked connect(this, SIGNAL(titleClicked(int)), SLOT(setSortColumn(int))); connect(this, SIGNAL(foldSubTree(int)), SLOT(subtree_folded(int))); connect(head, SIGNAL(toolTip(QPoint, int)), this, SLOT(showTip(QPoint, int))); connect(this, SIGNAL(flyOnCell(int, int)), SLOT(mouseOnCell(int, int))); connect(this, SIGNAL(outOfCell()), SLOT(mouseOutOfCell())); } // who call this ? : from qps.cpp void Pstable::setProcview(Procview *pv) { procview = pv; } HeadedTable::NodeState Pstable::folded(int row) { Procinfo *p = procview->linear_procs[row]; return (p->table_children.size() > 0) ? (p->hidekids ? Closed : Open) : Leaf; } // slot: called when selection changes // called by // 1.void HeadedTable::selectionNotify() /* void Pstable::selection_update(const Svec *rows) { //CLIPBOARD qDebug("debug:selection_update()\n"); for(int i = 0; i < rows->size(); i++) { int row = (*rows)[i]; procview->linear_procs[row]->selected = isSelected(row); // WRONG !!! } qps->update_menu_selection_status(); if(numSelected() > 0 && qps->pids_to_selection) { // set the X11 selection to "PID1 PID2 PID3 ..." QString s, num; int n = numRows(); for(int i = 0; i < n; i++) { if(isSelected(i)) { num.setNum(procview->linear_procs[i]->pid); s.append(num); if(i < n - 1) s.append(" "); } } // important: this mustn't be called non-interactively since Qt uses // the selection time of the last mouse or keyboard event //// QApplication::clipboard()->setText(s); } } */ // call by // 1.void Qps::set_table_mode(bool treemode) // slot: changes table mode void Pstable::setTreeMode(bool treemode) { // qDebug("Pstable::setTreeMode() %d , procview.treeview // =%d\n",treemode,procview->treeview); // no more HeadedTable::setTreeMode(treemode); HeadedTable::setTreeMode(treemode); procview->treeview = treemode; procview->fieldArrange(); set_sortcol(); refresh(); //==rebuild(); } // bool Pstable::columnMovable(int col) { if (treemode) { if (col == 0) return false; } if (procview->cats[col]->index == F_CMDLINE) return false; return true; } // called by HeadedTable // Description : FIELD movement by mouse drag to place From col // virtual HeadedTable::moveCol(col,place); void Pstable::moveCol(int col, int place) { // qDebug("Pstable::moveCol\n"); procview->moveColumn(col, place); set_sortcol(); //??? procview->fieldArrange(); // update(); refresh(); // width size changed ,... return; // updateColWidth(place); updateColWidth(col);// TEMP } // NEED Check !! // Slot: called when a subtree is opened or closed // row = row number of sheet void Pstable::subtree_folded(int row) { Procinfo *p = procview->linear_procs[row]; p->hidekids = !p->hidekids; if (p->hidekids) clear_subtree_selections(p); // *** important refresh(); // tree rebuild only return; // ??? Procinfo *nextp = (row < numRows() - 1) ? procview->linear_procs[row + 1] : 0; if (!p->hidekids) { // Show as much as possible of the opened subtree int r = row + 1; while (r < numRows() && procview->linear_procs[r] != nextp) r++; // setAutoUpdate(FALSE); showRange(row, r - 1); // setAutoUpdate(TRUE); } // This is a stopgap solution; it would be better to have htable // take care of the hiding of subtrees and repaint only the rows under // the line hidden } // DRAFT CODE: // 1.procview->refresh: proc.refresh, rebuild // 2.resetwidth // 3.repaint // called by // 1.void Qps::refresh() void STATUSBAR_SETCOUNT(int n); static int kgen = 123; void Pstable::checkTableModel() { // int size=procview->linear_procs.size(); // if(size!=numRows()) { // printf("Warnning: this is the bug.. wrong! %d //%d\n",size,numRows()); } if (procview->current_gen != kgen) { // printf("Warnning: maybe this is the bug.. wrong! //%d //%d\n",kgen,procview->current_gen); // setAutoUpdate(false); // ********** important for // GUI-thread // HeadedTable::setTreeMode(procview->treeview); procview->rebuild(); // for Table setNumRows(procview->linear_procs.size()); // 1. // qDebug("Pstable setTreeMode =%d , procview.treeview //=%d\n",treemode,procview->treeview); setNumCols(procview->cats.size()); // 2. resetWidths() kgen = procview->current_gen; // setAutoUpdate(true); } } // paintEvent(); void Pstable::refresh() { // qDebug("Pstable:refresh()"); // procview->refresh(); -> move to Qps::refresh() // qDebug("catsize=%d\n",procview->cats.size()); procview->rebuild(); // for Table setNumRows(procview->linear_procs.size()); // 1. setNumCols(procview->cats.size()); // 2. resetWidths() UNINITIAL kgen = procview->current_gen; // checkTableModel(); repaint_changed(); /* if(true) { int count=0,trow=0; for(int row = 0; row < nrows; row++) if(isSelected(row)) { count++; trow=row; } if (count == 1) centerVertically(trow); } */ STATUSBAR_SETCOUNT(procview->num_process); }