Warning, file /sdk/cervisia/qttableview.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /********************************************************************** 0002 ** $Id$ 0003 ** 0004 ** Implementation of QtTableView class 0005 ** 0006 ** Created : 941115 0007 ** 0008 ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. 0009 ** 0010 ** This file contains a class moved out of the Qt GUI Toolkit API. It 0011 ** may be used, distributed and modified without limitation. 0012 ** 0013 **********************************************************************/ 0014 0015 #include "qttableview.h" 0016 #include <climits> 0017 #include <qapplication.h> 0018 #include <qdrawutil.h> 0019 #include <qevent.h> 0020 #include <qpainter.h> 0021 #include <qscrollbar.h> 0022 0023 enum ScrollBarDirtyFlags { 0024 verGeometry = 0x01, 0025 verSteps = 0x02, 0026 verRange = 0x04, 0027 verValue = 0x08, 0028 horGeometry = 0x10, 0029 horSteps = 0x20, 0030 horRange = 0x40, 0031 horValue = 0x80, 0032 verMask = 0x0F, 0033 horMask = 0xF0 0034 }; 0035 0036 #define HSBEXT horizontalScrollBar()->sizeHint().height() 0037 #define VSBEXT verticalScrollBar()->sizeHint().width() 0038 0039 class QCornerSquare : public QWidget // internal class 0040 { 0041 public: 0042 QCornerSquare(QWidget *); 0043 }; 0044 0045 QCornerSquare::QCornerSquare(QWidget *parent) 0046 : QWidget(parent) 0047 { 0048 setAutoFillBackground(true); 0049 } 0050 0051 // NOT REVISED 0052 /*! 0053 \class QtTableView qttableview.h 0054 \brief The QtTableView class provides an abstract base for tables. 0055 0056 \obsolete 0057 0058 A table view consists of a number of abstract cells organized in rows 0059 and columns, and a visible part called a view. The cells are identified 0060 with a row index and a column index. The top-left cell is in row 0, 0061 column 0. 0062 0063 The behavior of the widget can be finely tuned using 0064 setTableFlags(); a typical subclass will consist of little more than a 0065 call to setTableFlags(), some table content manipulation and an 0066 implementation of paintCell(). Subclasses that need cells with 0067 variable width or height must reimplement cellHeight() and/or 0068 cellWidth(). Use updateTableSize() to tell QtTableView when the 0069 width or height has changed. 0070 0071 When you read this documentation, it is important to understand the 0072 distinctions among the four pixel coordinate systems involved. 0073 0074 \list 1 0075 \i The \e cell coordinates. (0,0) is the top-left corner of a cell. 0076 Cell coordinates are used by functions such as paintCell(). 0077 0078 \i The \e table coordinates. (0,0) is the top-left corner of the cell at 0079 row 0 and column 0. These coordinates are absolute; that is, they are 0080 independent of what part of the table is visible at the moment. They are 0081 used by functions such as setXOffset() or maxYOffset(). 0082 0083 \i The \e widget coordinates. (0,0) is the top-left corner of the widget, 0084 \e including the frame. They are used by functions such as repaint(). 0085 0086 \i The \e view coordinates. (0,0) is the top-left corner of the view, \e 0087 excluding the frame. This is the least-used coordinate system; it is used by 0088 functions such as viewWidth(). \endlist 0089 0090 It is rather unfortunate that we have to use four different 0091 coordinate systems, but there was no alternative to provide a flexible and 0092 powerful base class. 0093 0094 Note: The row,column indices are always given in that order, 0095 i.e., first the vertical (row), then the horizontal (column). This is 0096 the opposite order of all pixel operations, which take first the 0097 horizontal (x) and then the vertical (y). 0098 0099 <img src=qtablevw-m.png> <img src=qtablevw-w.png> 0100 0101 \warning the functions setNumRows(), setNumCols(), setCellHeight(), 0102 setCellWidth(), setTableFlags() and clearTableFlags() may cause 0103 virtual functions such as cellWidth() and cellHeight() to be called, 0104 even if autoUpdate() is 'false'. This may cause errors if relevant 0105 state variables are not initialized. 0106 0107 \warning Experience has shown that use of this widget tends to cause 0108 more bugs than expected and our analysis indicates that the widget's 0109 very flexibility is the problem. If QScrollView or QListBox can 0110 easily be made to do the job you need, we recommend subclassing 0111 those widgets rather than QtTableView. In addition, QScrollView makes 0112 it easy to have child widgets inside tables, which QtTableView 0113 doesn't support at all. 0114 0115 \sa QScrollView 0116 \link guibooks.html#fowler GUI Design Handbook: Table\endlink 0117 */ 0118 0119 /*! 0120 Constructs a table view. The \a parent, \a name and \f arguments 0121 are passed to the QFrame constructor. 0122 0123 The \link setTableFlags() table flags\endlink are all cleared (set to 0). 0124 Set \c Tbl_autoVScrollBar or \c Tbl_autoHScrollBar to get automatic scroll 0125 bars and \c Tbl_clipCellPainting to get safe clipping. 0126 0127 The \link setCellHeight() cell height\endlink and \link setCellWidth() 0128 cell width\endlink are set to 0. 0129 0130 Frame line shapes (QFrame::HLink and QFrame::VLine) are disallowed; 0131 see QFrame::setFrameStyle(). 0132 0133 Note that the \a f argument is \e not \link setTableFlags() table 0134 flags \endlink but rather \link QWidget::QWidget() widget 0135 flags. \endlink 0136 0137 */ 0138 0139 QtTableView::QtTableView(QWidget *parent, const char *name) 0140 : QFrame(parent) 0141 { 0142 nRows = nCols = 0; // zero rows/cols 0143 xCellOffs = yCellOffs = 0; // zero offset 0144 xCellDelta = yCellDelta = 0; // zero cell offset 0145 xOffs = yOffs = 0; // zero total pixel offset 0146 cellH = cellW = 0; // user defined cell size 0147 tFlags = 0; 0148 vScrollBar = hScrollBar = 0; // no scroll bars 0149 cornerSquare = 0; 0150 sbDirty = 0; 0151 eraseInPaint = false; 0152 verSliding = false; 0153 verSnappingOff = false; 0154 horSliding = false; 0155 horSnappingOff = false; 0156 coveringCornerSquare = false; 0157 inSbUpdate = false; 0158 0159 setAttribute(Qt::WA_OpaquePaintEvent, true); 0160 setObjectName(name); 0161 } 0162 0163 /*! 0164 Destroys the table view. 0165 */ 0166 0167 QtTableView::~QtTableView() 0168 { 0169 delete vScrollBar; 0170 delete hScrollBar; 0171 delete cornerSquare; 0172 } 0173 0174 /*! 0175 \overload void QtTableView::repaint( bool erase ) 0176 Repaints the entire view. 0177 */ 0178 0179 /*! 0180 Repaints the table view directly by calling paintEvent() directly 0181 unless updates are disabled. 0182 0183 Erases the view area \a (x,y,w,h) if \a erase is 'true'. Parameters \a 0184 (x,y) are in \e widget coordinates. 0185 0186 If \a w is negative, it is replaced with <code>width() - x</code>. 0187 If \a h is negative, it is replaced with <code>height() - y</code>. 0188 0189 Doing a repaint() usually is faster than doing an update(), but 0190 calling update() many times in a row will generate a single paint 0191 event. 0192 0193 At present, QtTableView is the only widget that reimplements \link 0194 QWidget::repaint() repaint()\endlink. It does this because by 0195 clearing and then repainting one cell at at time, it can make the 0196 screen flicker less than it would otherwise. */ 0197 0198 void QtTableView::repaint(int x, int y, int w, int h, bool erase) 0199 { 0200 if (!isVisible()) 0201 return; 0202 if (w < 0) 0203 w = width() - x; 0204 if (h < 0) 0205 h = height() - y; 0206 QRect r(x, y, w, h); 0207 if (r.isEmpty()) 0208 return; // nothing to do 0209 if (erase && testAttribute(Qt::WA_OpaquePaintEvent)) 0210 eraseInPaint = true; // erase when painting 0211 QWidget::repaint(r); 0212 eraseInPaint = false; 0213 } 0214 0215 /*! 0216 \overload void QtTableView::repaint( const QRect &r, bool erase ) 0217 Repaints rectangle \a r. If \a erase is 'true' draws the background 0218 using the palette's background. 0219 */ 0220 0221 /*! 0222 \fn int QtTableView::numRows() const 0223 Returns the number of rows in the table. 0224 \sa numCols(), setNumRows() 0225 */ 0226 0227 /*! 0228 Sets the number of rows of the table to \a rows (must be non-negative). 0229 Does not change topCell(). 0230 0231 The table repaints itself automatically if autoUpdate() is set. 0232 0233 \sa numCols(), setNumCols(), numRows() 0234 */ 0235 0236 void QtTableView::setNumRows(int rows) 0237 { 0238 if (rows < 0) { 0239 #if defined(QT_CHECK_RANGE) 0240 qWarning("QtTableView::setNumRows: (%s) Negative argument %d.", name("unnamed"), rows); 0241 #endif 0242 return; 0243 } 0244 if (nRows == rows) 0245 return; 0246 0247 if (autoUpdate() && isVisible()) { 0248 int oldLastVisible = lastRowVisible(); 0249 int oldTopCell = topCell(); 0250 nRows = rows; 0251 if (autoUpdate() && isVisible() && (oldLastVisible != lastRowVisible() || oldTopCell != topCell())) 0252 repaint(oldTopCell != topCell()); 0253 } else { 0254 // Be more careful - if destructing, bad things might happen. 0255 nRows = rows; 0256 } 0257 updateScrollBars(verRange); 0258 updateFrameSize(); 0259 } 0260 0261 /*! 0262 \fn int QtTableView::numCols() const 0263 Returns the number of columns in the table. 0264 \sa numRows(), setNumCols() 0265 */ 0266 0267 /*! 0268 Sets the number of columns of the table to \a cols (must be non-negative). 0269 Does not change leftCell(). 0270 0271 The table repaints itself automatically if autoUpdate() is set. 0272 0273 \sa numCols(), numRows(), setNumRows() 0274 */ 0275 0276 void QtTableView::setNumCols(int cols) 0277 { 0278 if (cols < 0) { 0279 #if defined(QT_CHECK_RANGE) 0280 qWarning("QtTableView::setNumCols: (%s) Negative argument %d.", name("unnamed"), cols); 0281 #endif 0282 return; 0283 } 0284 if (nCols == cols) 0285 return; 0286 int oldCols = nCols; 0287 nCols = cols; 0288 if (autoUpdate() && isVisible()) { 0289 int maxCol = lastColVisible(); 0290 if (maxCol >= oldCols || maxCol >= nCols) 0291 repaint(); 0292 } 0293 updateScrollBars(horRange); 0294 updateFrameSize(); 0295 } 0296 0297 /*! 0298 \fn int QtTableView::topCell() const 0299 Returns the index of the first row in the table that is visible in 0300 the view. The index of the first row is 0. 0301 \sa leftCell(), setTopCell() 0302 */ 0303 0304 /*! 0305 Scrolls the table so that \a row becomes the top row. 0306 The index of the very first row is 0. 0307 \sa setYOffset(), setTopLeftCell(), setLeftCell() 0308 */ 0309 0310 void QtTableView::setTopCell(int row) 0311 { 0312 setTopLeftCell(row, -1); 0313 return; 0314 } 0315 0316 /*! 0317 \fn int QtTableView::leftCell() const 0318 Returns the index of the first column in the table that is visible in 0319 the view. The index of the very leftmost column is 0. 0320 \sa topCell(), setLeftCell() 0321 */ 0322 0323 /*! 0324 Scrolls the table so that \a col becomes the leftmost 0325 column. The index of the leftmost column is 0. 0326 \sa setXOffset(), setTopLeftCell(), setTopCell() 0327 */ 0328 0329 void QtTableView::setLeftCell(int col) 0330 { 0331 setTopLeftCell(-1, col); 0332 return; 0333 } 0334 0335 /*! 0336 Scrolls the table so that the cell at row \a row and column \a 0337 col becomes the top-left cell in the view. The cell at the extreme 0338 top left of the table is at position (0,0). 0339 \sa setLeftCell(), setTopCell(), setOffset() 0340 */ 0341 0342 void QtTableView::setTopLeftCell(int row, int col) 0343 { 0344 int newX = xOffs; 0345 int newY = yOffs; 0346 0347 if (col >= 0) { 0348 if (cellW) { 0349 newX = col * cellW; 0350 if (newX > maxXOffset()) 0351 newX = maxXOffset(); 0352 } else { 0353 newX = 0; 0354 while (col) 0355 newX += cellWidth(--col); // optimize using current! ### 0356 } 0357 } 0358 if (row >= 0) { 0359 if (cellH) { 0360 newY = row * cellH; 0361 if (newY > maxYOffset()) 0362 newY = maxYOffset(); 0363 } else { 0364 newY = 0; 0365 while (row) 0366 newY += cellHeight(--row); // optimize using current! ### 0367 } 0368 } 0369 setOffset(newX, newY); 0370 } 0371 0372 /*! 0373 \fn int QtTableView::xOffset() const 0374 0375 Returns the x coordinate in \e table coordinates of the pixel that is 0376 currently on the left edge of the view. 0377 0378 \sa setXOffset(), yOffset(), leftCell() */ 0379 0380 /*! 0381 Scrolls the table so that \a x becomes the leftmost pixel in the view. 0382 The \a x parameter is in \e table coordinates. 0383 0384 The interaction with \link setTableFlags() Tbl_snapToHGrid 0385 \endlink is tricky. 0386 0387 \sa xOffset(), setYOffset(), setOffset(), setLeftCell() 0388 */ 0389 0390 void QtTableView::setXOffset(int x) 0391 { 0392 setOffset(x, yOffset()); 0393 } 0394 0395 /*! 0396 \fn int QtTableView::yOffset() const 0397 0398 Returns the y coordinate in \e table coordinates of the pixel that is 0399 currently on the top edge of the view. 0400 0401 \sa setYOffset(), xOffset(), topCell() 0402 */ 0403 0404 /*! 0405 Scrolls the table so that \a y becomes the top pixel in the view. 0406 The \a y parameter is in \e table coordinates. 0407 0408 The interaction with \link setTableFlags() Tbl_snapToVGrid 0409 \endlink is tricky. 0410 0411 \sa yOffset(), setXOffset(), setOffset(), setTopCell() 0412 */ 0413 0414 void QtTableView::setYOffset(int y) 0415 { 0416 setOffset(xOffset(), y); 0417 } 0418 0419 /*! 0420 Scrolls the table so that \a (x,y) becomes the top-left pixel 0421 in the view. Parameters \a (x,y) are in \e table coordinates. 0422 0423 The interaction with \link setTableFlags() Tbl_snapTo*Grid \endlink 0424 is tricky. If \a updateScrBars is 'true', the scroll bars are 0425 updated. 0426 0427 \sa xOffset(), yOffset(), setXOffset(), setYOffset(), setTopLeftCell() 0428 */ 0429 0430 void QtTableView::setOffset(int x, int y, bool updateScrBars) 0431 { 0432 if ((!testTableFlags(Tbl_snapToHGrid) || xCellDelta == 0) && (!testTableFlags(Tbl_snapToVGrid) || yCellDelta == 0) && (x == xOffs && y == yOffs)) 0433 return; 0434 0435 if (x < 0) 0436 x = 0; 0437 if (y < 0) 0438 y = 0; 0439 0440 if (cellW) { 0441 if (x > maxXOffset()) 0442 x = maxXOffset(); 0443 xCellOffs = x / cellW; 0444 if (!testTableFlags(Tbl_snapToHGrid)) { 0445 xCellDelta = (short)(x % cellW); 0446 } else { 0447 x = xCellOffs * cellW; 0448 xCellDelta = 0; 0449 } 0450 } else { 0451 int xn = 0, xcd = 0, col = 0; 0452 while (col < nCols - 1 && x >= xn + (xcd = cellWidth(col))) { 0453 xn += xcd; 0454 col++; 0455 } 0456 xCellOffs = col; 0457 if (testTableFlags(Tbl_snapToHGrid)) { 0458 xCellDelta = 0; 0459 x = xn; 0460 } else { 0461 xCellDelta = (short)(x - xn); 0462 } 0463 } 0464 if (cellH) { 0465 if (y > maxYOffset()) 0466 y = maxYOffset(); 0467 yCellOffs = y / cellH; 0468 if (!testTableFlags(Tbl_snapToVGrid)) { 0469 yCellDelta = (short)(y % cellH); 0470 } else { 0471 y = yCellOffs * cellH; 0472 yCellDelta = 0; 0473 } 0474 } else { 0475 int yn = 0, yrd = 0, row = 0; 0476 while (row < nRows - 1 && y >= yn + (yrd = cellHeight(row))) { 0477 yn += yrd; 0478 row++; 0479 } 0480 yCellOffs = row; 0481 if (testTableFlags(Tbl_snapToVGrid)) { 0482 yCellDelta = 0; 0483 y = yn; 0484 } else { 0485 yCellDelta = (short)(y - yn); 0486 } 0487 } 0488 int dx = (x - xOffs); 0489 int dy = (y - yOffs); 0490 xOffs = x; 0491 yOffs = y; 0492 if (autoUpdate() && isVisible()) 0493 scroll(dx, dy); 0494 if (updateScrBars) 0495 updateScrollBars(verValue | horValue); 0496 } 0497 0498 /*! 0499 \overload int QtTableView::cellWidth() const 0500 0501 Returns the column width in pixels. Returns 0 if the columns have 0502 variable widths. 0503 0504 \sa setCellWidth(), cellHeight() 0505 */ 0506 0507 /*! 0508 Returns the width of column \a col in pixels. 0509 0510 This function is virtual and must be reimplemented by subclasses that 0511 have variable cell widths. Note that if the total table width 0512 changes, updateTableSize() must be called. 0513 0514 \sa setCellWidth(), cellHeight(), totalWidth(), updateTableSize() 0515 */ 0516 0517 int QtTableView::cellWidth(int) 0518 { 0519 return cellW; 0520 } 0521 0522 /*! 0523 Sets the width in pixels of the table cells to \a cellWidth. 0524 0525 Setting it to 0 means that the column width is variable. When 0526 set to 0 (this is the default) QtTableView calls the virtual function 0527 cellWidth() to get the width. 0528 0529 \sa cellWidth(), setCellHeight(), totalWidth(), numCols() 0530 */ 0531 0532 void QtTableView::setCellWidth(int cellWidth) 0533 { 0534 if (cellW == cellWidth) 0535 return; 0536 #if defined(QT_CHECK_RANGE) 0537 if (cellWidth < 0 || cellWidth > SHRT_MAX) { 0538 qWarning("QtTableView::setCellWidth: (%s) Argument out of range (%d)", name("unnamed"), cellWidth); 0539 return; 0540 } 0541 #endif 0542 cellW = (short)cellWidth; 0543 0544 updateScrollBars(horSteps | horRange); 0545 if (autoUpdate() && isVisible()) 0546 repaint(); 0547 } 0548 0549 /*! 0550 \overload int QtTableView::cellHeight() const 0551 0552 Returns the row height, in pixels. Returns 0 if the rows have 0553 variable heights. 0554 0555 \sa setCellHeight(), cellWidth() 0556 */ 0557 0558 /*! 0559 Returns the height of row \a row in pixels. 0560 0561 This function is virtual and must be reimplemented by subclasses that 0562 have variable cell heights. Note that if the total table height 0563 changes, updateTableSize() must be called. 0564 0565 \sa setCellHeight(), cellWidth(), totalHeight() 0566 */ 0567 0568 int QtTableView::cellHeight(int) 0569 { 0570 return cellH; 0571 } 0572 0573 /*! 0574 Sets the height in pixels of the table cells to \a cellHeight. 0575 0576 Setting it to 0 means that the row height is variable. When set 0577 to 0 (this is the default), QtTableView calls the virtual function 0578 cellHeight() to get the height. 0579 0580 \sa cellHeight(), setCellWidth(), totalHeight(), numRows() 0581 */ 0582 0583 void QtTableView::setCellHeight(int cellHeight) 0584 { 0585 if (cellH == cellHeight) 0586 return; 0587 #if defined(QT_CHECK_RANGE) 0588 if (cellHeight < 0 || cellHeight > SHRT_MAX) { 0589 qWarning("QtTableView::setCellHeight: (%s) Argument out of range (%d)", name("unnamed"), cellHeight); 0590 return; 0591 } 0592 #endif 0593 cellH = (short)cellHeight; 0594 if (autoUpdate() && isVisible()) 0595 repaint(); 0596 updateScrollBars(verSteps | verRange); 0597 } 0598 0599 /*! 0600 Returns the total width of the table in pixels. 0601 0602 This function is virtual and should be reimplemented by subclasses that 0603 have variable cell widths and a non-trivial cellWidth() function, or a 0604 large number of columns in the table. 0605 0606 The default implementation may be slow for very wide tables. 0607 0608 \sa cellWidth(), totalHeight() */ 0609 0610 int QtTableView::totalWidth() 0611 { 0612 if (cellW) { 0613 return cellW * nCols; 0614 } else { 0615 int tw = 0; 0616 for (int i = 0; i < nCols; i++) 0617 tw += cellWidth(i); 0618 return tw; 0619 } 0620 } 0621 0622 /*! 0623 Returns the total height of the table in pixels. 0624 0625 This function is virtual and should be reimplemented by subclasses that 0626 have variable cell heights and a non-trivial cellHeight() function, or a 0627 large number of rows in the table. 0628 0629 The default implementation may be slow for very tall tables. 0630 0631 \sa cellHeight(), totalWidth() 0632 */ 0633 0634 int QtTableView::totalHeight() 0635 { 0636 if (cellH) { 0637 return cellH * nRows; 0638 } else { 0639 int th = 0; 0640 for (int i = 0; i < nRows; i++) 0641 th += cellHeight(i); 0642 return th; 0643 } 0644 } 0645 0646 /*! 0647 \fn uint QtTableView::tableFlags() const 0648 0649 Returns the union of the table flags that are currently set. 0650 0651 \sa setTableFlags(), clearTableFlags(), testTableFlags() 0652 */ 0653 0654 /*! 0655 \fn bool QtTableView::testTableFlags( uint f ) const 0656 0657 Returns 'true' if any of the table flags in \a f are currently set, 0658 otherwise 'false'. 0659 0660 \sa setTableFlags(), clearTableFlags(), tableFlags() 0661 */ 0662 0663 /*! 0664 Sets the table flags to \a f. 0665 0666 If a flag setting changes the appearance of the table, the table is 0667 repainted if - and only if - autoUpdate() is 'true'. 0668 0669 The table flags are mostly single bits, though there are some multibit 0670 flags for convenience. Here is a complete list: 0671 0672 <dl compact> 0673 <dt> Tbl_vScrollBar <dd> - The table has a vertical scroll bar. 0674 <dt> Tbl_hScrollBar <dd> - The table has a horizontal scroll bar. 0675 <dt> Tbl_autoVScrollBar <dd> - The table has a vertical scroll bar if 0676 - and only if - the table is taller than the view. 0677 <dt> Tbl_autoHScrollBar <dd> The table has a horizontal scroll bar if 0678 - and only if - the table is wider than the view. 0679 <dt> Tbl_autoScrollBars <dd> - The union of the previous two flags. 0680 <dt> Tbl_clipCellPainting <dd> - The table uses QPainter::setClipRect() to 0681 make sure that paintCell() will not draw outside the cell 0682 boundaries. 0683 <dt> Tbl_cutCellsV <dd> - The table will never show part of a 0684 cell at the bottom of the table; if there is not space for all of 0685 a cell, the space is left blank. 0686 <dt> Tbl_cutCellsH <dd> - The table will never show part of a 0687 cell at the right side of the table; if there is not space for all of 0688 a cell, the space is left blank. 0689 <dt> Tbl_cutCells <dd> - The union of the previous two flags. 0690 <dt> Tbl_scrollLastHCell <dd> - When the user scrolls horizontally, 0691 let him/her scroll the last cell left until it is at the left 0692 edge of the view. If this flag is not set, the user can only scroll 0693 to the point where the last cell is completely visible. 0694 <dt> Tbl_scrollLastVCell <dd> - When the user scrolls vertically, let 0695 him/her scroll the last cell up until it is at the top edge of 0696 the view. If this flag is not set, the user can only scroll to the 0697 point where the last cell is completely visible. 0698 <dt> Tbl_scrollLastCell <dd> - The union of the previous two flags. 0699 <dt> Tbl_smoothHScrolling <dd> - The table scrolls as smoothly as 0700 possible when the user scrolls horizontally. When this flag is not 0701 set, scrolling is done one cell at a time. 0702 <dt> Tbl_smoothVScrolling <dd> - The table scrolls as smoothly as 0703 possible when scrolling vertically. When this flag is not set, 0704 scrolling is done one cell at a time. 0705 <dt> Tbl_smoothScrolling <dd> - The union of the previous two flags. 0706 <dt> Tbl_snapToHGrid <dd> - Except when the user is actually scrolling, 0707 the leftmost column shown snaps to the leftmost edge of the view. 0708 <dt> Tbl_snapToVGrid <dd> - Except when the user is actually 0709 scrolling, the top row snaps to the top edge of the view. 0710 <dt> Tbl_snapToGrid <dd> - The union of the previous two flags. 0711 </dl> 0712 0713 You can specify more than one flag at a time using bitwise OR. 0714 0715 Example: 0716 \code 0717 setTableFlags( Tbl_smoothScrolling | Tbl_autoScrollBars ); 0718 \endcode 0719 0720 \warning The cutCells options (\c Tbl_cutCells, \c Tbl_cutCellsH and 0721 Tbl_cutCellsV) may cause painting problems when scrollbars are 0722 enabled. Do not combine cutCells and scrollbars. 0723 0724 0725 \sa clearTableFlags(), testTableFlags(), tableFlags() 0726 */ 0727 0728 void QtTableView::setTableFlags(uint f) 0729 { 0730 f = (f ^ tFlags) & f; // clear flags already set 0731 tFlags |= f; 0732 0733 bool updateOn = autoUpdate(); 0734 setAutoUpdate(false); 0735 0736 uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH; 0737 0738 if (f & Tbl_vScrollBar) { 0739 setVerScrollBar(true); 0740 } 0741 if (f & Tbl_hScrollBar) { 0742 setHorScrollBar(true); 0743 } 0744 if (f & Tbl_autoVScrollBar) { 0745 updateScrollBars(verRange); 0746 } 0747 if (f & Tbl_autoHScrollBar) { 0748 updateScrollBars(horRange); 0749 } 0750 if (f & Tbl_scrollLastHCell) { 0751 updateScrollBars(horRange); 0752 } 0753 if (f & Tbl_scrollLastVCell) { 0754 updateScrollBars(verRange); 0755 } 0756 if (f & Tbl_snapToHGrid) { 0757 updateScrollBars(horRange); 0758 } 0759 if (f & Tbl_snapToVGrid) { 0760 updateScrollBars(verRange); 0761 } 0762 if (f & Tbl_snapToGrid) { // Note: checks for 2 flags 0763 if ((f & Tbl_snapToHGrid) != 0 && xCellDelta != 0 || // have to scroll? 0764 (f & Tbl_snapToVGrid) != 0 && yCellDelta != 0) { 0765 snapToGrid((f & Tbl_snapToHGrid) != 0, // do snapping 0766 (f & Tbl_snapToVGrid) != 0); 0767 repaintMask |= Tbl_snapToGrid; // repaint table 0768 } 0769 } 0770 0771 if (updateOn) { 0772 setAutoUpdate(true); 0773 updateScrollBars(); 0774 if (isVisible() && (f & repaintMask)) 0775 repaint(); 0776 } 0777 } 0778 0779 /*! 0780 Clears the \link setTableFlags() table flags\endlink that are set 0781 in \a f. 0782 0783 Example (clears a single flag): 0784 \code 0785 clearTableFlags( Tbl_snapToGrid ); 0786 \endcode 0787 0788 The default argument clears all flags. 0789 0790 \sa setTableFlags(), testTableFlags(), tableFlags() 0791 */ 0792 0793 void QtTableView::clearTableFlags(uint f) 0794 { 0795 f = (f ^ ~tFlags) & f; // clear flags that are already 0 0796 tFlags &= ~f; 0797 0798 bool updateOn = autoUpdate(); 0799 setAutoUpdate(false); 0800 0801 uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH; 0802 0803 if (f & Tbl_vScrollBar) { 0804 setVerScrollBar(false); 0805 } 0806 if (f & Tbl_hScrollBar) { 0807 setHorScrollBar(false); 0808 } 0809 if (f & Tbl_scrollLastHCell) { 0810 int maxX = maxXOffset(); 0811 if (xOffs > maxX) { 0812 setOffset(maxX, yOffs); 0813 repaintMask |= Tbl_scrollLastHCell; 0814 } 0815 updateScrollBars(horRange); 0816 } 0817 if (f & Tbl_scrollLastVCell) { 0818 int maxY = maxYOffset(); 0819 if (yOffs > maxY) { 0820 setOffset(xOffs, maxY); 0821 repaintMask |= Tbl_scrollLastVCell; 0822 } 0823 updateScrollBars(verRange); 0824 } 0825 if (f & Tbl_smoothScrolling) { // Note: checks for 2 flags 0826 if ((f & Tbl_smoothHScrolling) != 0 && xCellDelta != 0 || // must scroll? 0827 (f & Tbl_smoothVScrolling) != 0 && yCellDelta != 0) { 0828 snapToGrid((f & Tbl_smoothHScrolling) != 0, // do snapping 0829 (f & Tbl_smoothVScrolling) != 0); 0830 repaintMask |= Tbl_smoothScrolling; // repaint table 0831 } 0832 } 0833 if (f & Tbl_snapToHGrid) { 0834 updateScrollBars(horRange); 0835 } 0836 if (f & Tbl_snapToVGrid) { 0837 updateScrollBars(verRange); 0838 } 0839 if (updateOn) { 0840 setAutoUpdate(true); 0841 updateScrollBars(); // returns immediately if nothing to do 0842 if (isVisible() && (f & repaintMask)) 0843 repaint(); 0844 } 0845 } 0846 0847 /*! 0848 \fn bool QtTableView::autoUpdate() const 0849 0850 Returns 'true' if the view updates itself automatically whenever it 0851 is changed in some way. 0852 0853 \sa setAutoUpdate() 0854 */ 0855 0856 /*! 0857 Sets the auto-update option of the table view to \a enable. 0858 0859 If \a enable is 'true' (this is the default), the view updates itself 0860 automatically whenever it has changed in some way (for example, when a 0861 \link setTableFlags() flag\endlink is changed). 0862 0863 If \a enable is 'false', the view does NOT repaint itself or update 0864 its internal state variables when it is changed. This can be 0865 useful to avoid flicker during large changes and is singularly 0866 useless otherwise. Disable auto-update, do the changes, re-enable 0867 auto-update and call repaint(). 0868 0869 \warning Do not leave the view in this state for a long time 0870 (i.e., between events). If, for example, the user interacts with the 0871 view when auto-update is off, strange things can happen. 0872 0873 Setting auto-update to 'true' does not repaint the view; you must call 0874 repaint() to do this. 0875 0876 \sa autoUpdate(), repaint() 0877 */ 0878 0879 void QtTableView::setAutoUpdate(bool enable) 0880 { 0881 if (updatesEnabled() == enable) 0882 return; 0883 setUpdatesEnabled(enable); 0884 if (enable) { 0885 showOrHideScrollBars(); 0886 updateScrollBars(); 0887 } 0888 } 0889 0890 /*! 0891 Repaints the cell at row \a row, column \a col if it is inside the view. 0892 0893 If \a erase is 'true', the relevant part of the view is cleared to the 0894 background color/pixmap before the contents are repainted. 0895 0896 \sa isVisible() 0897 */ 0898 0899 void QtTableView::updateCell(int row, int col, bool erase) 0900 { 0901 int xPos, yPos; 0902 if (!colXPos(col, &xPos)) 0903 return; 0904 if (!rowYPos(row, &yPos)) 0905 return; 0906 QRect uR = QRect(xPos, yPos, cellW ? cellW : cellWidth(col), cellH ? cellH : cellHeight(row)); 0907 repaint(uR.intersected(viewRect()), erase); 0908 } 0909 0910 /*! 0911 \fn QRect QtTableView::cellUpdateRect() const 0912 0913 This function should be called only from the paintCell() function in 0914 subclasses. It returns the portion of a cell that actually needs to be 0915 updated in \e cell coordinates. This is useful only for non-trivial 0916 paintCell(). 0917 0918 */ 0919 0920 /*! 0921 Returns the rectangle that is the actual table, excluding any 0922 frame, in \e widget coordinates. 0923 */ 0924 0925 QRect QtTableView::viewRect() const 0926 { 0927 return {frameWidth(), frameWidth(), viewWidth(), viewHeight()}; 0928 } 0929 0930 /*! 0931 Returns the index of the last (bottom) row in the view. 0932 The index of the first row is 0. 0933 0934 If no rows are visible it returns -1. This can happen if the 0935 view is too small for the first row and Tbl_cutCellsV is set. 0936 0937 \sa lastColVisible() 0938 */ 0939 0940 int QtTableView::lastRowVisible() const 0941 { 0942 int cellMaxY; 0943 int row = findRawRow(maxViewY(), &cellMaxY); 0944 if (row == -1 || row >= nRows) { // maxViewY() past end? 0945 row = nRows - 1; // yes: return last row 0946 } else { 0947 if (testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY()) { 0948 if (row == yCellOffs) // cut by right margin? 0949 return -1; // yes, nothing in the view 0950 else 0951 row = row - 1; // cut by margin, one back 0952 } 0953 } 0954 return row; 0955 } 0956 0957 /*! 0958 Returns the index of the last (right) column in the view. 0959 The index of the first column is 0. 0960 0961 If no columns are visible it returns -1. This can happen if the 0962 view is too narrow for the first column and Tbl_cutCellsH is set. 0963 0964 \sa lastRowVisible() 0965 */ 0966 0967 int QtTableView::lastColVisible() const 0968 { 0969 int cellMaxX; 0970 int col = findRawCol(maxViewX(), &cellMaxX); 0971 if (col == -1 || col >= nCols) { // maxViewX() past end? 0972 col = nCols - 1; // yes: return last col 0973 } else { 0974 if (testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX()) { 0975 if (col == xCellOffs) // cut by bottom margin? 0976 return -1; // yes, nothing in the view 0977 else 0978 col = col - 1; // cell by margin, one back 0979 } 0980 } 0981 return col; 0982 } 0983 0984 /*! 0985 Returns 'true' if \a row is at least partially visible. 0986 \sa colIsVisible() 0987 */ 0988 0989 bool QtTableView::rowIsVisible(int row) const 0990 { 0991 return rowYPos(row, 0); 0992 } 0993 0994 /*! 0995 Returns 'true' if \a col is at least partially visible. 0996 \sa rowIsVisible() 0997 */ 0998 0999 bool QtTableView::colIsVisible(int col) const 1000 { 1001 return colXPos(col, 0); 1002 } 1003 1004 /*! 1005 \internal 1006 Called when both scroll bars are active at the same time. Covers the 1007 bottom left corner between the two scroll bars with an empty widget. 1008 */ 1009 1010 void QtTableView::coverCornerSquare(bool enable) 1011 { 1012 coveringCornerSquare = enable; 1013 if (!cornerSquare && enable) { 1014 cornerSquare = new QCornerSquare(this); 1015 Q_CHECK_PTR(cornerSquare); 1016 cornerSquare->setGeometry(maxViewX() + frameWidth() + 1, maxViewY() + frameWidth() + 1, VSBEXT, HSBEXT); 1017 } 1018 if (autoUpdate() && cornerSquare) { 1019 if (enable) 1020 cornerSquare->show(); 1021 else 1022 cornerSquare->hide(); 1023 } 1024 } 1025 1026 /*! 1027 \internal 1028 Scroll the view to a position such that: 1029 1030 If \a horizontal is 'true', the leftmost column shown fits snugly 1031 with the left edge of the view. 1032 1033 If \a vertical is 'true', the top row shown fits snugly with the top 1034 of the view. 1035 1036 You can achieve the same effect automatically by setting any of the 1037 \link setTableFlags() Tbl_snapTo*Grid \endlink table flags. 1038 */ 1039 1040 void QtTableView::snapToGrid(bool horizontal, bool vertical) 1041 { 1042 int newXCell = -1; 1043 int newYCell = -1; 1044 if (horizontal && xCellDelta != 0) { 1045 int w = cellW ? cellW : cellWidth(xCellOffs); 1046 if (xCellDelta >= w / 2) 1047 newXCell = xCellOffs + 1; 1048 else 1049 newXCell = xCellOffs; 1050 } 1051 if (vertical && yCellDelta != 0) { 1052 int h = cellH ? cellH : cellHeight(yCellOffs); 1053 if (yCellDelta >= h / 2) 1054 newYCell = yCellOffs + 1; 1055 else 1056 newYCell = yCellOffs; 1057 } 1058 setTopLeftCell(newYCell, newXCell); // row,column 1059 } 1060 1061 /*! 1062 \internal 1063 This internal slot is connected to the horizontal scroll bar's 1064 QScrollBar::valueChanged() signal. 1065 1066 Moves the table horizontally to offset \a val without updating the 1067 scroll bar. 1068 */ 1069 1070 void QtTableView::horSbValue(int val) 1071 { 1072 if (horSliding) { 1073 horSliding = false; 1074 if (horSnappingOff) { 1075 horSnappingOff = false; 1076 tFlags |= Tbl_snapToHGrid; 1077 } 1078 } 1079 setOffset(val, yOffs, false); 1080 } 1081 1082 /*! 1083 \internal 1084 This internal slot is connected to the horizontal scroll bar's 1085 QScrollBar::sliderMoved() signal. 1086 1087 Scrolls the table smoothly horizontally even if \c Tbl_snapToHGrid is set. 1088 */ 1089 1090 void QtTableView::horSbSliding(int val) 1091 { 1092 if (testTableFlags(Tbl_snapToHGrid) && testTableFlags(Tbl_smoothHScrolling)) { 1093 tFlags &= ~Tbl_snapToHGrid; // turn off snapping while sliding 1094 setOffset(val, yOffs, false); 1095 tFlags |= Tbl_snapToHGrid; // turn on snapping again 1096 } else { 1097 setOffset(val, yOffs, false); 1098 } 1099 } 1100 1101 /*! 1102 \internal 1103 This internal slot is connected to the horizontal scroll bar's 1104 QScrollBar::sliderReleased() signal. 1105 */ 1106 1107 void QtTableView::horSbSlidingDone() 1108 { 1109 if (testTableFlags(Tbl_snapToHGrid) && testTableFlags(Tbl_smoothHScrolling)) 1110 snapToGrid(true, false); 1111 } 1112 1113 /*! 1114 \internal 1115 This internal slot is connected to the vertical scroll bar's 1116 QScrollBar::valueChanged() signal. 1117 1118 Moves the table vertically to offset \a val without updating the 1119 scroll bar. 1120 */ 1121 1122 void QtTableView::verSbValue(int val) 1123 { 1124 if (verSliding) { 1125 verSliding = false; 1126 if (verSnappingOff) { 1127 verSnappingOff = false; 1128 tFlags |= Tbl_snapToVGrid; 1129 } 1130 } 1131 setOffset(xOffs, val, false); 1132 } 1133 1134 /*! 1135 \internal 1136 This internal slot is connected to the vertical scroll bar's 1137 QScrollBar::sliderMoved() signal. 1138 1139 Scrolls the table smoothly vertically even if \c Tbl_snapToVGrid is set. 1140 */ 1141 1142 void QtTableView::verSbSliding(int val) 1143 { 1144 if (testTableFlags(Tbl_snapToVGrid) && testTableFlags(Tbl_smoothVScrolling)) { 1145 tFlags &= ~Tbl_snapToVGrid; // turn off snapping while sliding 1146 setOffset(xOffs, val, false); 1147 tFlags |= Tbl_snapToVGrid; // turn on snapping again 1148 } else { 1149 setOffset(xOffs, val, false); 1150 } 1151 } 1152 1153 /*! 1154 \internal 1155 This internal slot is connected to the vertical scroll bar's 1156 QScrollBar::sliderReleased() signal. 1157 */ 1158 1159 void QtTableView::verSbSlidingDone() 1160 { 1161 if (testTableFlags(Tbl_snapToVGrid) && testTableFlags(Tbl_smoothVScrolling)) 1162 snapToGrid(false, true); 1163 } 1164 1165 /*! 1166 This virtual function is called before painting of table cells 1167 is started. It can be reimplemented by subclasses that want to 1168 to set up the painter in a special way and that do not want to 1169 do so for each cell. 1170 */ 1171 1172 void QtTableView::setupPainter(QPainter *) 1173 { 1174 } 1175 1176 /*! 1177 \fn void QtTableView::paintCell( QPainter *p, int row, int col ) 1178 1179 This pure virtual function is called to paint the single cell at \a 1180 (row,col) using \a p, which is open when paintCell() is called and 1181 must remain open. 1182 1183 The coordinate system is \link QPainter::translate() translated \endlink 1184 so that the origin is at the top-left corner of the cell to be 1185 painted, i.e. \e cell coordinates. Do not scale or shear the coordinate 1186 system (or if you do, restore the transformation matrix before you 1187 return). 1188 1189 The painter is not clipped by default and for maximum efficiency. For safety, 1190 call setTableFlags(Tbl_clipCellPainting) to enable clipping. 1191 1192 \sa paintEvent(), setTableFlags() */ 1193 1194 /*! 1195 Handles paint events, \a e, for the table view. 1196 1197 Calls paintCell() for the cells that needs to be repainted. 1198 */ 1199 1200 void QtTableView::paintEvent(QPaintEvent *e) 1201 { 1202 QRect updateR = e->rect(); // update rectangle 1203 if (sbDirty) { 1204 bool e = eraseInPaint; 1205 updateScrollBars(); 1206 eraseInPaint = e; 1207 } 1208 1209 QPainter paint(this); 1210 1211 if (!contentsRect().contains(updateR, true)) { // update frame ? 1212 drawFrame(&paint); 1213 if (updateR.left() < frameWidth()) //### 1214 updateR.setLeft(frameWidth()); 1215 if (updateR.top() < frameWidth()) 1216 updateR.setTop(frameWidth()); 1217 } 1218 1219 int maxWX = maxViewX(); 1220 int maxWY = maxViewY(); 1221 if (updateR.right() > maxWX) 1222 updateR.setRight(maxWX); 1223 if (updateR.bottom() > maxWY) 1224 updateR.setBottom(maxWY); 1225 1226 setupPainter(&paint); // prepare for painting table 1227 1228 int firstRow = findRow(updateR.y()); 1229 int firstCol = findCol(updateR.x()); 1230 int xStart, yStart; 1231 if (!colXPos(firstCol, &xStart) || !rowYPos(firstRow, &yStart)) { 1232 paint.eraseRect(updateR); // erase area outside cells but in view 1233 return; 1234 } 1235 int maxX = updateR.right(); 1236 int maxY = updateR.bottom(); 1237 int row = firstRow; 1238 int col; 1239 int yPos = yStart; 1240 int xPos = maxX + 1; // in case the while() is empty 1241 int nextX; 1242 int nextY; 1243 QRect winR = viewRect(); 1244 QRect cellR; 1245 QRect cellUR; 1246 #ifndef QT_NO_TRANSFORMATIONS 1247 QTransform matrix; 1248 #endif 1249 1250 while (yPos <= maxY && row < nRows) { 1251 nextY = yPos + (cellH ? cellH : cellHeight(row)); 1252 if (testTableFlags(Tbl_cutCellsV) && nextY > (maxWY + 1)) 1253 break; 1254 col = firstCol; 1255 xPos = xStart; 1256 while (xPos <= maxX && col < nCols) { 1257 nextX = xPos + (cellW ? cellW : cellWidth(col)); 1258 if (testTableFlags(Tbl_cutCellsH) && nextX > (maxWX + 1)) 1259 break; 1260 1261 cellR.setRect(xPos, yPos, cellW ? cellW : cellWidth(col), cellH ? cellH : cellHeight(row)); 1262 cellUR = cellR.intersected(updateR); 1263 if (cellUR.isValid()) { 1264 cellUpdateR = cellUR; 1265 cellUpdateR.translate(-xPos, -yPos); // cell coordinates 1266 if (eraseInPaint) 1267 paint.eraseRect(cellUR); 1268 1269 #ifndef QT_NO_TRANSFORMATIONS 1270 matrix.translate(xPos, yPos); 1271 paint.setTransform(matrix); 1272 if (testTableFlags(Tbl_clipCellPainting) || frameWidth() > 0 && !winR.contains(cellR)) { //##arnt 1273 #ifdef __GNUC__ 1274 #warning disable clipping for now as it interferes with drawText() in DiffView::paintCell() 1275 #endif 1276 // paint.setClipRect( cellUpdateR ); 1277 paintCell(&paint, row, col); 1278 // paint.setClipping( false ); 1279 } else { 1280 paintCell(&paint, row, col); 1281 } 1282 matrix.reset(); 1283 paint.setTransform(matrix); 1284 #else 1285 paint.translate(xPos, yPos); 1286 if (testTableFlags(Tbl_clipCellPainting) || frameWidth() > 0 && !winR.contains(cellR)) { //##arnt 1287 paint.setClipRect(cellUpdateR); 1288 paintCell(&paint, row, col); 1289 paint.setClipping(false); 1290 } else { 1291 paintCell(&paint, row, col); 1292 } 1293 paint.translate(-xPos, -yPos); 1294 #endif 1295 } 1296 col++; 1297 xPos = nextX; 1298 } 1299 row++; 1300 yPos = nextY; 1301 } 1302 1303 // while painting we have to erase any areas in the view that 1304 // are not covered by cells but are covered by the paint event 1305 // rectangle these must be erased. We know that xPos is the last 1306 // x pixel updated + 1 and that yPos is the last y pixel updated + 1. 1307 1308 // Note that this needs to be done regardless whether we do 1309 // eraseInPaint or not. Reason: a subclass may implement 1310 // flicker-freeness and encourage the use of repaint(false). 1311 // The subclass, however, cannot draw all pixels, just those 1312 // inside the cells. So QtTableView is responsible for all pixels 1313 // outside the cells. 1314 1315 QRect viewR = viewRect(); 1316 QPalette g = palette(); 1317 1318 if (xPos <= maxX) { 1319 QRect r = viewR; 1320 r.setLeft(xPos); 1321 r.setBottom(yPos < maxY ? yPos : maxY); 1322 if (inherits("QMultiLineEdit")) 1323 paint.fillRect(r.intersected(updateR), g.base()); 1324 else 1325 paint.eraseRect(r.intersected(updateR)); 1326 } 1327 if (yPos <= maxY) { 1328 QRect r = viewR; 1329 r.setTop(yPos); 1330 if (inherits("QMultiLineEdit")) 1331 paint.fillRect(r.intersected(updateR), g.base()); 1332 else 1333 paint.eraseRect(r.intersected(updateR)); 1334 } 1335 } 1336 1337 /*!\reimp 1338 */ 1339 void QtTableView::resizeEvent(QResizeEvent *) 1340 { 1341 updateScrollBars(horValue | verValue | horSteps | horGeometry | horRange | verSteps | verGeometry | verRange); 1342 showOrHideScrollBars(); 1343 updateFrameSize(); 1344 int maxX = qMin(xOffs, maxXOffset()); // ### can be slow 1345 int maxY = qMin(yOffs, maxYOffset()); 1346 setOffset(maxX, maxY); 1347 } 1348 1349 void QtTableView::showEvent(QShowEvent *e) 1350 { 1351 showOrHideScrollBars(); 1352 QFrame::showEvent(e); 1353 } 1354 1355 void QtTableView::wheelEvent(QWheelEvent *e) 1356 { 1357 if (e->orientation() == Qt::Vertical && vScrollBar && vScrollBar->isVisible()) 1358 QApplication::sendEvent(vScrollBar, e); 1359 } 1360 1361 /*! 1362 Redraws all visible cells in the table view. 1363 */ 1364 1365 void QtTableView::updateView() 1366 { 1367 repaint(viewRect()); 1368 } 1369 1370 /*! 1371 Returns a pointer to the vertical scroll bar mainly so you can 1372 connect() to its signals. Note that the scroll bar works in pixel 1373 values; use findRow() to translate to cell numbers. 1374 */ 1375 1376 QScrollBar *QtTableView::verticalScrollBar() const 1377 { 1378 auto that = (QtTableView *)this; // semantic const 1379 if (!vScrollBar) { 1380 auto sb = new QScrollBar(Qt::Vertical, that); 1381 sb->setAttribute(Qt::WA_NoMousePropagation); 1382 sb->setAutoFillBackground(true); 1383 #ifndef QT_NO_CURSOR 1384 sb->setCursor(Qt::ArrowCursor); 1385 #endif 1386 sb->resize(sb->sizeHint()); // height is irrelevant 1387 Q_CHECK_PTR(sb); 1388 sb->setTracking(false); 1389 sb->setFocusPolicy(Qt::NoFocus); 1390 connect(sb, SIGNAL(valueChanged(int)), SLOT(verSbValue(int))); 1391 connect(sb, SIGNAL(sliderMoved(int)), SLOT(verSbSliding(int))); 1392 connect(sb, SIGNAL(sliderReleased()), SLOT(verSbSlidingDone())); 1393 sb->hide(); 1394 that->vScrollBar = sb; 1395 return sb; 1396 } 1397 return vScrollBar; 1398 } 1399 1400 /*! 1401 Returns a pointer to the horizontal scroll bar mainly so you can 1402 connect() to its signals. Note that the scroll bar works in pixel 1403 values; use findCol() to translate to cell numbers. 1404 */ 1405 1406 QScrollBar *QtTableView::horizontalScrollBar() const 1407 { 1408 auto that = (QtTableView *)this; // semantic const 1409 if (!hScrollBar) { 1410 auto sb = new QScrollBar(Qt::Horizontal, that); 1411 sb->setAutoFillBackground(true); 1412 #ifndef QT_NO_CURSOR 1413 sb->setCursor(Qt::ArrowCursor); 1414 #endif 1415 sb->resize(sb->sizeHint()); // width is irrelevant 1416 sb->setFocusPolicy(Qt::NoFocus); 1417 Q_CHECK_PTR(sb); 1418 sb->setTracking(false); 1419 connect(sb, SIGNAL(valueChanged(int)), SLOT(horSbValue(int))); 1420 connect(sb, SIGNAL(sliderMoved(int)), SLOT(horSbSliding(int))); 1421 connect(sb, SIGNAL(sliderReleased()), SLOT(horSbSlidingDone())); 1422 sb->hide(); 1423 that->hScrollBar = sb; 1424 return sb; 1425 } 1426 return hScrollBar; 1427 } 1428 1429 /*! 1430 Enables or disables the horizontal scroll bar, as required by 1431 setAutoUpdate() and the \link setTableFlags() table flags\endlink. 1432 */ 1433 1434 void QtTableView::setHorScrollBar(bool on, bool update) 1435 { 1436 if (on) { 1437 tFlags |= Tbl_hScrollBar; 1438 horizontalScrollBar(); // created 1439 if (update) 1440 updateScrollBars(horMask | verMask); 1441 else 1442 sbDirty = sbDirty | (horMask | verMask); 1443 if (testTableFlags(Tbl_vScrollBar)) 1444 coverCornerSquare(true); 1445 if (autoUpdate()) 1446 sbDirty = sbDirty | horMask; 1447 } else { 1448 tFlags &= ~Tbl_hScrollBar; 1449 if (!hScrollBar) 1450 return; 1451 coverCornerSquare(false); 1452 bool hideScrollBar = autoUpdate() && hScrollBar->isVisible(); 1453 if (hideScrollBar) 1454 hScrollBar->hide(); 1455 if (update) 1456 updateScrollBars(verMask); 1457 else 1458 sbDirty = sbDirty | verMask; 1459 if (hideScrollBar && isVisible()) 1460 repaint(hScrollBar->x(), hScrollBar->y(), width() - hScrollBar->x(), hScrollBar->height()); 1461 } 1462 if (update) 1463 updateFrameSize(); 1464 } 1465 1466 /*! 1467 Enables or disables the vertical scroll bar, as required by 1468 setAutoUpdate() and the \link setTableFlags() table flags\endlink. 1469 */ 1470 1471 void QtTableView::setVerScrollBar(bool on, bool update) 1472 { 1473 if (on) { 1474 tFlags |= Tbl_vScrollBar; 1475 verticalScrollBar(); // created 1476 if (update) 1477 updateScrollBars(verMask | horMask); 1478 else 1479 sbDirty = sbDirty | (horMask | verMask); 1480 if (testTableFlags(Tbl_hScrollBar)) 1481 coverCornerSquare(true); 1482 if (autoUpdate()) 1483 sbDirty = sbDirty | verMask; 1484 } else { 1485 tFlags &= ~Tbl_vScrollBar; 1486 if (!vScrollBar) 1487 return; 1488 coverCornerSquare(false); 1489 bool hideScrollBar = autoUpdate() && vScrollBar->isVisible(); 1490 if (hideScrollBar) 1491 vScrollBar->hide(); 1492 if (update) 1493 updateScrollBars(horMask); 1494 else 1495 sbDirty = sbDirty | horMask; 1496 if (hideScrollBar && isVisible()) 1497 repaint(vScrollBar->x(), vScrollBar->y(), vScrollBar->width(), height() - vScrollBar->y()); 1498 } 1499 if (update) 1500 updateFrameSize(); 1501 } 1502 1503 int QtTableView::findRawRow(int yPos, int *cellMaxY, int *cellMinY, bool goOutsideView) const 1504 { 1505 int r = -1; 1506 if (nRows == 0) 1507 return r; 1508 if (goOutsideView || yPos >= minViewY() && yPos <= maxViewY()) { 1509 if (yPos < minViewY()) { 1510 #if defined(QT_CHECK_RANGE) 1511 qWarning( 1512 "QtTableView::findRawRow: (%s) internal error: " 1513 "yPos < minViewY() && goOutsideView " 1514 "not supported. (%d,%d)", 1515 name("unnamed"), 1516 yPos, 1517 yOffs); 1518 #endif 1519 return -1; 1520 } 1521 if (cellH) { // uniform cell height 1522 r = (yPos - minViewY() + yCellDelta) / cellH; // cell offs from top 1523 if (cellMaxY) 1524 *cellMaxY = (r + 1) * cellH + minViewY() - yCellDelta - 1; 1525 if (cellMinY) 1526 *cellMinY = r * cellH + minViewY() - yCellDelta; 1527 r += yCellOffs; // absolute cell index 1528 } else { // variable cell height 1529 auto tw = (QtTableView *)this; 1530 r = yCellOffs; 1531 int h = minViewY() - yCellDelta; //##arnt3 1532 int oldH = h; 1533 Q_ASSERT(r < nRows); 1534 while (r < nRows) { 1535 oldH = h; 1536 h += tw->cellHeight(r); // Start of next cell 1537 if (yPos < h) 1538 break; 1539 r++; 1540 } 1541 if (cellMaxY) 1542 *cellMaxY = h - 1; 1543 if (cellMinY) 1544 *cellMinY = oldH; 1545 } 1546 } 1547 return r; 1548 } 1549 1550 int QtTableView::findRawCol(int xPos, int *cellMaxX, int *cellMinX, bool goOutsideView) const 1551 { 1552 int c = -1; 1553 if (nCols == 0) 1554 return c; 1555 if (goOutsideView || xPos >= minViewX() && xPos <= maxViewX()) { 1556 if (xPos < minViewX()) { 1557 #if defined(QT_CHECK_RANGE) 1558 qWarning( 1559 "QtTableView::findRawCol: (%s) internal error: " 1560 "xPos < minViewX() && goOutsideView " 1561 "not supported. (%d,%d)", 1562 name("unnamed"), 1563 xPos, 1564 xOffs); 1565 #endif 1566 return -1; 1567 } 1568 if (cellW) { // uniform cell width 1569 c = (xPos - minViewX() + xCellDelta) / cellW; // cell offs from left 1570 if (cellMaxX) 1571 *cellMaxX = (c + 1) * cellW + minViewX() - xCellDelta - 1; 1572 if (cellMinX) 1573 *cellMinX = c * cellW + minViewX() - xCellDelta; 1574 c += xCellOffs; // absolute cell index 1575 } else { // variable cell width 1576 auto tw = (QtTableView *)this; 1577 c = xCellOffs; 1578 int w = minViewX() - xCellDelta; //##arnt3 1579 int oldW = w; 1580 Q_ASSERT(c < nCols); 1581 while (c < nCols) { 1582 oldW = w; 1583 w += tw->cellWidth(c); // Start of next cell 1584 if (xPos < w) 1585 break; 1586 c++; 1587 } 1588 if (cellMaxX) 1589 *cellMaxX = w - 1; 1590 if (cellMinX) 1591 *cellMinX = oldW; 1592 } 1593 } 1594 return c; 1595 } 1596 1597 /*! 1598 Returns the index of the row at position \a yPos, where \a yPos is in 1599 \e widget coordinates. Returns -1 if \a yPos is outside the valid 1600 range. 1601 1602 \sa findCol(), rowYPos() 1603 */ 1604 1605 int QtTableView::findRow(int yPos) const 1606 { 1607 int cellMaxY; 1608 int row = findRawRow(yPos, &cellMaxY); 1609 if (testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY()) 1610 row = -1; // cell cut by bottom margin 1611 if (row >= nRows) 1612 row = -1; 1613 return row; 1614 } 1615 1616 /*! 1617 Returns the index of the column at position \a xPos, where \a xPos is 1618 in \e widget coordinates. Returns -1 if \a xPos is outside the valid 1619 range. 1620 1621 \sa findRow(), colXPos() 1622 */ 1623 1624 int QtTableView::findCol(int xPos) const 1625 { 1626 int cellMaxX; 1627 int col = findRawCol(xPos, &cellMaxX); 1628 if (testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX()) 1629 col = -1; // cell cut by right margin 1630 if (col >= nCols) 1631 col = -1; 1632 return col; 1633 } 1634 1635 /*! 1636 Computes the position in the widget of row \a row. 1637 1638 Returns 'true' and stores the result in \a *yPos (in \e widget 1639 coordinates) if the row is visible. Returns 'false' and does not modify 1640 \a *yPos if \a row is invisible or invalid. 1641 1642 \sa colXPos(), findRow() 1643 */ 1644 1645 bool QtTableView::rowYPos(int row, int *yPos) const 1646 { 1647 int y; 1648 if (row >= yCellOffs) { 1649 if (cellH) { 1650 int lastVisible = lastRowVisible(); 1651 if (row > lastVisible || lastVisible == -1) 1652 return false; 1653 y = (row - yCellOffs) * cellH + minViewY() - yCellDelta; 1654 } else { 1655 //##arnt3 1656 y = minViewY() - yCellDelta; // y of leftmost cell in view 1657 int r = yCellOffs; 1658 auto tw = (QtTableView *)this; 1659 int maxY = maxViewY(); 1660 while (r < row && y <= maxY) 1661 y += tw->cellHeight(r++); 1662 if (y > maxY) 1663 return false; 1664 } 1665 } else { 1666 return false; 1667 } 1668 if (yPos) 1669 *yPos = y; 1670 return true; 1671 } 1672 1673 /*! 1674 Computes the position in the widget of column \a col. 1675 1676 Returns 'true' and stores the result in \a *xPos (in \e widget 1677 coordinates) if the column is visible. Returns 'false' and does not 1678 modify \a *xPos if \a col is invisible or invalid. 1679 1680 \sa rowYPos(), findCol() 1681 */ 1682 1683 bool QtTableView::colXPos(int col, int *xPos) const 1684 { 1685 int x; 1686 if (col >= xCellOffs) { 1687 if (cellW) { 1688 int lastVisible = lastColVisible(); 1689 if (col > lastVisible || lastVisible == -1) 1690 return false; 1691 x = (col - xCellOffs) * cellW + minViewX() - xCellDelta; 1692 } else { 1693 //##arnt3 1694 x = minViewX() - xCellDelta; // x of uppermost cell in view 1695 int c = xCellOffs; 1696 auto tw = (QtTableView *)this; 1697 int maxX = maxViewX(); 1698 while (c < col && x <= maxX) 1699 x += tw->cellWidth(c++); 1700 if (x > maxX) 1701 return false; 1702 } 1703 } else { 1704 return false; 1705 } 1706 if (xPos) 1707 *xPos = x; 1708 return true; 1709 } 1710 1711 /*! 1712 Moves the visible area of the table right by \a xPixels and 1713 down by \a yPixels pixels. Both may be negative. 1714 1715 \warning You might find that QScrollView offers a higher-level of 1716 functionality than using QtTableView and this function. 1717 1718 This function is \e not the same as QWidget::scroll(); in particular, 1719 the signs of \a xPixels and \a yPixels have the reverse semantics. 1720 1721 \sa setXOffset(), setYOffset(), setOffset(), setTopCell(), 1722 setLeftCell() 1723 */ 1724 1725 void QtTableView::scroll(int xPixels, int yPixels) 1726 { 1727 QWidget::scroll(-xPixels, -yPixels, contentsRect()); 1728 } 1729 1730 /*! 1731 Returns the leftmost pixel of the table view in \e view 1732 coordinates. This excludes the frame and any header. 1733 1734 \sa maxViewY(), viewWidth(), contentsRect() 1735 */ 1736 1737 int QtTableView::minViewX() const 1738 { 1739 return frameWidth(); 1740 } 1741 1742 /*! 1743 Returns the top pixel of the table view in \e view 1744 coordinates. This excludes the frame and any header. 1745 1746 \sa maxViewX(), viewHeight(), contentsRect() 1747 */ 1748 1749 int QtTableView::minViewY() const 1750 { 1751 return frameWidth(); 1752 } 1753 1754 /*! 1755 Returns the rightmost pixel of the table view in \e view 1756 coordinates. This excludes the frame and any scroll bar, but 1757 includes blank pixels to the right of the visible table data. 1758 1759 \sa maxViewY(), viewWidth(), contentsRect() 1760 */ 1761 1762 int QtTableView::maxViewX() const 1763 { 1764 return width() - 1 - frameWidth() - (tFlags & Tbl_vScrollBar ? VSBEXT : 0); 1765 } 1766 1767 /*! 1768 Returns the bottom pixel of the table view in \e view 1769 coordinates. This excludes the frame and any scroll bar, but 1770 includes blank pixels below the visible table data. 1771 1772 \sa maxViewX(), viewHeight(), contentsRect() 1773 */ 1774 1775 int QtTableView::maxViewY() const 1776 { 1777 return height() - 1 - frameWidth() - (tFlags & Tbl_hScrollBar ? HSBEXT : 0); 1778 } 1779 1780 /*! 1781 Returns the width of the table view, as such, in \e view 1782 coordinates. This does not include any header, scroll bar or frame, 1783 but it does include background pixels to the right of the table data. 1784 1785 \sa minViewX() maxViewX(), viewHeight(), contentsRect() viewRect() 1786 */ 1787 1788 int QtTableView::viewWidth() const 1789 { 1790 return maxViewX() - minViewX() + 1; 1791 } 1792 1793 /*! 1794 Returns the height of the table view, as such, in \e view 1795 coordinates. This does not include any header, scroll bar or frame, 1796 but it does include background pixels below the table data. 1797 1798 \sa minViewY() maxViewY() viewWidth() contentsRect() viewRect() 1799 */ 1800 1801 int QtTableView::viewHeight() const 1802 { 1803 return maxViewY() - minViewY() + 1; 1804 } 1805 1806 void QtTableView::doAutoScrollBars() 1807 { 1808 int viewW = width() - frameWidth() - minViewX(); 1809 int viewH = height() - frameWidth() - minViewY(); 1810 bool vScrollOn = testTableFlags(Tbl_vScrollBar); 1811 bool hScrollOn = testTableFlags(Tbl_hScrollBar); 1812 int w = 0; 1813 int h = 0; 1814 int i; 1815 1816 if (testTableFlags(Tbl_autoHScrollBar)) { 1817 if (cellW) { 1818 w = cellW * nCols; 1819 } else { 1820 i = 0; 1821 while (i < nCols && w <= viewW) 1822 w += cellWidth(i++); 1823 } 1824 if (w > viewW) 1825 hScrollOn = true; 1826 else 1827 hScrollOn = false; 1828 } 1829 1830 if (testTableFlags(Tbl_autoVScrollBar)) { 1831 if (cellH) { 1832 h = cellH * nRows; 1833 } else { 1834 i = 0; 1835 while (i < nRows && h <= viewH) 1836 h += cellHeight(i++); 1837 } 1838 1839 if (h > viewH) 1840 vScrollOn = true; 1841 else 1842 vScrollOn = false; 1843 } 1844 1845 if (testTableFlags(Tbl_autoHScrollBar) && vScrollOn && !hScrollOn) 1846 if (w > viewW - VSBEXT) 1847 hScrollOn = true; 1848 1849 if (testTableFlags(Tbl_autoVScrollBar) && hScrollOn && !vScrollOn) 1850 if (h > viewH - HSBEXT) 1851 vScrollOn = true; 1852 1853 setHorScrollBar(hScrollOn, false); 1854 setVerScrollBar(vScrollOn, false); 1855 updateFrameSize(); 1856 } 1857 1858 /*! 1859 \fn void QtTableView::updateScrollBars() 1860 1861 Updates the scroll bars' contents and presence to match the table's 1862 state. Generally, you should not need to call this. 1863 1864 \sa setTableFlags() 1865 */ 1866 1867 /*! 1868 Updates the scroll bars' contents and presence to match the table's 1869 state \c or \a f. 1870 1871 \sa setTableFlags() 1872 */ 1873 1874 void QtTableView::updateScrollBars(uint f) 1875 { 1876 sbDirty = sbDirty | f; 1877 if (inSbUpdate) 1878 return; 1879 inSbUpdate = true; 1880 1881 if (testTableFlags(Tbl_autoHScrollBar) && (sbDirty & horRange) || testTableFlags(Tbl_autoVScrollBar) && (sbDirty & verRange)) 1882 // if range change and auto 1883 doAutoScrollBars(); // turn scroll bars on/off if needed 1884 1885 if (!autoUpdate()) { 1886 inSbUpdate = false; 1887 return; 1888 } 1889 if (yOffset() > 0 && testTableFlags(Tbl_autoVScrollBar) && !testTableFlags(Tbl_vScrollBar)) { 1890 setYOffset(0); 1891 } 1892 if (xOffset() > 0 && testTableFlags(Tbl_autoHScrollBar) && !testTableFlags(Tbl_hScrollBar)) { 1893 setXOffset(0); 1894 } 1895 if (!isVisible()) { 1896 inSbUpdate = false; 1897 return; 1898 } 1899 1900 if (testTableFlags(Tbl_hScrollBar) && (sbDirty & horMask) != 0) { 1901 if (sbDirty & horGeometry) 1902 hScrollBar->setGeometry(0, height() - HSBEXT, viewWidth() + frameWidth() * 2, HSBEXT); 1903 1904 if (sbDirty & horSteps) { 1905 if (cellW) 1906 hScrollBar->setSingleStep(qMin((int)cellW, viewWidth() / 2)); 1907 else 1908 hScrollBar->setSingleStep(16); 1909 1910 hScrollBar->setPageStep(viewWidth()); 1911 } 1912 1913 if (sbDirty & horRange) 1914 hScrollBar->setRange(0, maxXOffset()); 1915 1916 if (sbDirty & horValue) 1917 hScrollBar->setValue(xOffs); 1918 1919 // show scrollbar only when it has a sane geometry 1920 if (!hScrollBar->isVisible()) 1921 hScrollBar->show(); 1922 } 1923 1924 if (testTableFlags(Tbl_vScrollBar) && (sbDirty & verMask) != 0) { 1925 if (sbDirty & verGeometry) 1926 vScrollBar->setGeometry(width() - VSBEXT, 0, VSBEXT, viewHeight() + frameWidth() * 2); 1927 1928 if (sbDirty & verSteps) { 1929 if (cellH) 1930 vScrollBar->setSingleStep(qMin((int)cellH, viewHeight() / 2)); 1931 else 1932 vScrollBar->setSingleStep(16); // fttb! ### 1933 1934 vScrollBar->setPageStep(viewHeight()); 1935 } 1936 1937 if (sbDirty & verRange) 1938 vScrollBar->setRange(0, maxYOffset()); 1939 1940 if (sbDirty & verValue) 1941 vScrollBar->setValue(yOffs); 1942 1943 // show scrollbar only when it has a sane geometry 1944 if (!vScrollBar->isVisible()) 1945 vScrollBar->show(); 1946 } 1947 if (coveringCornerSquare && ((sbDirty & verGeometry) || (sbDirty & horGeometry))) 1948 cornerSquare->move(maxViewX() + frameWidth() + 1, maxViewY() + frameWidth() + 1); 1949 1950 sbDirty = 0; 1951 inSbUpdate = false; 1952 } 1953 1954 void QtTableView::updateFrameSize() 1955 { 1956 int rw = width() - (testTableFlags(Tbl_vScrollBar) ? VSBEXT : 0); 1957 int rh = height() - (testTableFlags(Tbl_hScrollBar) ? HSBEXT : 0); 1958 if (rw < 0) 1959 rw = 0; 1960 if (rh < 0) 1961 rh = 0; 1962 1963 if (autoUpdate()) { 1964 int fh = frameRect().height(); 1965 int fw = frameRect().width(); 1966 setFrameRect(QRect(0, 0, rw, rh)); 1967 1968 if (rw != fw) 1969 update(qMin(fw, rw) - frameWidth() - 2, 0, frameWidth() + 4, rh); 1970 if (rh != fh) 1971 update(0, qMin(fh, rh) - frameWidth() - 2, rw, frameWidth() + 4); 1972 } 1973 } 1974 1975 /*! 1976 Returns the maximum horizontal offset within the table of the 1977 view's left edge in \e table coordinates. 1978 1979 This is used mainly to set the horizontal scroll bar's range. 1980 1981 \sa maxColOffset(), maxYOffset(), totalWidth() 1982 */ 1983 1984 int QtTableView::maxXOffset() 1985 { 1986 int tw = totalWidth(); 1987 int maxOffs; 1988 if (testTableFlags(Tbl_scrollLastHCell)) { 1989 if (nCols != 1) 1990 maxOffs = tw - (cellW ? cellW : cellWidth(nCols - 1)); 1991 else 1992 maxOffs = tw - viewWidth(); 1993 } else { 1994 if (testTableFlags(Tbl_snapToHGrid)) { 1995 if (cellW) { 1996 maxOffs = tw - (viewWidth() / cellW) * cellW; 1997 } else { 1998 int goal = tw - viewWidth(); 1999 int pos = tw; 2000 int nextCol = nCols - 1; 2001 int nextCellWidth = cellWidth(nextCol); 2002 while (nextCol > 0 && pos > goal + nextCellWidth) { 2003 pos -= nextCellWidth; 2004 nextCellWidth = cellWidth(--nextCol); 2005 } 2006 if (goal + nextCellWidth == pos) 2007 maxOffs = goal; 2008 else if (goal < pos) 2009 maxOffs = pos; 2010 else 2011 maxOffs = 0; 2012 } 2013 } else { 2014 maxOffs = tw - viewWidth(); 2015 } 2016 } 2017 return maxOffs > 0 ? maxOffs : 0; 2018 } 2019 2020 /*! 2021 Returns the maximum vertical offset within the table of the 2022 view's top edge in \e table coordinates. 2023 2024 This is used mainly to set the vertical scroll bar's range. 2025 2026 \sa maxRowOffset(), maxXOffset(), totalHeight() 2027 */ 2028 2029 int QtTableView::maxYOffset() 2030 { 2031 int th = totalHeight(); 2032 int maxOffs; 2033 if (testTableFlags(Tbl_scrollLastVCell)) { 2034 if (nRows != 1) 2035 maxOffs = th - (cellH ? cellH : cellHeight(nRows - 1)); 2036 else 2037 maxOffs = th - viewHeight(); 2038 } else { 2039 if (testTableFlags(Tbl_snapToVGrid)) { 2040 if (cellH) { 2041 maxOffs = th - (viewHeight() / cellH) * cellH; 2042 } else { 2043 int goal = th - viewHeight(); 2044 int pos = th; 2045 int nextRow = nRows - 1; 2046 int nextCellHeight = cellHeight(nextRow); 2047 while (nextRow > 0 && pos > goal + nextCellHeight) { 2048 pos -= nextCellHeight; 2049 nextCellHeight = cellHeight(--nextRow); 2050 } 2051 if (goal + nextCellHeight == pos) 2052 maxOffs = goal; 2053 else if (goal < pos) 2054 maxOffs = pos; 2055 else 2056 maxOffs = 0; 2057 } 2058 } else { 2059 maxOffs = th - viewHeight(); 2060 } 2061 } 2062 return maxOffs > 0 ? maxOffs : 0; 2063 } 2064 2065 /*! 2066 Returns the index of the last column, which may be at the left edge 2067 of the view. 2068 2069 Depending on the \link setTableFlags() Tbl_scrollLastHCell\endlink flag, 2070 this may or may not be the last column. 2071 2072 \sa maxXOffset(), maxRowOffset() 2073 */ 2074 2075 int QtTableView::maxColOffset() 2076 { 2077 int mx = maxXOffset(); 2078 if (cellW) 2079 return mx / cellW; 2080 else { 2081 int xcd = 0, col = 0; 2082 while (col < nCols && mx > (xcd = cellWidth(col))) { 2083 mx -= xcd; 2084 col++; 2085 } 2086 return col; 2087 } 2088 } 2089 2090 /*! 2091 Returns the index of the last row, which may be at the top edge of 2092 the view. 2093 2094 Depending on the \link setTableFlags() Tbl_scrollLastVCell\endlink flag, 2095 this may or may not be the last row. 2096 2097 \sa maxYOffset(), maxColOffset() 2098 */ 2099 2100 int QtTableView::maxRowOffset() 2101 { 2102 int my = maxYOffset(); 2103 if (cellH) 2104 return my / cellH; 2105 else { 2106 int ycd = 0, row = 0; 2107 while (row < nRows && my > (ycd = cellHeight(row))) { 2108 my -= ycd; 2109 row++; 2110 } 2111 return row; 2112 } 2113 } 2114 2115 void QtTableView::showOrHideScrollBars() 2116 { 2117 if (!autoUpdate()) 2118 return; 2119 if (vScrollBar) { 2120 if (testTableFlags(Tbl_vScrollBar)) { 2121 if (!vScrollBar->isVisible()) 2122 sbDirty = sbDirty | verMask; 2123 } else { 2124 if (vScrollBar->isVisible()) 2125 vScrollBar->hide(); 2126 } 2127 } 2128 if (hScrollBar) { 2129 if (testTableFlags(Tbl_hScrollBar)) { 2130 if (!hScrollBar->isVisible()) 2131 sbDirty = sbDirty | horMask; 2132 } else { 2133 if (hScrollBar->isVisible()) 2134 hScrollBar->hide(); 2135 } 2136 } 2137 if (cornerSquare) { 2138 if (testTableFlags(Tbl_hScrollBar) && testTableFlags(Tbl_vScrollBar)) { 2139 if (!cornerSquare->isVisible()) 2140 cornerSquare->show(); 2141 } else { 2142 if (cornerSquare->isVisible()) 2143 cornerSquare->hide(); 2144 } 2145 } 2146 } 2147 2148 /*! 2149 Updates the scroll bars and internal state. 2150 2151 Call this function when the table view's total size is changed; 2152 typically because the result of cellHeight() or cellWidth() have changed. 2153 2154 This function does not repaint the widget. 2155 */ 2156 2157 void QtTableView::updateTableSize() 2158 { 2159 bool updateOn = autoUpdate(); 2160 setAutoUpdate(false); 2161 int xofs = xOffset(); 2162 xOffs++; // so that setOffset will not return immediately 2163 setOffset(xofs, yOffset(), false); // to calculate internal state correctly 2164 setAutoUpdate(updateOn); 2165 2166 updateScrollBars(horSteps | horRange | verSteps | verRange); 2167 showOrHideScrollBars(); 2168 }