// very dirty and complex code ( fasthyun@magicn.com) // Disaster !! // htable.cpp // This program is free software. See the file COPYING for details. // Author: Mattias EngdegÄrd, 1997-1999 // TODO: // * autoscroll speed proportional to distance from edge // * interface to add/remove rows (for disclosure triangles) // * interface to display pixmaps in cells (for disclosure triangles etc) // * include sorting functionality here for more generality #include "htable.h" #include #include #include #include #define DEBUG qDebug //#define DEBUG VPointer *vp = NULL; // Temporary VPointer::VPointer(QWidget *parent) : QWidget(parent) { pix = new QPixmap(":/icon/vpointer.png"); pix_vcross = new QPixmap(":/icon/vcross.png"); int w = pix->width(); bool flag_movable = true; setGeometry(0, 0, w, w); } void VPointer::paintEvent(QPaintEvent *event) { QPainter p(this); p.setClipping(false); // not work if (flag_movable) p.drawPixmap(0, 0, *pix); else p.drawPixmap(0, 0, *pix_vcross); } FloatingHead::FloatingHead(QWidget *parent) : QWidget(parent) {} void FloatingHead::setTitle(QString str, int w, int h) { title = str; resize(w, h); } void FloatingHead::paintEvent(QPaintEvent *event) { QPainter p(this); QStyleOptionHeader opt; p.setOpacity(0.7); opt.rect = rect(); opt.text = title; opt.state = QStyle::State_Enabled; // if(htable->sortedCol()==col) opt.state= opt.state | // QStyle::State_Sunken; // CE_Header, CE_HeaderSection, CE_HeaderLabel style()->drawControl(QStyle::CE_Header, &opt, &p, this); return; } // TableHead: the horizontally scrollable table head TableHead::TableHead(HeadedTable *parent) : QtTableView(parent), htable(parent), dragging(false) { setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); // setSizePolicy(QSizePolicy // (QSizePolicy::Minimum,QSizePolicy::Expanding)); // setTableFlags(Tbl_smoothHScrolling | Tbl_scrollLastHCell); setTableFlags(Tbl_scrollLastHCell); // ? setNumRows(1); setMouseTracking(true); // for tooltip floatHead = new FloatingHead(parent); // tiny memory leak! don't care. floatHead->hide(); // setMinimumHeight(20);//cellHeight()); //ZERO!! fault } // Description : draw a field name of table when DRAG !! // called by paintHeading() // called by QtTableView::repaint() void TableHead::paintCell(QPainter *p, int row, int col, bool use_cache) { static int count = 0; /// printf(" paintcell %d,%d\n",row,col); int w = htable->max_widths[col]; // if( isCellChanged (row,col,true)==false) { // printf(" paintcell %d,%d\n",row,col); // if(use_cache==true) // check cached value { // return; } } // if( col ==11 ) printf("head: %d (%d) \n",col,count++); // w = cellUpdateR.width(); { QStyleOptionHeader opt; QRect rectR(0, 0, w, height()); opt.rect = rectR; opt.text = htable->title(col); opt.state = QStyle::State_Enabled; if (htable->sortedCol() == col) opt.state = opt.state | QStyle::State_Sunken; // CE_Header, CE_HeaderSection, CE_HeaderLabel style()->drawControl(QStyle::CE_Header, &opt, p, this); } } // works void TableHead::eraseRight(QPainter *p, QRect &r) { QStyleOptionHeader opt; // printf("widt=%d \n",r.width()); opt.rect = r; opt.text = ""; style()->drawControl(QStyle::CE_Header, &opt, p, this); } // virtual ! int TableHead::cellWidth(int col) { return htable->max_widths[col]; } // void TableHead::scrollSideways(int val) { setXOffset(val); } void TableHead::mousePressEvent(QMouseEvent *e) { int col = findCol(e->x()); // printf("col=%d\n",col); if (col == -1) return; click_col = col; if (e->button() == Qt::RightButton) // && htable->options & HTBL_HEADING_CONTEXT_MENU) { emit rightClicked(e->globalPos(), col); return; } if (e->button() == Qt::LeftButton) { press = e->pos(); } } void TableHead::dragEnterEvent(QDragEnterEvent *event) { printf("dragEnterEvent()\n"); } void TableHead::dragLeaveEvent(QDragLeaveEvent *event) { printf("dragLeaveEvent()\n"); } void TableHead::mouseMoveEvent(QMouseEvent *e) { // printf("mouseMoveEvent()\n"); int col = findCol(e->x()); if (col < 0) { emit htable->outOfHCell(); return; } // if( !dragging) return; emit htable->flyOnHCell(col); int thold = abs(press.x() - e->pos().x()); if (e->buttons() == Qt::LeftButton // Button state and htable->options & HTBL_REORDER_COLS) { { if (!dragging and thold > 5) { dragging = true; drag_offset = press.x() - htable->colOffset(click_col) + xOffset(); floatHead->setTitle(htable->title(click_col), cellWidth(click_col), height()); floatHead->show(); // vp->show(); } if (dragging) { // htable->body->drawGhostCol(drag_pos - // drag_offset, w); floatHead->move(e->x() - drag_offset, 0); int vcol = findColNoMinus(e->x() - drag_offset); int vcol_offx = htable->colOffset(vcol); static int old_pos = -1; // printf("vcol=%d\n",vcol); // virtual Pointer move! if (old_pos != vcol_offx) { QWidget *p = parentWidget(); // htable // vp->setMovable(htable->columnMovable(htable->columnMovable(vcol) // and htable->columnMovable(click_col) // )); // vp->move(vcol_offx - // p->geometry().x() //,p->geometry().y() - // 13); // vp->move(e->x() ,10); old_pos = vcol_offx; } drag_pos = e->x(); // save old pos return; } } } if (col != -1) // ToolTip { // for(int i=0;i<1024*1024;i++) htable->tipText(col); //// memory leak // test QString s = htable->tipText(col); if (!s.isEmpty()) QToolTip::showText(e->globalPos(), s); } } void TableHead::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) // Returns the button that caused the // event. { int col = findCol(e->x()); if (col < 0) col = (e->x() < 0) ? 0 : htable->ncols - 1; // good! if (!dragging and col == click_col) { // htable->emit_click_signal(col); // just click no drag emit htable->titleClicked(col); } if (dragging) { int vcol = findColNoMinus(e->x() - drag_offset); if (click_col >= 0) { htable->moveCol(click_col, vcol); // call // Pstable::moveCol(int // col, int place) // should emit !! // emit colMoved(click_col, vcol); } /// printf(" vcol2=%d \n",vcol); } dragging = false; floatHead->hide(); // vp->hide(); } } #include // TableBody: the table body, scrollable in all ways TableBody::TableBody(HeadedTable *parent) : QtTableView(parent), htable(parent) { // setTableFlags(Tbl_autoScrollBars | Tbl_smoothScrolling); setTableFlags(Tbl_snapToVGrid); // works setTableFlags(Tbl_hScrollBar | Tbl_vScrollBar); first_drag_row = prev_drag_row = -1; autoscrolling = false; gadget_click = false; setMouseTracking(true); QStyle *s = QStyleFactory::create("windows"); if (s) setStyle(s); } // virtual from QtTableView void TableBody::scrollTrigger(int rx, int ry) { if (ry == 0) return; int n = ry / cellHeight(); /// printf("ry=%d n=%d\n",ry,n); if (ry > 0) tablecache.cutDown(n); // error? else tablecache.cutUp(-n); // printf("ry=%d cellheight=%d n=%d\n",ry,cellHeight(),n); } // new, possible COMMON? bool TableBody::isCellChanged(int row, int col) { QString str; int xpos; int fold, dep; bool selected; bool sorted; int lc; int width; { str = htable->text(row, col); xpos = htable->colXPos(col); selected = htable->isSelected(row); sorted = (htable->sortedCol() == col); width = htable->max_widths[col]; } // int left = leftCell(), top = topCell(); CellAttribute *attr = tablecache.value(row - topCell(), col - leftCell()); if (attr == NULL) // never NULL { return true; } else { bool result = false; if (attr->text == str and attr->selected == selected and attr->sorted == sorted and attr->xpos == xpos and attr->w == width // and attr->size==tmp_size and (attr->size.height() >= tmp_size.height()) // and (attr->size.width()>=tmp_size.width()) ) { result = false; } else { // attr->text=str; // attr->selected=selected; // attr->sorted=sorted; // attr->xpos=xpos; // attr->size=tmp_size; // attr->w=width; // if (row==29 and col==0) // printf("(%d %d) xpos=%d %d sorted=%d %d sel=%d //%d str=%s //%s\n",attr->size.height(),tmp_size.height(), // attr->xpos,xpos,attr->sorted,sorted,attr->selected,selected // ,qPrintable(attr->text),qPrintable(str)); // printf("true (%d //%d)\n",row-topCell(),col-leftCell()); return true; } if (col == 0) { dep = htable->rowDepth(row); // folding_level fold = htable->folded(row); lc = htable->lastChild(row); if (attr->depth == dep /* Uninitial*/ and attr->folded == fold and attr->lastchild == lc) { // false } else { // attr->depth=dep; // attr->folded=fold; result = true; // printf("true (%d //%d)\n",row-topCell(),col-leftCell()); } } return result; } } bool TableHead::isCellChanged(int row, int col) { int xpos; int ypos; int w; int fold, dep; QString str; bool sorted = (htable->sortedCol() == col); w = htable->max_widths[col]; xpos = htable->colXPos(col); { str = htable->title(col); } // int left = leftCell(); // int top = topCell(); CellAttribute *attr = tablecache.value(row - topCell(), col - leftCell()); if (attr == NULL) // Uninitialed? { return true; } else { bool result = false; if (attr->text == str and attr->sorted == sorted and attr->size == tmp_size and attr->xpos == xpos // and attr->w==w ) { return false; } else { attr->text = str; attr->sorted = sorted; attr->xpos = xpos; // attr->w=w; attr->size = tmp_size; // if(head) printf("head // true"); return true; } // printf("return %s x=%d\n",str.toAscii().data(),xpos); } } #include // DRAFT CODE !! BOTTLENECK !!! // Description : draw a cell of table // 1. draw the background of a cell // 2. draw the text of a cell // // called by // 1.QtTableView::paintEvent() void TableBody::paintCell(QPainter *p, int row, int col, bool use_cache) { // *** sequence important !!! // if(isCellChanged(row,col)==false) { // if(use_cache==true) return; //} CellAttribute *attr = tablecache.value(row - topCell(), col - leftCell()); // save cache // isCellChanged(row,col); bool sort; int h = cellHeight(); int w = htable->max_widths[col]; attr->w = w; // QColor baseColor = palette().brush(QPalette::Base).color(); sort = (col == htable->sorted_col); attr->sorted = sort; // gridline QColor lineColor, textColor; QColor altColor = palette().brush(QPalette::AlternateBase).color(); lineColor.setRgb((baseColor.red() * 0.5 + altColor.red() * 0.5), (baseColor.green() * 0.4 + altColor.green() * 0.6), (baseColor.blue() * 0.4 + altColor.blue() * 0.6)); // QStyleOption opt; // opt.rect=QRect(0,0,w,h-1); // opt.state = QStyle::State_Active; //? // QStyle::SH_ItemView_PaintAlternatingRowColorsForEmptyArea // const int gridHint = // style()->styleHint(QStyle::SH_Table_GridLineColor, // &opt, this); p->setPen(lineColor); p->drawLine(0, h - 1, w, h - 1); // background if (htable->isSelected(row)) { p->fillRect(0, 0, w, h - 1, palette().brush(QPalette::Highlight)); p->setPen(palette().brush(QPalette::HighlightedText).color()); // text attr->selected = true; } else { attr->selected = false; if (sort) { p->fillRect(0, 0, w, h - 1, lineColor.dark(101)); } else { p->fillRect(0, 0, w, h - 1, baseColor); } // style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, // this); p->setPen(palette().brush(QPalette::Text).color()); // text } // tree gadget , treestep=height int gap = h / 4; int testFlag = 0; if (col == 0 and htable->treemode == true) { QStyleOption opt; int d = htable->rowDepth(row); attr->depth = d; //** int treestep = htable->treestep; if (true /*lines*/) { /// int dx = folding ? gadget_space : 6; for (int level = d, prow = row; level >= 0 and prow >= 0; level--, prow = htable->parentRow(prow)) { if (level == d) continue; int x = gap + level * treestep; QRect branchR(x, 0, treestep, h); opt.rect = branchR; if (htable->lastChild(prow) == false) { if (testFlag) { p->drawLine(x + treestep / 2, 0, x + treestep / 2, h); } else { opt.state = QStyle::State_Sibling; // | vertical // line style()->drawPrimitive(QStyle::PE_IndicatorBranch, &opt, p, this); } } } QRect branchR(gap + d * treestep, 0, treestep, h); opt.rect = branchR; if (testFlag) { int x = gap + d * treestep + treestep / 2; p->drawLine(x, h / 2, x + treestep / 2, h / 2); if (!htable->lastChild(row)) { p->drawLine(x, 0, x, h); } else { p->drawLine(x, 0, x, h / 2); } } else { opt.state = QStyle::State_Item; //? if (!htable->lastChild(row)) opt.state = opt.state | QStyle::State_Sibling; // | } attr->lastchild = htable->lastChild(row); } if (true /*folding*/) { HeadedTable::NodeState fs = htable->folded(row); attr->folded = fs; //** if (fs != HeadedTable::Leaf) { opt.state = opt.state | QStyle::State_Children; if (fs != HeadedTable::Closed) opt.state = opt.state | QStyle::State_Open; } p->save(); // temp , save pencolor style()->drawPrimitive(QStyle::PE_IndicatorBranch, &opt, p, this); p->restore(); } gap = htable->gadget_space + d * treestep + 1; } // virtual int Pstable::alignment(int col) if (htable->alignment_col[col] == Qt::AlignRight) // using cache { w -= gap; gap = 0; } // Qt::IncludeTrailingSpaces // p->drawText(gap, 0, w , h, Qt::TextIncludeTrailingSpace | // Qt::IncludeTrailingSpaces | Qt::AlignVCenter | // htable->alignment_col[col],htable->text(row,col)); // p->drawText(gap, 0, w , h, Qt::TextIncludeTrailingSpace | // Qt::AlignVCenter // | htable->alignment_col[col],htable->text(row,col)); p->drawText(gap, 0, w, h, Qt::AlignVCenter | htable->alignment_col[col], htable->text(row, col)); htable->overpaintCell(p, row, col, gap); // cache write! // attr->xpos=tmp_x ; attr->text = htable->text(row, col); attr->xpos = htable->colXPos(col); attr->size = tmp_size; } // DEL , Home key void TableBody::jumpTop() { setYOffset(0); } // DEL, End Key void TableBody::jumpBottom() { setYOffset(maxYOffset()); } /// !!!! void TableBody::centerVertically(int row) { int topcell = row - viewHeight() / (cellHeight() * 2); setTopCell(qMax(topcell, 0)); update(); } //?? void TableBody::showRange(int from, int to) { int h = viewHeight() / cellHeight(); if (to >= topCell() + h) setTopCell(qMax(0, qMin(from, to - h + 1))); } // virtual // called by // 1. int TableBody::cellWidth(int col) { return htable->max_widths[col]; } // **** fix !! void TableBody::updateRow(int row) { // ?? // for(int col = 0; col < htable->ncols; col++) // updateCell(row, col,false); updateCell(row, col); } void TableBody::mousePressEvent(QMouseEvent *e) { if (numRows() == 0) return; // *** prevent out of range // printf("mousePressEvent() 1\n"); static int last_row = -1; int row = findRow(e->y()); if (row == -1) { // printf("mousePressEvent\n"); htable->clearAllSelections(); if (e->y() >= 0) row = numRows(); // if SHIFT+click outside ~ first_drag_row = prev_drag_row = row; return; } if (!(htable->options & HTBL_ROW_SELECTION)) return; if (e->button() == Qt::LeftButton) { // folding if (htable->treemode && htable->folding && e->x() < htable->gadget_space + htable->treestep * htable->rowDepth(row) && htable->folded(row) != HeadedTable::Leaf) { emit htable->foldSubTree(row); gadget_click = true; last_row = row; // clearCache(); // dont use cache return; } if (e->modifiers() & Qt::ShiftModifier) { if (row < last_row) for (int i = row; i < last_row; i++) htable->setSelected(i, true); // virtual else for (int i = last_row; i <= row; i++) htable->setSelected(i, true); // virtual } else if (e->modifiers() & Qt::ControlModifier) { htable->setSelected(row, !htable->isSelected(row)); } else htable->selectOnlyOne(row); first_drag_row = prev_drag_row = row; emit htable->selectionChanged(); } else if (e->button() == Qt::RightButton) { if (!htable->isSelected(row)) htable->selectOnlyOne(row); emit htable->selectionChanged(); // better? emit htable->rightClicked(e->globalPos()); } last_row = row; // htable->repaint_changed(); repaintChanged(); // repaint // view->update(); // fast but use more CPU } void TableBody::mouseReleaseEvent(QMouseEvent *e) { gadget_click = false; if (e->button() == Qt::LeftButton) { if (autoscrolling) { ////killTimers(); // no more autoscrolling first_drag_row = prev_drag_row = -1; autoscrolling = false; } } else if (e->button() == Qt::RightButton) { QPoint p(6, 3); p += e->globalPos(); emit htable->rightClicked(p); } } void TableBody::mouseDoubleClickEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { int row = findRow(e->y()); if (row != -1) { if (htable->options & HTBL_ROW_SELECTION && !htable->isSelected(row)) htable->selectOnlyOne(row); // htable->selectionNotify(); emit htable->selectionChanged(); // htable->emit_double_click_signal(row); emit htable->doubleClicked(row); } } } // Bottle Neck ? no void TableBody::leaveEvent(QEvent *) { emit htable->outOfCell(); } void TableBody::mouseMoveEvent(QMouseEvent *e) { if (numRows() == 0) return; // *** prevent out of range // DRAFT CODE ! // Signal : find row, col(field name) emit flyOnEvent Signal int row = findRow(e->y()); int col = findCol(e->x()); if (row < 0 or col < 0) { emit htable->outOfCell(); // if... return; } emit htable->flyOnCell(row, col); if (e->buttons() == Qt::NoButton) return; if (e->buttons() == Qt::RightButton) return; if (e->buttons() & Qt::ControlModifier || gadget_click) return; if (row != prev_drag_row) { if (row == -1) { if (!autoscrolling) { // dragging outside table, cause scrolling scrolldir = (e->y() < 0) ? UP : DOWN; // killTimers(); // startTimer(scroll_delay); autoscrolling = true; } } else { ////killTimers(); autoscrolling = false; dragSelectTo(row); } } // repaintRow(row); // view->update(); repaintChanged(); } void TableBody::timerEvent(QTimerEvent *) { // timer not proved ! return; // printf("timer\n"); if (!autoscrolling) return; ////killTimers(); if (scrolldir == UP) { int top = topCell(); setTopCell((top > 1) ? top - 1 : 0); dragSelectTo(topCell()); } else { setTopCell(topCell() + 1); int bottom = lastRowVisible(); dragSelectTo((bottom < numRows()) ? bottom : numRows() - 1); } startTimer(scroll_delay); } // change drag selection point from previous drag position to row void TableBody::dragSelectTo(int row) { int dir = (row > prev_drag_row) ? 1 : -1; if ((prev_drag_row - first_drag_row) * dir >= 0) { // moving away from start point for (int i = prev_drag_row + dir; i - dir != row; i += dir) htable->setSelected(i, true); } else { // moving towards start point for (int i = prev_drag_row; i != row; i += dir) htable->setSelected(i, false); } prev_drag_row = row; // htable->selectionNotify(); emit htable->selectionChanged(); } // heuristic for determining a good XOR color: This is in general a hard // problem but since we know (most of) the background and the foreground, // we can try. Note that this function might not return an allocated QColor, // so it is only useful for XOR drawing. QColor TableBody::getXorColor() { QColor fg = palette().brush(QPalette::Base).color(); return fg; /// QColor(0, fg.pixel() ^ backgroundColor().pixel()); } void TableBody::drawGhostCol(int x, int w) { static QColor xorcol = getXorColor(); QPainter p(this); p.setPen(xorcol); // p.setRasterOp(XorROP); /// p.drawLine(x, 0, x, height()); ////p.drawLine(x + w, 0, x + w, height()); } // HeadedTable: the actually useable class HeadedTable::HeadedTable(QWidget *parent, int opts) : QWidget(parent) { // meaningless? options = HTBL_ROW_CONTEXT_MENU | HTBL_ROW_SELECTION | HTBL_ROW_DOUBLE_CLICK | HTBL_HEADING_TOOLTIPS | HTBL_HEADING_CONTEXT_MENU | HTBL_HEADING_CLICK | HTBL_REORDER_COLS; head = new TableHead(this); body = new TableBody(this); head->setObjectName("head"); body->setObjectName("body"); sorted_col = -1; treemode = false; treestep = 0; lines = true; folding = true; gadget_space = 0; nrows = ncols = 0; // hmm... // printf("style name=%s \n",qPrintable(style()->objectName())); // QApplication::setStyle(new QWindowsStyle); head->setFrameShape(QFrame::NoFrame); if (style()->objectName().contains("oxygen")) ; else { body->setFrameShape(QFrame::NoFrame); } QVBoxLayout *vlayout = new QVBoxLayout; vlayout->setSpacing(0); // distance between Widget and Widget #if QT_VERSION < 0x040300 vlayout->setMargin(0); // qt-4.2 #else vlayout->setContentsMargins(0, 0, 0, 0); // qt-4.3 #endif // vlayout->setSizeConstraint ( SizeConstraint ) vlayout->addWidget(head); vlayout->addWidget(body); setLayout(vlayout); // connect keyboard shortcuts QShortcut *c; c = new QShortcut(Qt::CTRL + Qt::Key_A, this, SLOT(selectAll())); // synchronize horizontal scrolling of head and body connect(body->horizontalScrollBar(), SIGNAL(valueChanged(int)), head, SLOT(scrollSideways(int))); fontChange(font()); // *** need for init // vp=new VPointer((QWidget *)QObject::parent()); // vp->hide(); //memory leak!! } HeadedTable::~HeadedTable() {} // ok : move to Qttableview void HeadedTable::fontChange(const QFont &oldFont) { // DEBUG("fontChange()\n"); int fontHeight = fontMetrics().height() + 1; // printf("cell height =%d \n", cellH); if (fontHeight % 2 != 0) fontHeight++; // for pretty fold-lines head->setCellHeight(fontHeight + 5); head->setMaximumHeight(head->cellHeight()); body->setCellHeight(fontHeight); treestep = fontHeight; gadget_space = folding ? fontHeight + (fontHeight / 2) : 0; // QWidget::fontChange ( oldFont ); } // DRAFT virtual ! void HeadedTable::moveCol(int col, int place) { // go to void Procview::moveColumn(int col, int place) } // distance (in table coords) from left table edge of physical column int HeadedTable::colOffset(int col) { int x = 0; for (int c = 0; c < col; c++) x += max_widths[c]; // x += body->cellWidth(c); return x; } // OPTIZ inline int HeadedTable::colXPos(int col) { int x = 0; // + coloffset for (int c = 0; c < col; c++) x += max_widths[c]; return x; } // repaint columns from col0 to col1. If col1 is -1, repaint all // the way to the right edge of the table. // called by // 1.void Qps::update_table(int col) void HeadedTable::repaintColumns(int col0, int col1) { QRect bvr = body->viewRect(); QRect hvr = head->viewRect(); int x0 = colOffset(col0) - body->xOffset(); if (x0 > hvr.width()) return; if (x0 < 0) x0 = 0; bvr.setLeft(x0); hvr.setLeft(x0); if (col1 >= 0) { int x1 = colOffset(col1) + max_widths[col1] - body->xOffset(); if (x1 < hvr.width()) { hvr.setRight(x1); bvr.setRight(x1); } } head->repaint(hvr); body->repaint(bvr); } // DEL -> virtual // called by Pstable::setTreeMode(bool) void HeadedTable::setTreeMode(bool tm) { treemode = tm; head->clearCache(); body->clearCache(); } // update table Head !! void HeadedTable::setSortedCol(int col) { { int old_sorted = sorted_col; sorted_col = col; // printf("old_sorted=%d\n",old_sorted); // printf("sorted_col=%d\n",sorted_col); if (old_sorted != -1 && old_sorted < ncols) // ncols bug updateHeading(old_sorted); if (col != -1 && col < ncols) updateHeading(col); } } // should be virtual. why? void HeadedTable::clearAllSelections() { for (int row = 0; row < nrows; row++) setSelected(row, false); body->view->update(); // update(); // not work why? } // BottleNeck ? void HeadedTable::selectOnlyOne(int row) { // this apply to the current list only! for (int r = 0; r < nrows; r++) setSelected(r, r == row); } void HeadedTable::selectAll() { for (int r = 0; r < nrows; r++) setSelected(r, true); emit selectionChanged(); // notwork? } // default implementation returns a null string (no tip d) QString HeadedTable::tipText(int) { return ""; } char *HeadedTable::total_selectedRow(int col) { return 0; } void HeadedTable::setNumRows(int rows) { nrows = rows; head->setNumRows(1); body->setNumRows(rows); } void TableCache::setRow(int row) { if (row < 0) return; int i, size = rows.size(); if (row >= size) { // rows.append(new TableRow); } if (row < nrow) { // printf("row=%d,nrow=%d \n",row,nrow); if (size < nrow) nrow = size; for (i = row; i < nrow; i++) { for (int j = 0; j < 48; j++) rows[i]->cells[j].text = ""; } } nrow = row; } void TableCache::setCol(int col) { if (col < 0) return; if (col < ncol) { // printf("clear cache\n"); int i, size = rows.size(); for (i = 0; i < size; i++) for (int j = col; j < ncol; j++) rows[i]->cells[j].text = ""; } ncol = col; } // TEST void TableHead::checkProfile() { QRect viewR = viewRect(); // if(viewR.y()!=0) printf(" qps: ooooohss....\n"); int maxViewCol = findCol(viewR.width()); if (maxViewCol < 0) maxViewCol = numCols(); tablecache.setCol(maxViewCol); tablecache.setRow(1); } // TESt void TableBody::checkProfile() { htable->checkTableModel(); // important QRect viewR = viewRect(); if (viewR.y() != 0) printf(" qps: ooooophss....\n"); int maxViewRow = findRow(viewR.height()); if (maxViewRow < 0) maxViewRow = numRows(); int maxViewCol = findCol(viewR.width()); if (maxViewCol < 0) maxViewCol = numCols(); tablecache.setCol(maxViewCol); tablecache.setRow(maxViewRow); } void HeadedTable::setNumCols(int cols) { // printf("cols=%d\n",cols); ncols = cols; // resetWidths(); for (int i = 0; i < cols; i++) { alignment_col[i] = alignment(i); updateColWidth(i); } // printf("ncols=%d\n",ncols); head->setNumCols(ncols); body->setNumCols(ncols); } /* //virtual int HeadedTable::colWidth(int col) { int r = numRows(); for(int i=0;i w) w = sw; } if (treecol) { w += gadget_space; } } // don't forget the width of the heading hw = fontMetrics().width(title(col)) + 12; // return 0; if (hw > w) w = hw; // sw=fontmetric.width("0") * colWidth(col); // if(sw>w) w=sw; max_widths[col] = w; return 0; } void HeadedTable::resetWidths() { for (int i = 0; i < numCols() + 1; i++) max_widths[i] = 0; } // called by ? void HeadedTable::repaintAll() // -> repaint() { int count = 0, trow = 0; for (int row = 0; row < nrows; row++) if (isSelected(row)) { count++; trow = row; } // body->view->update(); // update(); // not work why? // printf("Qps debug: repaintAll()\n"); // head->clearCache(); // body->clearCache(); // update(); body->view->update(); head->view->update(); if (count == 1) centerVertically(trow); } // PROBLEM : update() + repaint() call = draw twice !!! // called by pstable::refresh() // DEL if (render_area smaller than full_arear ) then force draw void HeadedTable::repaint_changed() { // printf("repaint_changed()\n"); // body->setUpdatesEnabled(true); head->repaintChanged(); body->repaintChanged(); } void HeadedTable::hideEvent(QHideEvent *event) {} void HeadedTable::paintEvent(QPaintEvent *e) { static int c = 0; // printf("HeadedTable paintEvent %d\n",c++); //works ? // QWidget::paintEvent(e); // body->clearCache(); // head->update(); } void HeadedTable::showEvent(QShowEvent *) { // printf("HeadedTable showEvent\n"); // works // before paintEvent call head->clearCache(); body->clearCache(); } void HeadedTable::resizeEvent(QResizeEvent *e) { // DEBUG("resizeEvent() HeadedTable %d\n",head->cellHeight()); //// head->repaintRow(0); QWidget::resizeEvent(e); head->clearCache(); body->clearCache(); }