1 /**********************************************************************
2 ** $Id: qttableview.C,v 1.7 2005/04/26 10:30:22 leeming Exp $
4 ** Implementation of QtTableView class
8 ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
10 ** This file contains a class moved out of the Qt GUI Toolkit API. It
11 ** may be used, distributed and modified without limitation.
13 **********************************************************************/
17 #include "qttableview.h"
18 #ifndef QT_NO_QTTABLEVIEW
19 #include "qscrollbar.h"
26 /* Added by J. Levon for compilation with Qt 2.3.1 */
28 #define Q_CHECK_PTR CHECK_PTR
31 #define Q_ASSERT ASSERT
34 enum ScrollBarDirtyFlags {
48 #define HSBEXT horizontalScrollBar()->sizeHint().height()
49 #define VSBEXT verticalScrollBar()->sizeHint().width()
52 class QCornerSquare : public QWidget // internal class
55 QCornerSquare( QWidget *, const char* = 0 );
56 void paintEvent( QPaintEvent * );
59 QCornerSquare::QCornerSquare( QWidget *parent, const char *name )
60 : QWidget( parent, name )
64 void QCornerSquare::paintEvent( QPaintEvent * )
71 \class QtTableView qttableview.h
72 \brief The QtTableView class provides an abstract base for tables.
76 A table view consists of a number of abstract cells organized in rows
77 and columns, and a visible part called a view. The cells are identified
78 with a row index and a column index. The top-left cell is in row 0,
81 The behavior of the widget can be finely tuned using
82 setTableFlags(); a typical subclass will consist of little more than a
83 call to setTableFlags(), some table content manipulation and an
84 implementation of paintCell(). Subclasses that need cells with
85 variable width or height must reimplement cellHeight() and/or
86 cellWidth(). Use updateTableSize() to tell QtTableView when the
87 width or height has changed.
89 When you read this documentation, it is important to understand the
90 distinctions among the four pixel coordinate systems involved.
93 \i The \e cell coordinates. (0,0) is the top-left corner of a cell.
94 Cell coordinates are used by functions such as paintCell().
96 \i The \e table coordinates. (0,0) is the top-left corner of the cell at
97 row 0 and column 0. These coordinates are absolute; that is, they are
98 independent of what part of the table is visible at the moment. They are
99 used by functions such as setXOffset() or maxYOffset().
101 \i The \e widget coordinates. (0,0) is the top-left corner of the widget,
102 \e including the frame. They are used by functions such as repaint().
104 \i The \e view coordinates. (0,0) is the top-left corner of the view, \e
105 excluding the frame. This is the least-used coordinate system; it is used by
106 functions such as viewWidth(). \endlist
108 It is rather unfortunate that we have to use four different
109 coordinate systems, but there was no alternative to provide a flexible and
112 Note: The row,column indices are always given in that order,
113 i.e., first the vertical (row), then the horizontal (column). This is
114 the opposite order of all pixel operations, which take first the
115 horizontal (x) and then the vertical (y).
117 <img src=qtablevw-m.png> <img src=qtablevw-w.png>
119 \warning the functions setNumRows(), setNumCols(), setCellHeight(),
120 setCellWidth(), setTableFlags() and clearTableFlags() may cause
121 virtual functions such as cellWidth() and cellHeight() to be called,
122 even if autoUpdate() is FALSE. This may cause errors if relevant
123 state variables are not initialized.
125 \warning Experience has shown that use of this widget tends to cause
126 more bugs than expected and our analysis indicates that the widget's
127 very flexibility is the problem. If QScrollView or QListBox can
128 easily be made to do the job you need, we recommend subclassing
129 those widgets rather than QtTableView. In addition, QScrollView makes
130 it easy to have child widgets inside tables, which QtTableView
131 doesn't support at all.
134 \link guibooks.html#fowler GUI Design Handbook: Table\endlink
139 Constructs a table view. The \a parent, \a name and \f arguments
140 are passed to the QFrame constructor.
142 The \link setTableFlags() table flags\endlink are all cleared (set to 0).
143 Set \c Tbl_autoVScrollBar or \c Tbl_autoHScrollBar to get automatic scroll
144 bars and \c Tbl_clipCellPainting to get safe clipping.
146 The \link setCellHeight() cell height\endlink and \link setCellWidth()
147 cell width\endlink are set to 0.
149 Frame line shapes (QFrame::HLink and QFrame::VLine) are disallowed;
150 see QFrame::setFrameStyle().
152 Note that the \a f argument is \e not \link setTableFlags() table
153 flags \endlink but rather \link QWidget::QWidget() widget
158 QtTableView::QtTableView( QWidget *parent, const char *name, WFlags f )
159 : QFrame( parent, name, f )
161 nRows = nCols = 0; // zero rows/cols
162 xCellOffs = yCellOffs = 0; // zero offset
163 xCellDelta = yCellDelta = 0; // zero cell offset
164 xOffs = yOffs = 0; // zero total pixel offset
165 cellH = cellW = 0; // user defined cell size
167 vScrollBar = hScrollBar = 0; // no scroll bars
170 eraseInPaint = FALSE;
172 verSnappingOff = FALSE;
174 horSnappingOff = FALSE;
175 coveringCornerSquare = FALSE;
180 Destroys the table view.
183 QtTableView::~QtTableView()
193 Reimplements QWidget::setBackgroundColor() for binary compatibility.
197 void QtTableView::setBackgroundColor( const QColor &c )
199 QWidget::setBackgroundColor( c );
205 void QtTableView::setPalette( const QPalette &p )
207 QWidget::setPalette( p );
213 void QtTableView::show()
215 showOrHideScrollBars();
221 \overload void QtTableView::repaint( bool erase )
222 Repaints the entire view.
226 Repaints the table view directly by calling paintEvent() directly
227 unless updates are disabled.
229 Erases the view area \a (x,y,w,h) if \a erase is TRUE. Parameters \a
230 (x,y) are in \e widget coordinates.
232 If \a w is negative, it is replaced with <code>width() - x</code>.
233 If \a h is negative, it is replaced with <code>height() - y</code>.
235 Doing a repaint() usually is faster than doing an update(), but
236 calling update() many times in a row will generate a single paint
239 At present, QtTableView is the only widget that reimplements \link
240 QWidget::repaint() repaint()\endlink. It does this because by
241 clearing and then repainting one cell at at time, it can make the
242 screen flicker less than it would otherwise. */
244 void QtTableView::repaint( int x, int y, int w, int h, bool erase )
246 if ( !isVisible() || testWState(WState_BlockUpdates) )
252 QRect r( x, y, w, h );
254 return; // nothing to do
256 if ( erase && backgroundMode() != NoBackground )
257 eraseInPaint = TRUE; // erase when painting
259 eraseInPaint = FALSE;
263 \overload void QtTableView::repaint( const QRect &r, bool erase )
264 Replaints rectangle \a r. If \a erase is TRUE draws the background
265 using the palette's background.
270 \fn int QtTableView::numRows() const
271 Returns the number of rows in the table.
272 \sa numCols(), setNumRows()
276 Sets the number of rows of the table to \a rows (must be non-negative).
277 Does not change topCell().
279 The table repaints itself automatically if autoUpdate() is set.
281 \sa numCols(), setNumCols(), numRows()
284 void QtTableView::setNumRows( int rows )
287 #if defined(QT_CHECK_RANGE)
288 qWarning( "QtTableView::setNumRows: (%s) Negative argument %d.",
289 name( "unnamed" ), rows );
296 if ( autoUpdate() && isVisible() ) {
297 int oldLastVisible = lastRowVisible();
298 int oldTopCell = topCell();
300 if ( autoUpdate() && isVisible() &&
301 ( oldLastVisible != lastRowVisible() || oldTopCell != topCell() ) )
302 repaint( oldTopCell != topCell() );
304 // Be more careful - if destructing, bad things might happen.
307 updateScrollBars( verRange );
312 \fn int QtTableView::numCols() const
313 Returns the number of columns in the table.
314 \sa numRows(), setNumCols()
318 Sets the number of columns of the table to \a cols (must be non-negative).
319 Does not change leftCell().
321 The table repaints itself automatically if autoUpdate() is set.
323 \sa numCols(), numRows(), setNumRows()
326 void QtTableView::setNumCols( int cols )
329 #if defined(QT_CHECK_RANGE)
330 qWarning( "QtTableView::setNumCols: (%s) Negative argument %d.",
331 name( "unnamed" ), cols );
339 if ( autoUpdate() && isVisible() ) {
340 int maxCol = lastColVisible();
341 if ( maxCol >= oldCols || maxCol >= nCols )
344 updateScrollBars( horRange );
350 \fn int QtTableView::topCell() const
351 Returns the index of the first row in the table that is visible in
352 the view. The index of the first row is 0.
353 \sa leftCell(), setTopCell()
357 Scrolls the table so that \a row becomes the top row.
358 The index of the very first row is 0.
359 \sa setYOffset(), setTopLeftCell(), setLeftCell()
362 void QtTableView::setTopCell( int row )
364 setTopLeftCell( row, -1 );
369 \fn int QtTableView::leftCell() const
370 Returns the index of the first column in the table that is visible in
371 the view. The index of the very leftmost column is 0.
372 \sa topCell(), setLeftCell()
376 Scrolls the table so that \a col becomes the leftmost
377 column. The index of the leftmost column is 0.
378 \sa setXOffset(), setTopLeftCell(), setTopCell()
381 void QtTableView::setLeftCell( int col )
383 setTopLeftCell( -1, col );
388 Scrolls the table so that the cell at row \a row and colum \a
389 col becomes the top-left cell in the view. The cell at the extreme
390 top left of the table is at position (0,0).
391 \sa setLeftCell(), setTopCell(), setOffset()
394 void QtTableView::setTopLeftCell( int row, int col )
402 if ( newX > maxXOffset() )
407 newX += cellWidth( --col ); // optimize using current! ###
413 if ( newY > maxYOffset() )
418 newY += cellHeight( --row ); // optimize using current! ###
421 setOffset( newX, newY );
426 \fn int QtTableView::xOffset() const
428 Returns the x coordinate in \e table coordinates of the pixel that is
429 currently on the left edge of the view.
431 \sa setXOffset(), yOffset(), leftCell() */
434 Scrolls the table so that \a x becomes the leftmost pixel in the view.
435 The \a x parameter is in \e table coordinates.
437 The interaction with \link setTableFlags() Tbl_snapToHGrid
440 \sa xOffset(), setYOffset(), setOffset(), setLeftCell()
443 void QtTableView::setXOffset( int x )
445 setOffset( x, yOffset() );
449 \fn int QtTableView::yOffset() const
451 Returns the y coordinate in \e table coordinates of the pixel that is
452 currently on the top edge of the view.
454 \sa setYOffset(), xOffset(), topCell()
459 Scrolls the table so that \a y becomes the top pixel in the view.
460 The \a y parameter is in \e table coordinates.
462 The interaction with \link setTableFlags() Tbl_snapToVGrid
465 \sa yOffset(), setXOffset(), setOffset(), setTopCell()
468 void QtTableView::setYOffset( int y )
470 setOffset( xOffset(), y );
474 Scrolls the table so that \a (x,y) becomes the top-left pixel
475 in the view. Parameters \a (x,y) are in \e table coordinates.
477 The interaction with \link setTableFlags() Tbl_snapTo*Grid \endlink
478 is tricky. If \a updateScrBars is TRUE, the scroll bars are
481 \sa xOffset(), yOffset(), setXOffset(), setYOffset(), setTopLeftCell()
484 void QtTableView::setOffset( int x, int y, bool updateScrBars )
486 if ( (!testTableFlags(Tbl_snapToHGrid) || xCellDelta == 0) &&
487 (!testTableFlags(Tbl_snapToVGrid) || yCellDelta == 0) &&
488 (x == xOffs && y == yOffs) )
497 if ( x > maxXOffset() )
499 xCellOffs = x / cellW;
500 if ( !testTableFlags(Tbl_snapToHGrid) ) {
501 xCellDelta = (short)(x % cellW);
507 int xn=0, xcd=0, col = 0;
508 while ( col < nCols-1 && x >= xn+(xcd=cellWidth(col)) ) {
513 if ( testTableFlags(Tbl_snapToHGrid) ) {
517 xCellDelta = (short)(x-xn);
521 if ( y > maxYOffset() )
523 yCellOffs = y / cellH;
524 if ( !testTableFlags(Tbl_snapToVGrid) ) {
525 yCellDelta = (short)(y % cellH);
531 int yn=0, yrd=0, row=0;
532 while ( row < nRows-1 && y >= yn+(yrd=cellHeight(row)) ) {
537 if ( testTableFlags(Tbl_snapToVGrid) ) {
541 yCellDelta = (short)(y-yn);
544 int dx = (x - xOffs);
545 int dy = (y - yOffs);
548 if ( autoUpdate() && isVisible() )
551 updateScrollBars( verValue | horValue );
556 \overload int QtTableView::cellWidth() const
558 Returns the column width in pixels. Returns 0 if the columns have
561 \sa setCellWidth(), cellHeight()
565 Returns the width of column \a col in pixels.
567 This function is virtual and must be reimplemented by subclasses that
568 have variable cell widths. Note that if the total table width
569 changes, updateTableSize() must be called.
571 \sa setCellWidth(), cellHeight(), totalWidth(), updateTableSize()
574 int QtTableView::cellWidth( int )
581 Sets the width in pixels of the table cells to \a cellWidth.
583 Setting it to 0 means that the column width is variable. When
584 set to 0 (this is the default) QtTableView calls the virtual function
585 cellWidth() to get the width.
587 \sa cellWidth(), setCellHeight(), totalWidth(), numCols()
590 void QtTableView::setCellWidth( int cellWidth )
592 if ( cellW == cellWidth )
594 #if defined(QT_CHECK_RANGE)
595 if ( cellWidth < 0 || cellWidth > SHRT_MAX ) {
596 qWarning( "QtTableView::setCellWidth: (%s) Argument out of range (%d)",
597 name( "unnamed" ), cellWidth );
601 cellW = (short)cellWidth;
603 updateScrollBars( horSteps | horRange );
604 if ( autoUpdate() && isVisible() )
610 \overload int QtTableView::cellHeight() const
612 Returns the row height, in pixels. Returns 0 if the rows have
615 \sa setCellHeight(), cellWidth()
620 Returns the height of row \a row in pixels.
622 This function is virtual and must be reimplemented by subclasses that
623 have variable cell heights. Note that if the total table height
624 changes, updateTableSize() must be called.
626 \sa setCellHeight(), cellWidth(), totalHeight()
629 int QtTableView::cellHeight( int )
635 Sets the height in pixels of the table cells to \a cellHeight.
637 Setting it to 0 means that the row height is variable. When set
638 to 0 (this is the default), QtTableView calls the virtual function
639 cellHeight() to get the height.
641 \sa cellHeight(), setCellWidth(), totalHeight(), numRows()
644 void QtTableView::setCellHeight( int cellHeight )
646 if ( cellH == cellHeight )
648 #if defined(QT_CHECK_RANGE)
649 if ( cellHeight < 0 || cellHeight > SHRT_MAX ) {
650 qWarning( "QtTableView::setCellHeight: (%s) Argument out of range (%d)",
651 name( "unnamed" ), cellHeight );
655 cellH = (short)cellHeight;
656 if ( autoUpdate() && isVisible() )
658 updateScrollBars( verSteps | verRange );
663 Returns the total width of the table in pixels.
665 This function is virtual and should be reimplemented by subclasses that
666 have variable cell widths and a non-trivial cellWidth() function, or a
667 large number of columns in the table.
669 The default implementation may be slow for very wide tables.
671 \sa cellWidth(), totalHeight() */
673 int QtTableView::totalWidth()
679 for( int i = 0 ; i < nCols ; i++ )
680 tw += cellWidth( i );
686 Returns the total height of the table in pixels.
688 This function is virtual and should be reimplemented by subclasses that
689 have variable cell heights and a non-trivial cellHeight() function, or a
690 large number of rows in the table.
692 The default implementation may be slow for very tall tables.
694 \sa cellHeight(), totalWidth()
697 int QtTableView::totalHeight()
703 for( int i = 0 ; i < nRows ; i++ )
704 th += cellHeight( i );
711 \fn uint QtTableView::tableFlags() const
713 Returns the union of the table flags that are currently set.
715 \sa setTableFlags(), clearTableFlags(), testTableFlags()
719 \fn bool QtTableView::testTableFlags( uint f ) const
721 Returns TRUE if any of the table flags in \a f are currently set,
724 \sa setTableFlags(), clearTableFlags(), tableFlags()
728 Sets the table flags to \a f.
730 If a flag setting changes the appearance of the table, the table is
731 repainted if - and only if - autoUpdate() is TRUE.
733 The table flags are mostly single bits, though there are some multibit
734 flags for convenience. Here is a complete list:
737 <dt> Tbl_vScrollBar <dd> - The table has a vertical scroll bar.
738 <dt> Tbl_hScrollBar <dd> - The table has a horizontal scroll bar.
739 <dt> Tbl_autoVScrollBar <dd> - The table has a vertical scroll bar if
740 - and only if - the table is taller than the view.
741 <dt> Tbl_autoHScrollBar <dd> The table has a horizontal scroll bar if
742 - and only if - the table is wider than the view.
743 <dt> Tbl_autoScrollBars <dd> - The union of the previous two flags.
744 <dt> Tbl_clipCellPainting <dd> - The table uses QPainter::setClipRect() to
745 make sure that paintCell() will not draw outside the cell
747 <dt> Tbl_cutCellsV <dd> - The table will never show part of a
748 cell at the bottom of the table; if there is not space for all of
749 a cell, the space is left blank.
750 <dt> Tbl_cutCellsH <dd> - The table will never show part of a
751 cell at the right side of the table; if there is not space for all of
752 a cell, the space is left blank.
753 <dt> Tbl_cutCells <dd> - The union of the previous two flags.
754 <dt> Tbl_scrollLastHCell <dd> - When the user scrolls horizontally,
755 let him/her scroll the last cell left until it is at the left
756 edge of the view. If this flag is not set, the user can only scroll
757 to the point where the last cell is completely visible.
758 <dt> Tbl_scrollLastVCell <dd> - When the user scrolls vertically, let
759 him/her scroll the last cell up until it is at the top edge of
760 the view. If this flag is not set, the user can only scroll to the
761 point where the last cell is completely visible.
762 <dt> Tbl_scrollLastCell <dd> - The union of the previous two flags.
763 <dt> Tbl_smoothHScrolling <dd> - The table scrolls as smoothly as
764 possible when the user scrolls horizontally. When this flag is not
765 set, scrolling is done one cell at a time.
766 <dt> Tbl_smoothVScrolling <dd> - The table scrolls as smoothly as
767 possible when scrolling vertically. When this flag is not set,
768 scrolling is done one cell at a time.
769 <dt> Tbl_smoothScrolling <dd> - The union of the previous two flags.
770 <dt> Tbl_snapToHGrid <dd> - Except when the user is actually scrolling,
771 the leftmost column shown snaps to the leftmost edge of the view.
772 <dt> Tbl_snapToVGrid <dd> - Except when the user is actually
773 scrolling, the top row snaps to the top edge of the view.
774 <dt> Tbl_snapToGrid <dd> - The union of the previous two flags.
777 You can specify more than one flag at a time using bitwise OR.
781 setTableFlags( Tbl_smoothScrolling | Tbl_autoScrollBars );
784 \warning The cutCells options (\c Tbl_cutCells, \c Tbl_cutCellsH and
785 Tbl_cutCellsV) may cause painting problems when scrollbars are
786 enabled. Do not combine cutCells and scrollbars.
789 \sa clearTableFlags(), testTableFlags(), tableFlags()
792 void QtTableView::setTableFlags( uint f )
794 f = (f ^ tFlags) & f; // clear flags already set
797 bool updateOn = autoUpdate();
798 setAutoUpdate( FALSE );
800 uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
802 if ( f & Tbl_vScrollBar ) {
803 setVerScrollBar( TRUE );
805 if ( f & Tbl_hScrollBar ) {
806 setHorScrollBar( TRUE );
808 if ( f & Tbl_autoVScrollBar ) {
809 updateScrollBars( verRange );
811 if ( f & Tbl_autoHScrollBar ) {
812 updateScrollBars( horRange );
814 if ( f & Tbl_scrollLastHCell ) {
815 updateScrollBars( horRange );
817 if ( f & Tbl_scrollLastVCell ) {
818 updateScrollBars( verRange );
820 if ( f & Tbl_snapToHGrid ) {
821 updateScrollBars( horRange );
823 if ( f & Tbl_snapToVGrid ) {
824 updateScrollBars( verRange );
826 if ( f & Tbl_snapToGrid ) { // Note: checks for 2 flags
827 if ( (f & Tbl_snapToHGrid) != 0 && xCellDelta != 0 || //have to scroll?
828 (f & Tbl_snapToVGrid) != 0 && yCellDelta != 0 ) {
829 snapToGrid( (f & Tbl_snapToHGrid) != 0, // do snapping
830 (f & Tbl_snapToVGrid) != 0 );
831 repaintMask |= Tbl_snapToGrid; // repaint table
836 setAutoUpdate( TRUE );
838 if ( isVisible() && (f & repaintMask) )
845 Clears the \link setTableFlags() table flags\endlink that are set
848 Example (clears a single flag):
850 clearTableFlags( Tbl_snapToGrid );
853 The default argument clears all flags.
855 \sa setTableFlags(), testTableFlags(), tableFlags()
858 void QtTableView::clearTableFlags( uint f )
860 f = (f ^ ~tFlags) & f; // clear flags that are already 0
863 bool updateOn = autoUpdate();
864 setAutoUpdate( FALSE );
866 uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
868 if ( f & Tbl_vScrollBar ) {
869 setVerScrollBar( FALSE );
871 if ( f & Tbl_hScrollBar ) {
872 setHorScrollBar( FALSE );
874 if ( f & Tbl_scrollLastHCell ) {
875 int maxX = maxXOffset();
876 if ( xOffs > maxX ) {
877 setOffset( maxX, yOffs );
878 repaintMask |= Tbl_scrollLastHCell;
880 updateScrollBars( horRange );
882 if ( f & Tbl_scrollLastVCell ) {
883 int maxY = maxYOffset();
884 if ( yOffs > maxY ) {
885 setOffset( xOffs, maxY );
886 repaintMask |= Tbl_scrollLastVCell;
888 updateScrollBars( verRange );
890 if ( f & Tbl_smoothScrolling ) { // Note: checks for 2 flags
891 if ((f & Tbl_smoothHScrolling) != 0 && xCellDelta != 0 ||//must scroll?
892 (f & Tbl_smoothVScrolling) != 0 && yCellDelta != 0 ) {
893 snapToGrid( (f & Tbl_smoothHScrolling) != 0, // do snapping
894 (f & Tbl_smoothVScrolling) != 0 );
895 repaintMask |= Tbl_smoothScrolling; // repaint table
898 if ( f & Tbl_snapToHGrid ) {
899 updateScrollBars( horRange );
901 if ( f & Tbl_snapToVGrid ) {
902 updateScrollBars( verRange );
905 setAutoUpdate( TRUE );
906 updateScrollBars(); // returns immediately if nothing to do
907 if ( isVisible() && (f & repaintMask) )
915 \fn bool QtTableView::autoUpdate() const
917 Returns TRUE if the view updates itself automatically whenever it
918 is changed in some way.
924 Sets the auto-update option of the table view to \a enable.
926 If \a enable is TRUE (this is the default), the view updates itself
927 automatically whenever it has changed in some way (for example, when a
928 \link setTableFlags() flag\endlink is changed).
930 If \a enable is FALSE, the view does NOT repaint itself or update
931 its internal state variables when it is changed. This can be
932 useful to avoid flicker during large changes and is singularly
933 useless otherwise. Disable auto-update, do the changes, re-enable
934 auto-update and call repaint().
936 \warning Do not leave the view in this state for a long time
937 (i.e., between events). If, for example, the user interacts with the
938 view when auto-update is off, strange things can happen.
940 Setting auto-update to TRUE does not repaint the view; you must call
941 repaint() to do this.
943 \sa autoUpdate(), repaint()
946 void QtTableView::setAutoUpdate( bool enable )
948 if ( isUpdatesEnabled() == enable )
950 setUpdatesEnabled( enable );
952 showOrHideScrollBars();
959 Repaints the cell at row \a row, column \a col if it is inside the view.
961 If \a erase is TRUE, the relevant part of the view is cleared to the
962 background color/pixmap before the contents are repainted.
967 void QtTableView::updateCell( int row, int col, bool erase )
970 if ( !colXPos( col, &xPos ) )
972 if ( !rowYPos( row, &yPos ) )
974 QRect uR = QRect( xPos, yPos,
975 cellW ? cellW : cellWidth(col),
976 cellH ? cellH : cellHeight(row) );
977 repaint( uR.intersect(viewRect()), erase );
982 \fn QRect QtTableView::cellUpdateRect() const
984 This function should be called only from the paintCell() function in
985 subclasses. It returns the portion of a cell that actually needs to be
986 updated in \e cell coordinates. This is useful only for non-trivial
992 Returns the rectangle that is the actual table, excluding any
993 frame, in \e widget coordinates.
996 QRect QtTableView::viewRect() const
998 return QRect( frameWidth(), frameWidth(), viewWidth(), viewHeight() );
1003 Returns the index of the last (bottom) row in the view.
1004 The index of the first row is 0.
1006 If no rows are visible it returns -1. This can happen if the
1007 view is too small for the first row and Tbl_cutCellsV is set.
1009 \sa lastColVisible()
1012 int QtTableView::lastRowVisible() const
1015 int row = findRawRow( maxViewY(), &cellMaxY );
1016 if ( row == -1 || row >= nRows ) { // maxViewY() past end?
1017 row = nRows - 1; // yes: return last row
1019 if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() ) {
1020 if ( row == yCellOffs ) // cut by right margin?
1021 return -1; // yes, nothing in the view
1023 row = row - 1; // cut by margin, one back
1030 Returns the index of the last (right) column in the view.
1031 The index of the first column is 0.
1033 If no columns are visible it returns -1. This can happen if the
1034 view is too narrow for the first column and Tbl_cutCellsH is set.
1036 \sa lastRowVisible()
1039 int QtTableView::lastColVisible() const
1042 int col = findRawCol( maxViewX(), &cellMaxX );
1043 if ( col == -1 || col >= nCols ) { // maxViewX() past end?
1044 col = nCols - 1; // yes: return last col
1046 if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() ) {
1047 if ( col == xCellOffs ) // cut by bottom margin?
1048 return -1; // yes, nothing in the view
1050 col = col - 1; // cell by margin, one back
1057 Returns TRUE if \a row is at least partially visible.
1061 bool QtTableView::rowIsVisible( int row ) const
1063 return rowYPos( row, 0 );
1067 Returns TRUE if \a col is at least partially visible.
1071 bool QtTableView::colIsVisible( int col ) const
1073 return colXPos( col, 0 );
1079 Called when both scroll bars are active at the same time. Covers the
1080 bottom left corner between the two scroll bars with an empty widget.
1083 void QtTableView::coverCornerSquare( bool enable )
1085 coveringCornerSquare = enable;
1086 if ( !cornerSquare && enable ) {
1087 cornerSquare = new QCornerSquare( this );
1088 Q_CHECK_PTR( cornerSquare );
1089 cornerSquare->setGeometry( maxViewX() + frameWidth() + 1,
1090 maxViewY() + frameWidth() + 1,
1094 if ( autoUpdate() && cornerSquare ) {
1096 cornerSquare->show();
1098 cornerSquare->hide();
1105 Scroll the view to a position such that:
1107 If \a horizontal is TRUE, the leftmost column shown fits snugly
1108 with the left edge of the view.
1110 If \a vertical is TRUE, the top row shown fits snugly with the top
1113 You can achieve the same effect automatically by setting any of the
1114 \link setTableFlags() Tbl_snapTo*Grid \endlink table flags.
1117 void QtTableView::snapToGrid( bool horizontal, bool vertical )
1121 if ( horizontal && xCellDelta != 0 ) {
1122 int w = cellW ? cellW : cellWidth( xCellOffs );
1123 if ( xCellDelta >= w/2 )
1124 newXCell = xCellOffs + 1;
1126 newXCell = xCellOffs;
1128 if ( vertical && yCellDelta != 0 ) {
1129 int h = cellH ? cellH : cellHeight( yCellOffs );
1130 if ( yCellDelta >= h/2 )
1131 newYCell = yCellOffs + 1;
1133 newYCell = yCellOffs;
1135 setTopLeftCell( newYCell, newXCell ); //row,column
1140 This internal slot is connected to the horizontal scroll bar's
1141 QScrollBar::valueChanged() signal.
1143 Moves the table horizontally to offset \a val without updating the
1147 void QtTableView::horSbValue( int val )
1151 if ( horSnappingOff ) {
1152 horSnappingOff = FALSE;
1153 tFlags |= Tbl_snapToHGrid;
1156 setOffset( val, yOffs, FALSE );
1161 This internal slot is connected to the horizontal scroll bar's
1162 QScrollBar::sliderMoved() signal.
1164 Scrolls the table smoothly horizontally even if \c Tbl_snapToHGrid is set.
1167 void QtTableView::horSbSliding( int val )
1169 if ( testTableFlags(Tbl_snapToHGrid) &&
1170 testTableFlags(Tbl_smoothHScrolling) ) {
1171 tFlags &= ~Tbl_snapToHGrid; // turn off snapping while sliding
1172 setOffset( val, yOffs, FALSE );
1173 tFlags |= Tbl_snapToHGrid; // turn on snapping again
1175 setOffset( val, yOffs, FALSE );
1181 This internal slot is connected to the horizontal scroll bar's
1182 QScrollBar::sliderReleased() signal.
1185 void QtTableView::horSbSlidingDone( )
1187 if ( testTableFlags(Tbl_snapToHGrid) &&
1188 testTableFlags(Tbl_smoothHScrolling) )
1189 snapToGrid( TRUE, FALSE );
1194 This internal slot is connected to the vertical scroll bar's
1195 QScrollBar::valueChanged() signal.
1197 Moves the table vertically to offset \a val without updating the
1201 void QtTableView::verSbValue( int val )
1205 if ( verSnappingOff ) {
1206 verSnappingOff = FALSE;
1207 tFlags |= Tbl_snapToVGrid;
1210 setOffset( xOffs, val, FALSE );
1215 This internal slot is connected to the vertical scroll bar's
1216 QScrollBar::sliderMoved() signal.
1218 Scrolls the table smoothly vertically even if \c Tbl_snapToVGrid is set.
1221 void QtTableView::verSbSliding( int val )
1223 if ( testTableFlags(Tbl_snapToVGrid) &&
1224 testTableFlags(Tbl_smoothVScrolling) ) {
1225 tFlags &= ~Tbl_snapToVGrid; // turn off snapping while sliding
1226 setOffset( xOffs, val, FALSE );
1227 tFlags |= Tbl_snapToVGrid; // turn on snapping again
1229 setOffset( xOffs, val, FALSE );
1235 This internal slot is connected to the vertical scroll bar's
1236 QScrollBar::sliderReleased() signal.
1239 void QtTableView::verSbSlidingDone( )
1241 if ( testTableFlags(Tbl_snapToVGrid) &&
1242 testTableFlags(Tbl_smoothVScrolling) )
1243 snapToGrid( FALSE, TRUE );
1248 This virtual function is called before painting of table cells
1249 is started. It can be reimplemented by subclasses that want to
1250 to set up the painter in a special way and that do not want to
1251 do so for each cell.
1254 void QtTableView::setupPainter( QPainter * )
1259 \fn void QtTableView::paintCell( QPainter *p, int row, int col )
1261 This pure virtual function is called to paint the single cell at \a
1262 (row,col) using \a p, which is open when paintCell() is called and
1265 The coordinate system is \link QPainter::translate() translated \endlink
1266 so that the origin is at the top-left corner of the cell to be
1267 painted, i.e. \e cell coordinates. Do not scale or shear the coordinate
1268 system (or if you do, restore the transformation matrix before you
1271 The painter is not clipped by default and for maximum efficiency. For safety,
1272 call setTableFlags(Tbl_clipCellPainting) to enable clipping.
1274 \sa paintEvent(), setTableFlags() */
1278 Handles paint events, \a e, for the table view.
1280 Calls paintCell() for the cells that needs to be repainted.
1283 void QtTableView::paintEvent( QPaintEvent *e )
1285 QRect updateR = e->rect(); // update rectangle
1287 bool e = eraseInPaint;
1292 QPainter paint( this );
1294 if ( !contentsRect().contains( updateR, TRUE ) ) {// update frame ?
1295 drawFrame( &paint );
1296 if ( updateR.left() < frameWidth() ) //###
1297 updateR.setLeft( frameWidth() );
1298 if ( updateR.top() < frameWidth() )
1299 updateR.setTop( frameWidth() );
1302 int maxWX = maxViewX();
1303 int maxWY = maxViewY();
1304 if ( updateR.right() > maxWX )
1305 updateR.setRight( maxWX );
1306 if ( updateR.bottom() > maxWY )
1307 updateR.setBottom( maxWY );
1309 setupPainter( &paint ); // prepare for painting table
1311 int firstRow = findRow( updateR.y() );
1312 int firstCol = findCol( updateR.x() );
1315 if ( !colXPos( firstCol, &xStart ) || !rowYPos( firstRow, &yStart ) ) {
1316 paint.eraseRect( updateR ); // erase area outside cells but in view
1319 int maxX = updateR.right();
1320 int maxY = updateR.bottom();
1324 int xPos = maxX + 1; // in case the while() is empty
1327 QRect winR = viewRect();
1330 #ifndef QT_NO_TRANSFORMATIONS
1334 while ( yPos <= maxY && row < nRows ) {
1335 nextY = yPos + (cellH ? cellH : cellHeight( row ));
1336 if ( testTableFlags( Tbl_cutCellsV ) && nextY > ( maxWY + 1 ) )
1340 while ( xPos <= maxX && col < nCols ) {
1341 nextX = xPos + (cellW ? cellW : cellWidth( col ));
1342 if ( testTableFlags( Tbl_cutCellsH ) && nextX > ( maxWX + 1 ) )
1345 cellR.setRect( xPos, yPos, cellW ? cellW : cellWidth(col),
1346 cellH ? cellH : cellHeight(row) );
1347 cellUR = cellR.intersect( updateR );
1348 if ( cellUR.isValid() ) {
1349 cellUpdateR = cellUR;
1350 cellUpdateR.moveBy( -xPos, -yPos ); // cell coordinates
1352 paint.eraseRect( cellUR );
1354 #ifndef QT_NO_TRANSFORMATIONS
1355 matrix.translate( xPos, yPos );
1356 paint.setWorldMatrix( matrix );
1357 if ( testTableFlags(Tbl_clipCellPainting) ||
1358 frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1359 paint.setClipRect( cellUR );
1360 paintCell( &paint, row, col );
1361 paint.setClipping( FALSE );
1363 paintCell( &paint, row, col );
1366 paint.setWorldMatrix( matrix );
1368 paint.translate( xPos, yPos );
1369 if ( testTableFlags(Tbl_clipCellPainting) ||
1370 frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1371 paint.setClipRect( cellUR );
1372 paintCell( &paint, row, col );
1373 paint.setClipping( FALSE );
1375 paintCell( &paint, row, col );
1377 paint.translate( -xPos, -yPos );
1387 // while painting we have to erase any areas in the view that
1388 // are not covered by cells but are covered by the paint event
1389 // rectangle these must be erased. We know that xPos is the last
1390 // x pixel updated + 1 and that yPos is the last y pixel updated + 1.
1392 // Note that this needs to be done regardless whether we do
1393 // eraseInPaint or not. Reason: a subclass may implement
1394 // flicker-freeness and encourage the use of repaint(FALSE).
1395 // The subclass, however, cannot draw all pixels, just those
1396 // inside the cells. So QtTableView is reponsible for all pixels
1397 // outside the cells.
1399 QRect viewR = viewRect();
1400 const QColorGroup g = colorGroup();
1402 if ( xPos <= maxX ) {
1405 r.setBottom( yPos<maxY?yPos:maxY );
1406 if ( inherits( "QMultiLineEdit" ) )
1407 paint.fillRect( r.intersect( updateR ), g.base() );
1409 paint.eraseRect( r.intersect( updateR ) );
1411 if ( yPos <= maxY ) {
1414 if ( inherits( "QMultiLineEdit" ) )
1415 paint.fillRect( r.intersect( updateR ), g.base() );
1417 paint.eraseRect( r.intersect( updateR ) );
1423 void QtTableView::resizeEvent( QResizeEvent * )
1425 updateScrollBars( horValue | verValue | horSteps | horGeometry | horRange |
1426 verSteps | verGeometry | verRange );
1427 showOrHideScrollBars();
1429 int maxX = QMIN( xOffs, maxXOffset() ); // ### can be slow
1430 int maxY = QMIN( yOffs, maxYOffset() );
1431 setOffset( maxX, maxY );
1436 Redraws all visible cells in the table view.
1439 void QtTableView::updateView()
1441 repaint( viewRect() );
1445 Returns a pointer to the vertical scroll bar mainly so you can
1446 connect() to its signals. Note that the scroll bar works in pixel
1447 values; use findRow() to translate to cell numbers.
1450 QScrollBar *QtTableView::verticalScrollBar() const
1452 QtTableView *that = (QtTableView*)this; // semantic const
1453 if ( !vScrollBar ) {
1454 QScrollBar *sb = new QScrollBar( QScrollBar::Vertical, that );
1455 #ifndef QT_NO_CURSOR
1456 sb->setCursor( arrowCursor );
1458 sb->resize( sb->sizeHint() ); // height is irrelevant
1460 sb->setTracking( FALSE );
1461 sb->setFocusPolicy( NoFocus );
1462 connect( sb, SIGNAL(valueChanged(int)),
1463 SLOT(verSbValue(int)));
1464 connect( sb, SIGNAL(sliderMoved(int)),
1465 SLOT(verSbSliding(int)));
1466 connect( sb, SIGNAL(sliderReleased()),
1467 SLOT(verSbSlidingDone()));
1469 that->vScrollBar = sb;
1476 Returns a pointer to the horizontal scroll bar mainly so you can
1477 connect() to its signals. Note that the scroll bar works in pixel
1478 values; use findCol() to translate to cell numbers.
1481 QScrollBar *QtTableView::horizontalScrollBar() const
1483 QtTableView *that = (QtTableView*)this; // semantic const
1484 if ( !hScrollBar ) {
1485 QScrollBar *sb = new QScrollBar( QScrollBar::Horizontal, that );
1486 #ifndef QT_NO_CURSOR
1487 sb->setCursor( arrowCursor );
1489 sb->resize( sb->sizeHint() ); // width is irrelevant
1490 sb->setFocusPolicy( NoFocus );
1492 sb->setTracking( FALSE );
1493 connect( sb, SIGNAL(valueChanged(int)),
1494 SLOT(horSbValue(int)));
1495 connect( sb, SIGNAL(sliderMoved(int)),
1496 SLOT(horSbSliding(int)));
1497 connect( sb, SIGNAL(sliderReleased()),
1498 SLOT(horSbSlidingDone()));
1500 that->hScrollBar = sb;
1507 Enables or disables the horizontal scroll bar, as required by
1508 setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1511 void QtTableView::setHorScrollBar( bool on, bool update )
1514 tFlags |= Tbl_hScrollBar;
1515 horizontalScrollBar(); // created
1517 updateScrollBars( horMask | verMask );
1519 sbDirty = sbDirty | (horMask | verMask);
1520 if ( testTableFlags( Tbl_vScrollBar ) )
1521 coverCornerSquare( TRUE );
1523 sbDirty = sbDirty | horMask;
1525 tFlags &= ~Tbl_hScrollBar;
1528 coverCornerSquare( FALSE );
1529 bool hideScrollBar = autoUpdate() && hScrollBar->isVisible();
1530 if ( hideScrollBar )
1533 updateScrollBars( verMask );
1535 sbDirty = sbDirty | verMask;
1536 if ( hideScrollBar && isVisible() )
1537 repaint( hScrollBar->x(), hScrollBar->y(),
1538 width() - hScrollBar->x(), hScrollBar->height() );
1546 Enables or disables the vertical scroll bar, as required by
1547 setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1550 void QtTableView::setVerScrollBar( bool on, bool update )
1553 tFlags |= Tbl_vScrollBar;
1554 verticalScrollBar(); // created
1556 updateScrollBars( verMask | horMask );
1558 sbDirty = sbDirty | (horMask | verMask);
1559 if ( testTableFlags( Tbl_hScrollBar ) )
1560 coverCornerSquare( TRUE );
1562 sbDirty = sbDirty | verMask;
1564 tFlags &= ~Tbl_vScrollBar;
1567 coverCornerSquare( FALSE );
1568 bool hideScrollBar = autoUpdate() && vScrollBar->isVisible();
1569 if ( hideScrollBar )
1572 updateScrollBars( horMask );
1574 sbDirty = sbDirty | horMask;
1575 if ( hideScrollBar && isVisible() )
1576 repaint( vScrollBar->x(), vScrollBar->y(),
1577 vScrollBar->width(), height() - vScrollBar->y() );
1586 int QtTableView::findRawRow( int yPos, int *cellMaxY, int *cellMinY,
1587 bool goOutsideView ) const
1592 if ( goOutsideView || yPos >= minViewY() && yPos <= maxViewY() ) {
1593 if ( yPos < minViewY() ) {
1594 #if defined(QT_CHECK_RANGE)
1595 qWarning( "QtTableView::findRawRow: (%s) internal error: "
1596 "yPos < minViewY() && goOutsideView "
1597 "not supported. (%d,%d)",
1598 name( "unnamed" ), yPos, yOffs );
1602 if ( cellH ) { // uniform cell height
1603 r = (yPos - minViewY() + yCellDelta)/cellH; // cell offs from top
1605 *cellMaxY = (r + 1)*cellH + minViewY() - yCellDelta - 1;
1607 *cellMinY = r*cellH + minViewY() - yCellDelta;
1608 r += yCellOffs; // absolute cell index
1609 } else { // variable cell height
1610 QtTableView *tw = (QtTableView *)this;
1612 int h = minViewY() - yCellDelta; //##arnt3
1614 Q_ASSERT( r < nRows );
1615 while ( r < nRows ) {
1617 h += tw->cellHeight( r ); // Start of next cell
1633 int QtTableView::findRawCol( int xPos, int *cellMaxX, int *cellMinX ,
1634 bool goOutsideView ) const
1639 if ( goOutsideView || xPos >= minViewX() && xPos <= maxViewX() ) {
1640 if ( xPos < minViewX() ) {
1641 #if defined(QT_CHECK_RANGE)
1642 qWarning( "QtTableView::findRawCol: (%s) internal error: "
1643 "xPos < minViewX() && goOutsideView "
1644 "not supported. (%d,%d)",
1645 name( "unnamed" ), xPos, xOffs );
1649 if ( cellW ) { // uniform cell width
1650 c = (xPos - minViewX() + xCellDelta)/cellW; //cell offs from left
1652 *cellMaxX = (c + 1)*cellW + minViewX() - xCellDelta - 1;
1654 *cellMinX = c*cellW + minViewX() - xCellDelta;
1655 c += xCellOffs; // absolute cell index
1656 } else { // variable cell width
1657 QtTableView *tw = (QtTableView *)this;
1659 int w = minViewX() - xCellDelta; //##arnt3
1661 Q_ASSERT( c < nCols );
1662 while ( c < nCols ) {
1664 w += tw->cellWidth( c ); // Start of next cell
1680 Returns the index of the row at position \a yPos, where \a yPos is in
1681 \e widget coordinates. Returns -1 if \a yPos is outside the valid
1684 \sa findCol(), rowYPos()
1687 int QtTableView::findRow( int yPos ) const
1690 int row = findRawRow( yPos, &cellMaxY );
1691 if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() )
1692 row = - 1; // cell cut by bottom margin
1700 Returns the index of the column at position \a xPos, where \a xPos is
1701 in \e widget coordinates. Returns -1 if \a xPos is outside the valid
1704 \sa findRow(), colXPos()
1707 int QtTableView::findCol( int xPos ) const
1710 int col = findRawCol( xPos, &cellMaxX );
1711 if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() )
1712 col = - 1; // cell cut by right margin
1720 Computes the position in the widget of row \a row.
1722 Returns TRUE and stores the result in \a *yPos (in \e widget
1723 coordinates) if the row is visible. Returns FALSE and does not modify
1724 \a *yPos if \a row is invisible or invalid.
1726 \sa colXPos(), findRow()
1729 bool QtTableView::rowYPos( int row, int *yPos ) const
1732 if ( row >= yCellOffs ) {
1734 int lastVisible = lastRowVisible();
1735 if ( row > lastVisible || lastVisible == -1 )
1737 y = (row - yCellOffs)*cellH + minViewY() - yCellDelta;
1740 y = minViewY() - yCellDelta; // y of leftmost cell in view
1742 QtTableView *tw = (QtTableView *)this;
1743 int maxY = maxViewY();
1744 while ( r < row && y <= maxY )
1745 y += tw->cellHeight( r++ );
1760 Computes the position in the widget of column \a col.
1762 Returns TRUE and stores the result in \a *xPos (in \e widget
1763 coordinates) if the column is visible. Returns FALSE and does not
1764 modify \a *xPos if \a col is invisible or invalid.
1766 \sa rowYPos(), findCol()
1769 bool QtTableView::colXPos( int col, int *xPos ) const
1772 if ( col >= xCellOffs ) {
1774 int lastVisible = lastColVisible();
1775 if ( col > lastVisible || lastVisible == -1 )
1777 x = (col - xCellOffs)*cellW + minViewX() - xCellDelta;
1780 x = minViewX() - xCellDelta; // x of uppermost cell in view
1782 QtTableView *tw = (QtTableView *)this;
1783 int maxX = maxViewX();
1784 while ( c < col && x <= maxX )
1785 x += tw->cellWidth( c++ );
1799 Moves the visible area of the table right by \a xPixels and
1800 down by \a yPixels pixels. Both may be negative.
1802 \warning You might find that QScrollView offers a higher-level of
1803 functionality than using QtTableView and this function.
1805 This function is \e not the same as QWidget::scroll(); in particular,
1806 the signs of \a xPixels and \a yPixels have the reverse semantics.
1808 \sa setXOffset(), setYOffset(), setOffset(), setTopCell(),
1812 void QtTableView::scroll( int xPixels, int yPixels )
1814 QWidget::scroll( -xPixels, -yPixels, contentsRect() );
1819 Returns the leftmost pixel of the table view in \e view
1820 coordinates. This excludes the frame and any header.
1822 \sa maxViewY(), viewWidth(), contentsRect()
1825 int QtTableView::minViewX() const
1827 return frameWidth();
1832 Returns the top pixel of the table view in \e view
1833 coordinates. This excludes the frame and any header.
1835 \sa maxViewX(), viewHeight(), contentsRect()
1838 int QtTableView::minViewY() const
1840 return frameWidth();
1845 Returns the rightmost pixel of the table view in \e view
1846 coordinates. This excludes the frame and any scroll bar, but
1847 includes blank pixels to the right of the visible table data.
1849 \sa maxViewY(), viewWidth(), contentsRect()
1852 int QtTableView::maxViewX() const
1854 return width() - 1 - frameWidth()
1855 - (tFlags & Tbl_vScrollBar ? VSBEXT
1861 Returns the bottom pixel of the table view in \e view
1862 coordinates. This excludes the frame and any scroll bar, but
1863 includes blank pixels below the visible table data.
1865 \sa maxViewX(), viewHeight(), contentsRect()
1868 int QtTableView::maxViewY() const
1870 return height() - 1 - frameWidth()
1871 - (tFlags & Tbl_hScrollBar ? HSBEXT
1877 Returns the width of the table view, as such, in \e view
1878 coordinates. This does not include any header, scroll bar or frame,
1879 but it does include background pixels to the right of the table data.
1881 \sa minViewX() maxViewX(), viewHeight(), contentsRect() viewRect()
1884 int QtTableView::viewWidth() const
1886 return maxViewX() - minViewX() + 1;
1891 Returns the height of the table view, as such, in \e view
1892 coordinates. This does not include any header, scroll bar or frame,
1893 but it does include background pixels below the table data.
1895 \sa minViewY() maxViewY() viewWidth() contentsRect() viewRect()
1898 int QtTableView::viewHeight() const
1900 return maxViewY() - minViewY() + 1;
1904 void QtTableView::doAutoScrollBars()
1906 int viewW = width() - frameWidth() - minViewX();
1907 int viewH = height() - frameWidth() - minViewY();
1908 bool vScrollOn = testTableFlags(Tbl_vScrollBar);
1909 bool hScrollOn = testTableFlags(Tbl_hScrollBar);
1914 if ( testTableFlags(Tbl_autoHScrollBar) ) {
1919 while ( i < nCols && w <= viewW )
1920 w += cellWidth( i++ );
1928 if ( testTableFlags(Tbl_autoVScrollBar) ) {
1933 while ( i < nRows && h <= viewH )
1934 h += cellHeight( i++ );
1943 if ( testTableFlags(Tbl_autoHScrollBar) && vScrollOn && !hScrollOn )
1944 if ( w > viewW - VSBEXT )
1947 if ( testTableFlags(Tbl_autoVScrollBar) && hScrollOn && !vScrollOn )
1948 if ( h > viewH - HSBEXT )
1951 setHorScrollBar( hScrollOn, FALSE );
1952 setVerScrollBar( vScrollOn, FALSE );
1958 \fn void QtTableView::updateScrollBars()
1960 Updates the scroll bars' contents and presence to match the table's
1961 state. Generally, you should not need to call this.
1967 Updates the scroll bars' contents and presence to match the table's
1973 void QtTableView::updateScrollBars( uint f )
1975 sbDirty = sbDirty | f;
1980 if ( testTableFlags(Tbl_autoHScrollBar) && (sbDirty & horRange) ||
1981 testTableFlags(Tbl_autoVScrollBar) && (sbDirty & verRange) )
1982 // if range change and auto
1983 doAutoScrollBars(); // turn scroll bars on/off if needed
1985 if ( !autoUpdate() ) {
1989 if ( yOffset() > 0 && testTableFlags( Tbl_autoVScrollBar ) &&
1990 !testTableFlags( Tbl_vScrollBar ) ) {
1993 if ( xOffset() > 0 && testTableFlags( Tbl_autoHScrollBar ) &&
1994 !testTableFlags( Tbl_hScrollBar ) ) {
1997 if ( !isVisible() ) {
2002 if ( testTableFlags(Tbl_hScrollBar) && (sbDirty & horMask) != 0 ) {
2003 if ( sbDirty & horGeometry )
2004 hScrollBar->setGeometry( 0,height() - HSBEXT,
2005 viewWidth() + frameWidth()*2,
2008 if ( sbDirty & horSteps ) {
2010 hScrollBar->setSteps( QMIN(cellW,viewWidth()/2), viewWidth() );
2012 hScrollBar->setSteps( 16, viewWidth() );
2015 if ( sbDirty & horRange )
2016 hScrollBar->setRange( 0, maxXOffset() );
2018 if ( sbDirty & horValue )
2019 hScrollBar->setValue( xOffs );
2021 // show scrollbar only when it has a sane geometry
2022 if ( !hScrollBar->isVisible() )
2026 if ( testTableFlags(Tbl_vScrollBar) && (sbDirty & verMask) != 0 ) {
2027 if ( sbDirty & verGeometry )
2028 vScrollBar->setGeometry( width() - VSBEXT, 0,
2030 viewHeight() + frameWidth()*2 );
2032 if ( sbDirty & verSteps ) {
2034 vScrollBar->setSteps( QMIN(cellH,viewHeight()/2), viewHeight() );
2036 vScrollBar->setSteps( 16, viewHeight() ); // fttb! ###
2039 if ( sbDirty & verRange )
2040 vScrollBar->setRange( 0, maxYOffset() );
2042 if ( sbDirty & verValue )
2043 vScrollBar->setValue( yOffs );
2045 // show scrollbar only when it has a sane geometry
2046 if ( !vScrollBar->isVisible() )
2049 if ( coveringCornerSquare &&
2050 ( (sbDirty & verGeometry ) || (sbDirty & horGeometry)) )
2051 cornerSquare->move( maxViewX() + frameWidth() + 1,
2052 maxViewY() + frameWidth() + 1 );
2059 void QtTableView::updateFrameSize()
2061 int rw = width() - ( testTableFlags(Tbl_vScrollBar) ?
2063 int rh = height() - ( testTableFlags(Tbl_hScrollBar) ?
2070 if ( autoUpdate() ) {
2071 int fh = frameRect().height();
2072 int fw = frameRect().width();
2073 setFrameRect( QRect(0,0,rw,rh) );
2076 update( QMIN(fw,rw) - frameWidth() - 2, 0, frameWidth()+4, rh );
2078 update( 0, QMIN(fh,rh) - frameWidth() - 2, rw, frameWidth()+4 );
2084 Returns the maximum horizontal offset within the table of the
2085 view's left edge in \e table coordinates.
2087 This is used mainly to set the horizontal scroll bar's range.
2089 \sa maxColOffset(), maxYOffset(), totalWidth()
2092 int QtTableView::maxXOffset()
2094 int tw = totalWidth();
2096 if ( testTableFlags(Tbl_scrollLastHCell) ) {
2098 maxOffs = tw - ( cellW ? cellW : cellWidth( nCols - 1 ) );
2100 maxOffs = tw - viewWidth();
2102 if ( testTableFlags(Tbl_snapToHGrid) ) {
2104 maxOffs = tw - (viewWidth()/cellW)*cellW;
2106 int goal = tw - viewWidth();
2108 int nextCol = nCols - 1;
2109 int nextCellWidth = cellWidth( nextCol );
2110 while ( nextCol > 0 && pos > goal + nextCellWidth ) {
2111 pos -= nextCellWidth;
2112 nextCellWidth = cellWidth( --nextCol );
2114 if ( goal + nextCellWidth == pos )
2116 else if ( goal < pos )
2122 maxOffs = tw - viewWidth();
2125 return maxOffs > 0 ? maxOffs : 0;
2130 Returns the maximum vertical offset within the table of the
2131 view's top edge in \e table coordinates.
2133 This is used mainly to set the vertical scroll bar's range.
2135 \sa maxRowOffset(), maxXOffset(), totalHeight()
2138 int QtTableView::maxYOffset()
2140 int th = totalHeight();
2142 if ( testTableFlags(Tbl_scrollLastVCell) ) {
2144 maxOffs = th - ( cellH ? cellH : cellHeight( nRows - 1 ) );
2146 maxOffs = th - viewHeight();
2148 if ( testTableFlags(Tbl_snapToVGrid) ) {
2150 maxOffs = th - (viewHeight()/cellH)*cellH;
2152 int goal = th - viewHeight();
2154 int nextRow = nRows - 1;
2155 int nextCellHeight = cellHeight( nextRow );
2156 while ( nextRow > 0 && pos > goal + nextCellHeight ) {
2157 pos -= nextCellHeight;
2158 nextCellHeight = cellHeight( --nextRow );
2160 if ( goal + nextCellHeight == pos )
2162 else if ( goal < pos )
2168 maxOffs = th - viewHeight();
2171 return maxOffs > 0 ? maxOffs : 0;
2176 Returns the index of the last column, which may be at the left edge
2179 Depending on the \link setTableFlags() Tbl_scrollLastHCell\endlink flag,
2180 this may or may not be the last column.
2182 \sa maxXOffset(), maxRowOffset()
2185 int QtTableView::maxColOffset()
2187 int mx = maxXOffset();
2192 while ( col < nCols && mx > (xcd=cellWidth(col)) ) {
2202 Returns the index of the last row, which may be at the top edge of
2205 Depending on the \link setTableFlags() Tbl_scrollLastVCell\endlink flag,
2206 this may or may not be the last row.
2208 \sa maxYOffset(), maxColOffset()
2211 int QtTableView::maxRowOffset()
2213 int my = maxYOffset();
2218 while ( row < nRows && my > (ycd=cellHeight(row)) ) {
2227 void QtTableView::showOrHideScrollBars()
2229 if ( !autoUpdate() )
2232 if ( testTableFlags(Tbl_vScrollBar) ) {
2233 if ( !vScrollBar->isVisible() )
2234 sbDirty = sbDirty | verMask;
2236 if ( vScrollBar->isVisible() )
2241 if ( testTableFlags(Tbl_hScrollBar) ) {
2242 if ( !hScrollBar->isVisible() )
2243 sbDirty = sbDirty | horMask;
2245 if ( hScrollBar->isVisible() )
2249 if ( cornerSquare ) {
2250 if ( testTableFlags(Tbl_hScrollBar) &&
2251 testTableFlags(Tbl_vScrollBar) ) {
2252 if ( !cornerSquare->isVisible() )
2253 cornerSquare->show();
2255 if ( cornerSquare->isVisible() )
2256 cornerSquare->hide();
2263 Updates the scroll bars and internal state.
2265 Call this function when the table view's total size is changed;
2266 typically because the result of cellHeight() or cellWidth() have changed.
2268 This function does not repaint the widget.
2271 void QtTableView::updateTableSize()
2273 bool updateOn = autoUpdate();
2274 setAutoUpdate( FALSE );
2275 int xofs = xOffset();
2276 xOffs++; //so that setOffset will not return immediately
2277 setOffset(xofs,yOffset(),FALSE); //to calculate internal state correctly
2278 setAutoUpdate(updateOn);
2280 updateScrollBars( horSteps | horRange |
2281 verSteps | verRange );
2282 showOrHideScrollBars();