1 /**********************************************************************
2 ** $Id: qttableview.cpp,v 1.2 2002/03/09 03:13:15 jwalz 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 **********************************************************************/
15 #include "qttableview.h"
17 #ifndef QT_NO_QTTABLEVIEW
18 #include <qscrollbar.h>
20 #include <qdrawutil.h>
23 enum ScrollBarDirtyFlags {
37 #define HSBEXT horizontalScrollBar()->sizeHint().height()
38 #define VSBEXT verticalScrollBar()->sizeHint().width()
41 class QCornerSquare : public QWidget // internal class
44 QCornerSquare( QWidget *, const char* = 0 );
45 void paintEvent( QPaintEvent * );
48 QCornerSquare::QCornerSquare( QWidget *parent, const char *name )
49 : QWidget( parent, name )
53 void QCornerSquare::paintEvent( QPaintEvent * )
60 \class QtTableView qttableview.h
61 \brief The QtTableView class provides an abstract base for tables.
65 A table view consists of a number of abstract cells organized in rows
66 and columns, and a visible part called a view. The cells are identified
67 with a row index and a column index. The top-left cell is in row 0,
70 The behavior of the widget can be finely tuned using
71 setTableFlags(); a typical subclass will consist of little more than a
72 call to setTableFlags(), some table content manipulation and an
73 implementation of paintCell(). Subclasses that need cells with
74 variable width or height must reimplement cellHeight() and/or
75 cellWidth(). Use updateTableSize() to tell QtTableView when the
76 width or height has changed.
78 When you read this documentation, it is important to understand the
79 distinctions among the four pixel coordinate systems involved.
82 \i The \e cell coordinates. (0,0) is the top-left corner of a cell.
83 Cell coordinates are used by functions such as paintCell().
85 \i The \e table coordinates. (0,0) is the top-left corner of the cell at
86 row 0 and column 0. These coordinates are absolute; that is, they are
87 independent of what part of the table is visible at the moment. They are
88 used by functions such as setXOffset() or maxYOffset().
90 \i The \e widget coordinates. (0,0) is the top-left corner of the widget,
91 \e including the frame. They are used by functions such as repaint().
93 \i The \e view coordinates. (0,0) is the top-left corner of the view, \e
94 excluding the frame. This is the least-used coordinate system; it is used by
95 functions such as viewWidth(). \endlist
97 It is rather unfortunate that we have to use four different
98 coordinate systems, but there was no alternative to provide a flexible and
101 Note: The row,column indices are always given in that order,
102 i.e., first the vertical (row), then the horizontal (column). This is
103 the opposite order of all pixel operations, which take first the
104 horizontal (x) and then the vertical (y).
106 <img src=qtablevw-m.png> <img src=qtablevw-w.png>
108 \warning the functions setNumRows(), setNumCols(), setCellHeight(),
109 setCellWidth(), setTableFlags() and clearTableFlags() may cause
110 virtual functions such as cellWidth() and cellHeight() to be called,
111 even if autoUpdate() is FALSE. This may cause errors if relevant
112 state variables are not initialized.
114 \warning Experience has shown that use of this widget tends to cause
115 more bugs than expected and our analysis indicates that the widget's
116 very flexibility is the problem. If QScrollView or QListBox can
117 easily be made to do the job you need, we recommend subclassing
118 those widgets rather than QtTableView. In addition, QScrollView makes
119 it easy to have child widgets inside tables, which QtTableView
120 doesn't support at all.
123 \link guibooks.html#fowler GUI Design Handbook: Table\endlink
128 Constructs a table view. The \a parent, \a name and \f arguments
129 are passed to the QFrame constructor.
131 The \link setTableFlags() table flags\endlink are all cleared (set to 0).
132 Set \c Tbl_autoVScrollBar or \c Tbl_autoHScrollBar to get automatic scroll
133 bars and \c Tbl_clipCellPainting to get safe clipping.
135 The \link setCellHeight() cell height\endlink and \link setCellWidth()
136 cell width\endlink are set to 0.
138 Frame line shapes (QFrame::HLink and QFrame::VLine) are disallowed;
139 see QFrame::setFrameStyle().
141 Note that the \a f argument is \e not \link setTableFlags() table
142 flags \endlink but rather \link QWidget::QWidget() widget
147 QtTableView::QtTableView( QWidget *parent, const char *name, WFlags f )
148 : QFrame( parent, name, f )
150 nRows = nCols = 0; // zero rows/cols
151 xCellOffs = yCellOffs = 0; // zero offset
152 xCellDelta = yCellDelta = 0; // zero cell offset
153 xOffs = yOffs = 0; // zero total pixel offset
154 cellH = cellW = 0; // user defined cell size
156 vScrollBar = hScrollBar = 0; // no scroll bars
159 eraseInPaint = FALSE;
161 verSnappingOff = FALSE;
163 horSnappingOff = FALSE;
164 coveringCornerSquare = FALSE;
169 Destroys the table view.
172 QtTableView::~QtTableView()
182 Reimplements QWidget::setBackgroundColor() for binary compatibility.
186 void QtTableView::setBackgroundColor( const QColor &c )
188 QWidget::setBackgroundColor( c );
194 void QtTableView::setPalette( const QPalette &p )
196 QWidget::setPalette( p );
202 void QtTableView::show()
204 showOrHideScrollBars();
210 \overload void QtTableView::repaint( bool erase )
211 Repaints the entire view.
215 Repaints the table view directly by calling paintEvent() directly
216 unless updates are disabled.
218 Erases the view area \a (x,y,w,h) if \a erase is TRUE. Parameters \a
219 (x,y) are in \e widget coordinates.
221 If \a w is negative, it is replaced with <code>width() - x</code>.
222 If \a h is negative, it is replaced with <code>height() - y</code>.
224 Doing a repaint() usually is faster than doing an update(), but
225 calling update() many times in a row will generate a single paint
228 At present, QtTableView is the only widget that reimplements \link
229 QWidget::repaint() repaint()\endlink. It does this because by
230 clearing and then repainting one cell at at time, it can make the
231 screen flicker less than it would otherwise. */
233 void QtTableView::repaint( int x, int y, int w, int h, bool erase )
235 if ( !isVisible() || testWState(WState_BlockUpdates) )
241 QRect r( x, y, w, h );
243 return; // nothing to do
245 if ( erase && backgroundMode() != NoBackground )
246 eraseInPaint = TRUE; // erase when painting
248 eraseInPaint = FALSE;
252 \overload void QtTableView::repaint( const QRect &r, bool erase )
253 Replaints rectangle \a r. If \a erase is TRUE draws the background
254 using the palette's background.
259 \fn int QtTableView::numRows() const
260 Returns the number of rows in the table.
261 \sa numCols(), setNumRows()
265 Sets the number of rows of the table to \a rows (must be non-negative).
266 Does not change topCell().
268 The table repaints itself automatically if autoUpdate() is set.
270 \sa numCols(), setNumCols(), numRows()
273 void QtTableView::setNumRows( int rows )
276 #if defined(QT_CHECK_RANGE)
277 qWarning( "QtTableView::setNumRows: (%s) Negative argument %d.",
278 name( "unnamed" ), rows );
285 if ( autoUpdate() && isVisible() ) {
286 int oldLastVisible = lastRowVisible();
287 int oldTopCell = topCell();
289 if ( autoUpdate() && isVisible() &&
290 ( oldLastVisible != lastRowVisible() || oldTopCell != topCell() ) )
291 repaint( oldTopCell != topCell() );
293 // Be more careful - if destructing, bad things might happen.
296 updateScrollBars( verRange );
301 \fn int QtTableView::numCols() const
302 Returns the number of columns in the table.
303 \sa numRows(), setNumCols()
307 Sets the number of columns of the table to \a cols (must be non-negative).
308 Does not change leftCell().
310 The table repaints itself automatically if autoUpdate() is set.
312 \sa numCols(), numRows(), setNumRows()
315 void QtTableView::setNumCols( int cols )
318 #if defined(QT_CHECK_RANGE)
319 qWarning( "QtTableView::setNumCols: (%s) Negative argument %d.",
320 name( "unnamed" ), cols );
328 if ( autoUpdate() && isVisible() ) {
329 int maxCol = lastColVisible();
330 if ( maxCol >= oldCols || maxCol >= nCols )
333 updateScrollBars( horRange );
339 \fn int QtTableView::topCell() const
340 Returns the index of the first row in the table that is visible in
341 the view. The index of the first row is 0.
342 \sa leftCell(), setTopCell()
346 Scrolls the table so that \a row becomes the top row.
347 The index of the very first row is 0.
348 \sa setYOffset(), setTopLeftCell(), setLeftCell()
351 void QtTableView::setTopCell( int row )
353 setTopLeftCell( row, -1 );
358 \fn int QtTableView::leftCell() const
359 Returns the index of the first column in the table that is visible in
360 the view. The index of the very leftmost column is 0.
361 \sa topCell(), setLeftCell()
365 Scrolls the table so that \a col becomes the leftmost
366 column. The index of the leftmost column is 0.
367 \sa setXOffset(), setTopLeftCell(), setTopCell()
370 void QtTableView::setLeftCell( int col )
372 setTopLeftCell( -1, col );
377 Scrolls the table so that the cell at row \a row and colum \a
378 col becomes the top-left cell in the view. The cell at the extreme
379 top left of the table is at position (0,0).
380 \sa setLeftCell(), setTopCell(), setOffset()
383 void QtTableView::setTopLeftCell( int row, int col )
391 if ( newX > maxXOffset() )
396 newX += cellWidth( --col ); // optimize using current! ###
402 if ( newY > maxYOffset() )
407 newY += cellHeight( --row ); // optimize using current! ###
410 setOffset( newX, newY );
415 \fn int QtTableView::xOffset() const
417 Returns the x coordinate in \e table coordinates of the pixel that is
418 currently on the left edge of the view.
420 \sa setXOffset(), yOffset(), leftCell() */
423 Scrolls the table so that \a x becomes the leftmost pixel in the view.
424 The \a x parameter is in \e table coordinates.
426 The interaction with \link setTableFlags() Tbl_snapToHGrid
429 \sa xOffset(), setYOffset(), setOffset(), setLeftCell()
432 void QtTableView::setXOffset( int x )
434 setOffset( x, yOffset() );
438 \fn int QtTableView::yOffset() const
440 Returns the y coordinate in \e table coordinates of the pixel that is
441 currently on the top edge of the view.
443 \sa setYOffset(), xOffset(), topCell()
448 Scrolls the table so that \a y becomes the top pixel in the view.
449 The \a y parameter is in \e table coordinates.
451 The interaction with \link setTableFlags() Tbl_snapToVGrid
454 \sa yOffset(), setXOffset(), setOffset(), setTopCell()
457 void QtTableView::setYOffset( int y )
459 setOffset( xOffset(), y );
463 Scrolls the table so that \a (x,y) becomes the top-left pixel
464 in the view. Parameters \a (x,y) are in \e table coordinates.
466 The interaction with \link setTableFlags() Tbl_snapTo*Grid \endlink
467 is tricky. If \a updateScrBars is TRUE, the scroll bars are
470 \sa xOffset(), yOffset(), setXOffset(), setYOffset(), setTopLeftCell()
473 void QtTableView::setOffset( int x, int y, bool updateScrBars )
475 if ( (!testTableFlags(Tbl_snapToHGrid) || xCellDelta == 0) &&
476 (!testTableFlags(Tbl_snapToVGrid) || yCellDelta == 0) &&
477 (x == xOffs && y == yOffs) )
486 if ( x > maxXOffset() )
488 xCellOffs = x / cellW;
489 if ( !testTableFlags(Tbl_snapToHGrid) ) {
490 xCellDelta = (short)(x % cellW);
496 int xn=0, xcd=0, col = 0;
497 while ( col < nCols-1 && x >= xn+(xcd=cellWidth(col)) ) {
502 if ( testTableFlags(Tbl_snapToHGrid) ) {
506 xCellDelta = (short)(x-xn);
510 if ( y > maxYOffset() )
512 yCellOffs = y / cellH;
513 if ( !testTableFlags(Tbl_snapToVGrid) ) {
514 yCellDelta = (short)(y % cellH);
520 int yn=0, yrd=0, row=0;
521 while ( row < nRows-1 && y >= yn+(yrd=cellHeight(row)) ) {
526 if ( testTableFlags(Tbl_snapToVGrid) ) {
530 yCellDelta = (short)(y-yn);
533 int dx = (x - xOffs);
534 int dy = (y - yOffs);
537 if ( autoUpdate() && isVisible() )
540 updateScrollBars( verValue | horValue );
545 \overload int QtTableView::cellWidth() const
547 Returns the column width in pixels. Returns 0 if the columns have
550 \sa setCellWidth(), cellHeight()
554 Returns the width of column \a col in pixels.
556 This function is virtual and must be reimplemented by subclasses that
557 have variable cell widths. Note that if the total table width
558 changes, updateTableSize() must be called.
560 \sa setCellWidth(), cellHeight(), totalWidth(), updateTableSize()
563 int QtTableView::cellWidth( int )
570 Sets the width in pixels of the table cells to \a cellWidth.
572 Setting it to 0 means that the column width is variable. When
573 set to 0 (this is the default) QtTableView calls the virtual function
574 cellWidth() to get the width.
576 \sa cellWidth(), setCellHeight(), totalWidth(), numCols()
579 void QtTableView::setCellWidth( int cellWidth )
581 if ( cellW == cellWidth )
583 #if defined(QT_CHECK_RANGE)
584 if ( cellWidth < 0 || cellWidth > SHRT_MAX ) {
585 qWarning( "QtTableView::setCellWidth: (%s) Argument out of range (%d)",
586 name( "unnamed" ), cellWidth );
590 cellW = (short)cellWidth;
592 updateScrollBars( horSteps | horRange );
593 if ( autoUpdate() && isVisible() )
599 \overload int QtTableView::cellHeight() const
601 Returns the row height, in pixels. Returns 0 if the rows have
604 \sa setCellHeight(), cellWidth()
609 Returns the height of row \a row in pixels.
611 This function is virtual and must be reimplemented by subclasses that
612 have variable cell heights. Note that if the total table height
613 changes, updateTableSize() must be called.
615 \sa setCellHeight(), cellWidth(), totalHeight()
618 int QtTableView::cellHeight( int )
624 Sets the height in pixels of the table cells to \a cellHeight.
626 Setting it to 0 means that the row height is variable. When set
627 to 0 (this is the default), QtTableView calls the virtual function
628 cellHeight() to get the height.
630 \sa cellHeight(), setCellWidth(), totalHeight(), numRows()
633 void QtTableView::setCellHeight( int cellHeight )
635 if ( cellH == cellHeight )
637 #if defined(QT_CHECK_RANGE)
638 if ( cellHeight < 0 || cellHeight > SHRT_MAX ) {
639 qWarning( "QtTableView::setCellHeight: (%s) Argument out of range (%d)",
640 name( "unnamed" ), cellHeight );
644 cellH = (short)cellHeight;
645 if ( autoUpdate() && isVisible() )
647 updateScrollBars( verSteps | verRange );
652 Returns the total width of the table in pixels.
654 This function is virtual and should be reimplemented by subclasses that
655 have variable cell widths and a non-trivial cellWidth() function, or a
656 large number of columns in the table.
658 The default implementation may be slow for very wide tables.
660 \sa cellWidth(), totalHeight() */
662 int QtTableView::totalWidth()
668 for( int i = 0 ; i < nCols ; i++ )
669 tw += cellWidth( i );
675 Returns the total height of the table in pixels.
677 This function is virtual and should be reimplemented by subclasses that
678 have variable cell heights and a non-trivial cellHeight() function, or a
679 large number of rows in the table.
681 The default implementation may be slow for very tall tables.
683 \sa cellHeight(), totalWidth()
686 int QtTableView::totalHeight()
692 for( int i = 0 ; i < nRows ; i++ )
693 th += cellHeight( i );
700 \fn uint QtTableView::tableFlags() const
702 Returns the union of the table flags that are currently set.
704 \sa setTableFlags(), clearTableFlags(), testTableFlags()
708 \fn bool QtTableView::testTableFlags( uint f ) const
710 Returns TRUE if any of the table flags in \a f are currently set,
713 \sa setTableFlags(), clearTableFlags(), tableFlags()
717 Sets the table flags to \a f.
719 If a flag setting changes the appearance of the table, the table is
720 repainted if - and only if - autoUpdate() is TRUE.
722 The table flags are mostly single bits, though there are some multibit
723 flags for convenience. Here is a complete list:
726 <dt> Tbl_vScrollBar <dd> - The table has a vertical scroll bar.
727 <dt> Tbl_hScrollBar <dd> - The table has a horizontal scroll bar.
728 <dt> Tbl_autoVScrollBar <dd> - The table has a vertical scroll bar if
729 - and only if - the table is taller than the view.
730 <dt> Tbl_autoHScrollBar <dd> The table has a horizontal scroll bar if
731 - and only if - the table is wider than the view.
732 <dt> Tbl_autoScrollBars <dd> - The union of the previous two flags.
733 <dt> Tbl_clipCellPainting <dd> - The table uses QPainter::setClipRect() to
734 make sure that paintCell() will not draw outside the cell
736 <dt> Tbl_cutCellsV <dd> - The table will never show part of a
737 cell at the bottom of the table; if there is not space for all of
738 a cell, the space is left blank.
739 <dt> Tbl_cutCellsH <dd> - The table will never show part of a
740 cell at the right side of the table; if there is not space for all of
741 a cell, the space is left blank.
742 <dt> Tbl_cutCells <dd> - The union of the previous two flags.
743 <dt> Tbl_scrollLastHCell <dd> - When the user scrolls horizontally,
744 let him/her scroll the last cell left until it is at the left
745 edge of the view. If this flag is not set, the user can only scroll
746 to the point where the last cell is completely visible.
747 <dt> Tbl_scrollLastVCell <dd> - When the user scrolls vertically, let
748 him/her scroll the last cell up until it is at the top edge of
749 the view. If this flag is not set, the user can only scroll to the
750 point where the last cell is completely visible.
751 <dt> Tbl_scrollLastCell <dd> - The union of the previous two flags.
752 <dt> Tbl_smoothHScrolling <dd> - The table scrolls as smoothly as
753 possible when the user scrolls horizontally. When this flag is not
754 set, scrolling is done one cell at a time.
755 <dt> Tbl_smoothVScrolling <dd> - The table scrolls as smoothly as
756 possible when scrolling vertically. When this flag is not set,
757 scrolling is done one cell at a time.
758 <dt> Tbl_smoothScrolling <dd> - The union of the previous two flags.
759 <dt> Tbl_snapToHGrid <dd> - Except when the user is actually scrolling,
760 the leftmost column shown snaps to the leftmost edge of the view.
761 <dt> Tbl_snapToVGrid <dd> - Except when the user is actually
762 scrolling, the top row snaps to the top edge of the view.
763 <dt> Tbl_snapToGrid <dd> - The union of the previous two flags.
766 You can specify more than one flag at a time using bitwise OR.
770 setTableFlags( Tbl_smoothScrolling | Tbl_autoScrollBars );
773 \warning The cutCells options (\c Tbl_cutCells, \c Tbl_cutCellsH and
774 Tbl_cutCellsV) may cause painting problems when scrollbars are
775 enabled. Do not combine cutCells and scrollbars.
778 \sa clearTableFlags(), testTableFlags(), tableFlags()
781 void QtTableView::setTableFlags( uint f )
783 f = (f ^ tFlags) & f; // clear flags already set
786 bool updateOn = autoUpdate();
787 setAutoUpdate( FALSE );
789 uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
791 if ( f & Tbl_vScrollBar ) {
792 setVerScrollBar( TRUE );
794 if ( f & Tbl_hScrollBar ) {
795 setHorScrollBar( TRUE );
797 if ( f & Tbl_autoVScrollBar ) {
798 updateScrollBars( verRange );
800 if ( f & Tbl_autoHScrollBar ) {
801 updateScrollBars( horRange );
803 if ( f & Tbl_scrollLastHCell ) {
804 updateScrollBars( horRange );
806 if ( f & Tbl_scrollLastVCell ) {
807 updateScrollBars( verRange );
809 if ( f & Tbl_snapToHGrid ) {
810 updateScrollBars( horRange );
812 if ( f & Tbl_snapToVGrid ) {
813 updateScrollBars( verRange );
815 if ( f & Tbl_snapToGrid ) { // Note: checks for 2 flags
816 if ( (f & Tbl_snapToHGrid) != 0 && xCellDelta != 0 || //have to scroll?
817 (f & Tbl_snapToVGrid) != 0 && yCellDelta != 0 ) {
818 snapToGrid( (f & Tbl_snapToHGrid) != 0, // do snapping
819 (f & Tbl_snapToVGrid) != 0 );
820 repaintMask |= Tbl_snapToGrid; // repaint table
825 setAutoUpdate( TRUE );
827 if ( isVisible() && (f & repaintMask) )
834 Clears the \link setTableFlags() table flags\endlink that are set
837 Example (clears a single flag):
839 clearTableFlags( Tbl_snapToGrid );
842 The default argument clears all flags.
844 \sa setTableFlags(), testTableFlags(), tableFlags()
847 void QtTableView::clearTableFlags( uint f )
849 f = (f ^ ~tFlags) & f; // clear flags that are already 0
852 bool updateOn = autoUpdate();
853 setAutoUpdate( FALSE );
855 uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
857 if ( f & Tbl_vScrollBar ) {
858 setVerScrollBar( FALSE );
860 if ( f & Tbl_hScrollBar ) {
861 setHorScrollBar( FALSE );
863 if ( f & Tbl_scrollLastHCell ) {
864 int maxX = maxXOffset();
865 if ( xOffs > maxX ) {
866 setOffset( maxX, yOffs );
867 repaintMask |= Tbl_scrollLastHCell;
869 updateScrollBars( horRange );
871 if ( f & Tbl_scrollLastVCell ) {
872 int maxY = maxYOffset();
873 if ( yOffs > maxY ) {
874 setOffset( xOffs, maxY );
875 repaintMask |= Tbl_scrollLastVCell;
877 updateScrollBars( verRange );
879 if ( f & Tbl_smoothScrolling ) { // Note: checks for 2 flags
880 if ((f & Tbl_smoothHScrolling) != 0 && xCellDelta != 0 ||//must scroll?
881 (f & Tbl_smoothVScrolling) != 0 && yCellDelta != 0 ) {
882 snapToGrid( (f & Tbl_smoothHScrolling) != 0, // do snapping
883 (f & Tbl_smoothVScrolling) != 0 );
884 repaintMask |= Tbl_smoothScrolling; // repaint table
887 if ( f & Tbl_snapToHGrid ) {
888 updateScrollBars( horRange );
890 if ( f & Tbl_snapToVGrid ) {
891 updateScrollBars( verRange );
894 setAutoUpdate( TRUE );
895 updateScrollBars(); // returns immediately if nothing to do
896 if ( isVisible() && (f & repaintMask) )
904 \fn bool QtTableView::autoUpdate() const
906 Returns TRUE if the view updates itself automatically whenever it
907 is changed in some way.
913 Sets the auto-update option of the table view to \a enable.
915 If \a enable is TRUE (this is the default), the view updates itself
916 automatically whenever it has changed in some way (for example, when a
917 \link setTableFlags() flag\endlink is changed).
919 If \a enable is FALSE, the view does NOT repaint itself or update
920 its internal state variables when it is changed. This can be
921 useful to avoid flicker during large changes and is singularly
922 useless otherwise. Disable auto-update, do the changes, re-enable
923 auto-update and call repaint().
925 \warning Do not leave the view in this state for a long time
926 (i.e., between events). If, for example, the user interacts with the
927 view when auto-update is off, strange things can happen.
929 Setting auto-update to TRUE does not repaint the view; you must call
930 repaint() to do this.
932 \sa autoUpdate(), repaint()
935 void QtTableView::setAutoUpdate( bool enable )
937 if ( isUpdatesEnabled() == enable )
939 setUpdatesEnabled( enable );
941 showOrHideScrollBars();
948 Repaints the cell at row \a row, column \a col if it is inside the view.
950 If \a erase is TRUE, the relevant part of the view is cleared to the
951 background color/pixmap before the contents are repainted.
956 void QtTableView::updateCell( int row, int col, bool erase )
959 if ( !colXPos( col, &xPos ) )
961 if ( !rowYPos( row, &yPos ) )
963 QRect uR = QRect( xPos, yPos,
964 cellW ? cellW : cellWidth(col),
965 cellH ? cellH : cellHeight(row) );
966 repaint( uR.intersect(viewRect()), erase );
971 \fn QRect QtTableView::cellUpdateRect() const
973 This function should be called only from the paintCell() function in
974 subclasses. It returns the portion of a cell that actually needs to be
975 updated in \e cell coordinates. This is useful only for non-trivial
981 Returns the rectangle that is the actual table, excluding any
982 frame, in \e widget coordinates.
985 QRect QtTableView::viewRect() const
987 return QRect( frameWidth(), frameWidth(), viewWidth(), viewHeight() );
992 Returns the index of the last (bottom) row in the view.
993 The index of the first row is 0.
995 If no rows are visible it returns -1. This can happen if the
996 view is too small for the first row and Tbl_cutCellsV is set.
1001 int QtTableView::lastRowVisible() const
1004 int row = findRawRow( maxViewY(), &cellMaxY );
1005 if ( row == -1 || row >= nRows ) { // maxViewY() past end?
1006 row = nRows - 1; // yes: return last row
1008 if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() ) {
1009 if ( row == yCellOffs ) // cut by right margin?
1010 return -1; // yes, nothing in the view
1012 row = row - 1; // cut by margin, one back
1019 Returns the index of the last (right) column in the view.
1020 The index of the first column is 0.
1022 If no columns are visible it returns -1. This can happen if the
1023 view is too narrow for the first column and Tbl_cutCellsH is set.
1025 \sa lastRowVisible()
1028 int QtTableView::lastColVisible() const
1031 int col = findRawCol( maxViewX(), &cellMaxX );
1032 if ( col == -1 || col >= nCols ) { // maxViewX() past end?
1033 col = nCols - 1; // yes: return last col
1035 if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() ) {
1036 if ( col == xCellOffs ) // cut by bottom margin?
1037 return -1; // yes, nothing in the view
1039 col = col - 1; // cell by margin, one back
1046 Returns TRUE if \a row is at least partially visible.
1050 bool QtTableView::rowIsVisible( int row ) const
1052 return rowYPos( row, 0 );
1056 Returns TRUE if \a col is at least partially visible.
1060 bool QtTableView::colIsVisible( int col ) const
1062 return colXPos( col, 0 );
1068 Called when both scroll bars are active at the same time. Covers the
1069 bottom left corner between the two scroll bars with an empty widget.
1072 void QtTableView::coverCornerSquare( bool enable )
1074 coveringCornerSquare = enable;
1075 if ( !cornerSquare && enable ) {
1076 cornerSquare = new QCornerSquare( this );
1077 Q_CHECK_PTR( cornerSquare );
1078 cornerSquare->setGeometry( maxViewX() + frameWidth() + 1,
1079 maxViewY() + frameWidth() + 1,
1083 if ( autoUpdate() && cornerSquare ) {
1085 cornerSquare->show();
1087 cornerSquare->hide();
1094 Scroll the view to a position such that:
1096 If \a horizontal is TRUE, the leftmost column shown fits snugly
1097 with the left edge of the view.
1099 If \a vertical is TRUE, the top row shown fits snugly with the top
1102 You can achieve the same effect automatically by setting any of the
1103 \link setTableFlags() Tbl_snapTo*Grid \endlink table flags.
1106 void QtTableView::snapToGrid( bool horizontal, bool vertical )
1110 if ( horizontal && xCellDelta != 0 ) {
1111 int w = cellW ? cellW : cellWidth( xCellOffs );
1112 if ( xCellDelta >= w/2 )
1113 newXCell = xCellOffs + 1;
1115 newXCell = xCellOffs;
1117 if ( vertical && yCellDelta != 0 ) {
1118 int h = cellH ? cellH : cellHeight( yCellOffs );
1119 if ( yCellDelta >= h/2 )
1120 newYCell = yCellOffs + 1;
1122 newYCell = yCellOffs;
1124 setTopLeftCell( newYCell, newXCell ); //row,column
1129 This internal slot is connected to the horizontal scroll bar's
1130 QScrollBar::valueChanged() signal.
1132 Moves the table horizontally to offset \a val without updating the
1136 void QtTableView::horSbValue( int val )
1140 if ( horSnappingOff ) {
1141 horSnappingOff = FALSE;
1142 tFlags |= Tbl_snapToHGrid;
1145 setOffset( val, yOffs, FALSE );
1150 This internal slot is connected to the horizontal scroll bar's
1151 QScrollBar::sliderMoved() signal.
1153 Scrolls the table smoothly horizontally even if \c Tbl_snapToHGrid is set.
1156 void QtTableView::horSbSliding( int val )
1158 if ( testTableFlags(Tbl_snapToHGrid) &&
1159 testTableFlags(Tbl_smoothHScrolling) ) {
1160 tFlags &= ~Tbl_snapToHGrid; // turn off snapping while sliding
1161 setOffset( val, yOffs, FALSE );
1162 tFlags |= Tbl_snapToHGrid; // turn on snapping again
1164 setOffset( val, yOffs, FALSE );
1170 This internal slot is connected to the horizontal scroll bar's
1171 QScrollBar::sliderReleased() signal.
1174 void QtTableView::horSbSlidingDone( )
1176 if ( testTableFlags(Tbl_snapToHGrid) &&
1177 testTableFlags(Tbl_smoothHScrolling) )
1178 snapToGrid( TRUE, FALSE );
1183 This internal slot is connected to the vertical scroll bar's
1184 QScrollBar::valueChanged() signal.
1186 Moves the table vertically to offset \a val without updating the
1190 void QtTableView::verSbValue( int val )
1194 if ( verSnappingOff ) {
1195 verSnappingOff = FALSE;
1196 tFlags |= Tbl_snapToVGrid;
1199 setOffset( xOffs, val, FALSE );
1204 This internal slot is connected to the vertical scroll bar's
1205 QScrollBar::sliderMoved() signal.
1207 Scrolls the table smoothly vertically even if \c Tbl_snapToVGrid is set.
1210 void QtTableView::verSbSliding( int val )
1212 if ( testTableFlags(Tbl_snapToVGrid) &&
1213 testTableFlags(Tbl_smoothVScrolling) ) {
1214 tFlags &= ~Tbl_snapToVGrid; // turn off snapping while sliding
1215 setOffset( xOffs, val, FALSE );
1216 tFlags |= Tbl_snapToVGrid; // turn on snapping again
1218 setOffset( xOffs, val, FALSE );
1224 This internal slot is connected to the vertical scroll bar's
1225 QScrollBar::sliderReleased() signal.
1228 void QtTableView::verSbSlidingDone( )
1230 if ( testTableFlags(Tbl_snapToVGrid) &&
1231 testTableFlags(Tbl_smoothVScrolling) )
1232 snapToGrid( FALSE, TRUE );
1237 This virtual function is called before painting of table cells
1238 is started. It can be reimplemented by subclasses that want to
1239 to set up the painter in a special way and that do not want to
1240 do so for each cell.
1243 void QtTableView::setupPainter( QPainter * )
1248 \fn void QtTableView::paintCell( QPainter *p, int row, int col )
1250 This pure virtual function is called to paint the single cell at \a
1251 (row,col) using \a p, which is open when paintCell() is called and
1254 The coordinate system is \link QPainter::translate() translated \endlink
1255 so that the origin is at the top-left corner of the cell to be
1256 painted, i.e. \e cell coordinates. Do not scale or shear the coordinate
1257 system (or if you do, restore the transformation matrix before you
1260 The painter is not clipped by default and for maximum efficiency. For safety,
1261 call setTableFlags(Tbl_clipCellPainting) to enable clipping.
1263 \sa paintEvent(), setTableFlags() */
1267 Handles paint events, \a e, for the table view.
1269 Calls paintCell() for the cells that needs to be repainted.
1272 void QtTableView::paintEvent( QPaintEvent *e )
1274 QRect updateR = e->rect(); // update rectangle
1276 bool e = eraseInPaint;
1281 QPainter paint( this );
1283 if ( !contentsRect().contains( updateR, TRUE ) ) {// update frame ?
1284 drawFrame( &paint );
1285 if ( updateR.left() < frameWidth() ) //###
1286 updateR.setLeft( frameWidth() );
1287 if ( updateR.top() < frameWidth() )
1288 updateR.setTop( frameWidth() );
1291 int maxWX = maxViewX();
1292 int maxWY = maxViewY();
1293 if ( updateR.right() > maxWX )
1294 updateR.setRight( maxWX );
1295 if ( updateR.bottom() > maxWY )
1296 updateR.setBottom( maxWY );
1298 setupPainter( &paint ); // prepare for painting table
1300 int firstRow = findRow( updateR.y() );
1301 int firstCol = findCol( updateR.x() );
1303 if ( !colXPos( firstCol, &xStart ) || !rowYPos( firstRow, &yStart ) ) {
1304 paint.eraseRect( updateR ); // erase area outside cells but in view
1307 int maxX = updateR.right();
1308 int maxY = updateR.bottom();
1312 int xPos = maxX+1; // in case the while() is empty
1315 QRect winR = viewRect();
1318 #ifndef QT_NO_TRANSFORMATIONS
1322 while ( yPos <= maxY && row < nRows ) {
1323 nextY = yPos + (cellH ? cellH : cellHeight( row ));
1324 if ( testTableFlags( Tbl_cutCellsV ) && nextY > ( maxWY + 1 ) )
1328 while ( xPos <= maxX && col < nCols ) {
1329 nextX = xPos + (cellW ? cellW : cellWidth( col ));
1330 if ( testTableFlags( Tbl_cutCellsH ) && nextX > ( maxWX + 1 ) )
1333 cellR.setRect( xPos, yPos, cellW ? cellW : cellWidth(col),
1334 cellH ? cellH : cellHeight(row) );
1335 cellUR = cellR.intersect( updateR );
1336 if ( cellUR.isValid() ) {
1337 cellUpdateR = cellUR;
1338 cellUpdateR.moveBy( -xPos, -yPos ); // cell coordinates
1340 paint.eraseRect( cellUR );
1342 #ifndef QT_NO_TRANSFORMATIONS
1343 matrix.translate( xPos, yPos );
1344 paint.setWorldMatrix( matrix );
1345 if ( testTableFlags(Tbl_clipCellPainting) ||
1346 frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1347 paint.setClipRect( cellUR );
1348 paintCell( &paint, row, col );
1349 paint.setClipping( FALSE );
1351 paintCell( &paint, row, col );
1354 paint.setWorldMatrix( matrix );
1356 paint.translate( xPos, yPos );
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 );
1365 paint.translate( -xPos, -yPos );
1375 // while painting we have to erase any areas in the view that
1376 // are not covered by cells but are covered by the paint event
1377 // rectangle these must be erased. We know that xPos is the last
1378 // x pixel updated + 1 and that yPos is the last y pixel updated + 1.
1380 // Note that this needs to be done regardless whether we do
1381 // eraseInPaint or not. Reason: a subclass may implement
1382 // flicker-freeness and encourage the use of repaint(FALSE).
1383 // The subclass, however, cannot draw all pixels, just those
1384 // inside the cells. So QtTableView is reponsible for all pixels
1385 // outside the cells.
1387 QRect viewR = viewRect();
1388 const QColorGroup g = colorGroup();
1390 if ( xPos <= maxX ) {
1393 r.setBottom( yPos<maxY?yPos:maxY );
1394 if ( inherits( "QMultiLineEdit" ) )
1395 paint.fillRect( r.intersect( updateR ), g.base() );
1397 paint.eraseRect( r.intersect( updateR ) );
1399 if ( yPos <= maxY ) {
1402 if ( inherits( "QMultiLineEdit" ) )
1403 paint.fillRect( r.intersect( updateR ), g.base() );
1405 paint.eraseRect( r.intersect( updateR ) );
1411 void QtTableView::resizeEvent( QResizeEvent * )
1413 updateScrollBars( horValue | verValue | horSteps | horGeometry | horRange |
1414 verSteps | verGeometry | verRange );
1415 showOrHideScrollBars();
1417 int maxX = QMIN( xOffs, maxXOffset() ); // ### can be slow
1418 int maxY = QMIN( yOffs, maxYOffset() );
1419 setOffset( maxX, maxY );
1424 Redraws all visible cells in the table view.
1427 void QtTableView::updateView()
1429 repaint( viewRect() );
1433 Returns a pointer to the vertical scroll bar mainly so you can
1434 connect() to its signals. Note that the scroll bar works in pixel
1435 values; use findRow() to translate to cell numbers.
1438 QScrollBar *QtTableView::verticalScrollBar() const
1440 QtTableView *that = (QtTableView*)this; // semantic const
1441 if ( !vScrollBar ) {
1442 QScrollBar *sb = new QScrollBar( QScrollBar::Vertical, that );
1443 #ifndef QT_NO_CURSOR
1444 sb->setCursor( arrowCursor );
1446 sb->resize( sb->sizeHint() ); // height is irrelevant
1448 sb->setTracking( FALSE );
1449 sb->setFocusPolicy( NoFocus );
1450 connect( sb, SIGNAL(valueChanged(int)),
1451 SLOT(verSbValue(int)));
1452 connect( sb, SIGNAL(sliderMoved(int)),
1453 SLOT(verSbSliding(int)));
1454 connect( sb, SIGNAL(sliderReleased()),
1455 SLOT(verSbSlidingDone()));
1457 that->vScrollBar = sb;
1464 Returns a pointer to the horizontal scroll bar mainly so you can
1465 connect() to its signals. Note that the scroll bar works in pixel
1466 values; use findCol() to translate to cell numbers.
1469 QScrollBar *QtTableView::horizontalScrollBar() const
1471 QtTableView *that = (QtTableView*)this; // semantic const
1472 if ( !hScrollBar ) {
1473 QScrollBar *sb = new QScrollBar( QScrollBar::Horizontal, that );
1474 #ifndef QT_NO_CURSOR
1475 sb->setCursor( arrowCursor );
1477 sb->resize( sb->sizeHint() ); // width is irrelevant
1478 sb->setFocusPolicy( NoFocus );
1480 sb->setTracking( FALSE );
1481 connect( sb, SIGNAL(valueChanged(int)),
1482 SLOT(horSbValue(int)));
1483 connect( sb, SIGNAL(sliderMoved(int)),
1484 SLOT(horSbSliding(int)));
1485 connect( sb, SIGNAL(sliderReleased()),
1486 SLOT(horSbSlidingDone()));
1488 that->hScrollBar = sb;
1495 Enables or disables the horizontal scroll bar, as required by
1496 setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1499 void QtTableView::setHorScrollBar( bool on, bool update )
1502 tFlags |= Tbl_hScrollBar;
1503 horizontalScrollBar(); // created
1505 updateScrollBars( horMask | verMask );
1507 sbDirty = sbDirty | (horMask | verMask);
1508 if ( testTableFlags( Tbl_vScrollBar ) )
1509 coverCornerSquare( TRUE );
1511 sbDirty = sbDirty | horMask;
1513 tFlags &= ~Tbl_hScrollBar;
1516 coverCornerSquare( FALSE );
1517 bool hideScrollBar = autoUpdate() && hScrollBar->isVisible();
1518 if ( hideScrollBar )
1521 updateScrollBars( verMask );
1523 sbDirty = sbDirty | verMask;
1524 if ( hideScrollBar && isVisible() )
1525 repaint( hScrollBar->x(), hScrollBar->y(),
1526 width() - hScrollBar->x(), hScrollBar->height() );
1534 Enables or disables the vertical scroll bar, as required by
1535 setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1538 void QtTableView::setVerScrollBar( bool on, bool update )
1541 tFlags |= Tbl_vScrollBar;
1542 verticalScrollBar(); // created
1544 updateScrollBars( verMask | horMask );
1546 sbDirty = sbDirty | (horMask | verMask);
1547 if ( testTableFlags( Tbl_hScrollBar ) )
1548 coverCornerSquare( TRUE );
1550 sbDirty = sbDirty | verMask;
1552 tFlags &= ~Tbl_vScrollBar;
1555 coverCornerSquare( FALSE );
1556 bool hideScrollBar = autoUpdate() && vScrollBar->isVisible();
1557 if ( hideScrollBar )
1560 updateScrollBars( horMask );
1562 sbDirty = sbDirty | horMask;
1563 if ( hideScrollBar && isVisible() )
1564 repaint( vScrollBar->x(), vScrollBar->y(),
1565 vScrollBar->width(), height() - vScrollBar->y() );
1574 int QtTableView::findRawRow( int yPos, int *cellMaxY, int *cellMinY,
1575 bool goOutsideView ) const
1580 if ( goOutsideView || yPos >= minViewY() && yPos <= maxViewY() ) {
1581 if ( yPos < minViewY() ) {
1582 #if defined(QT_CHECK_RANGE)
1583 qWarning( "QtTableView::findRawRow: (%s) internal error: "
1584 "yPos < minViewY() && goOutsideView "
1585 "not supported. (%d,%d)",
1586 name( "unnamed" ), yPos, yOffs );
1590 if ( cellH ) { // uniform cell height
1591 r = (yPos - minViewY() + yCellDelta)/cellH; // cell offs from top
1593 *cellMaxY = (r + 1)*cellH + minViewY() - yCellDelta - 1;
1595 *cellMinY = r*cellH + minViewY() - yCellDelta;
1596 r += yCellOffs; // absolute cell index
1597 } else { // variable cell height
1598 QtTableView *tw = (QtTableView *)this;
1600 int h = minViewY() - yCellDelta; //##arnt3
1602 Q_ASSERT( r < nRows );
1603 while ( r < nRows ) {
1605 h += tw->cellHeight( r ); // Start of next cell
1621 int QtTableView::findRawCol( int xPos, int *cellMaxX, int *cellMinX ,
1622 bool goOutsideView ) const
1627 if ( goOutsideView || xPos >= minViewX() && xPos <= maxViewX() ) {
1628 if ( xPos < minViewX() ) {
1629 #if defined(QT_CHECK_RANGE)
1630 qWarning( "QtTableView::findRawCol: (%s) internal error: "
1631 "xPos < minViewX() && goOutsideView "
1632 "not supported. (%d,%d)",
1633 name( "unnamed" ), xPos, xOffs );
1637 if ( cellW ) { // uniform cell width
1638 c = (xPos - minViewX() + xCellDelta)/cellW; //cell offs from left
1640 *cellMaxX = (c + 1)*cellW + minViewX() - xCellDelta - 1;
1642 *cellMinX = c*cellW + minViewX() - xCellDelta;
1643 c += xCellOffs; // absolute cell index
1644 } else { // variable cell width
1645 QtTableView *tw = (QtTableView *)this;
1647 int w = minViewX() - xCellDelta; //##arnt3
1649 Q_ASSERT( c < nCols );
1650 while ( c < nCols ) {
1652 w += tw->cellWidth( c ); // Start of next cell
1668 Returns the index of the row at position \a yPos, where \a yPos is in
1669 \e widget coordinates. Returns -1 if \a yPos is outside the valid
1672 \sa findCol(), rowYPos()
1675 int QtTableView::findRow( int yPos ) const
1678 int row = findRawRow( yPos, &cellMaxY );
1679 if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() )
1680 row = - 1; // cell cut by bottom margin
1688 Returns the index of the column at position \a xPos, where \a xPos is
1689 in \e widget coordinates. Returns -1 if \a xPos is outside the valid
1692 \sa findRow(), colXPos()
1695 int QtTableView::findCol( int xPos ) const
1698 int col = findRawCol( xPos, &cellMaxX );
1699 if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() )
1700 col = - 1; // cell cut by right margin
1708 Computes the position in the widget of row \a row.
1710 Returns TRUE and stores the result in \a *yPos (in \e widget
1711 coordinates) if the row is visible. Returns FALSE and does not modify
1712 \a *yPos if \a row is invisible or invalid.
1714 \sa colXPos(), findRow()
1717 bool QtTableView::rowYPos( int row, int *yPos ) const
1720 if ( row >= yCellOffs ) {
1722 int lastVisible = lastRowVisible();
1723 if ( row > lastVisible || lastVisible == -1 )
1725 y = (row - yCellOffs)*cellH + minViewY() - yCellDelta;
1728 y = minViewY() - yCellDelta; // y of leftmost cell in view
1730 QtTableView *tw = (QtTableView *)this;
1731 int maxY = maxViewY();
1732 while ( r < row && y <= maxY )
1733 y += tw->cellHeight( r++ );
1748 Computes the position in the widget of column \a col.
1750 Returns TRUE and stores the result in \a *xPos (in \e widget
1751 coordinates) if the column is visible. Returns FALSE and does not
1752 modify \a *xPos if \a col is invisible or invalid.
1754 \sa rowYPos(), findCol()
1757 bool QtTableView::colXPos( int col, int *xPos ) const
1760 if ( col >= xCellOffs ) {
1762 int lastVisible = lastColVisible();
1763 if ( col > lastVisible || lastVisible == -1 )
1765 x = (col - xCellOffs)*cellW + minViewX() - xCellDelta;
1768 x = minViewX() - xCellDelta; // x of uppermost cell in view
1770 QtTableView *tw = (QtTableView *)this;
1771 int maxX = maxViewX();
1772 while ( c < col && x <= maxX )
1773 x += tw->cellWidth( c++ );
1787 Moves the visible area of the table right by \a xPixels and
1788 down by \a yPixels pixels. Both may be negative.
1790 \warning You might find that QScrollView offers a higher-level of
1791 functionality than using QtTableView and this function.
1793 This function is \e not the same as QWidget::scroll(); in particular,
1794 the signs of \a xPixels and \a yPixels have the reverse semantics.
1796 \sa setXOffset(), setYOffset(), setOffset(), setTopCell(),
1800 void QtTableView::scroll( int xPixels, int yPixels )
1802 QWidget::scroll( -xPixels, -yPixels, contentsRect() );
1807 Returns the leftmost pixel of the table view in \e view
1808 coordinates. This excludes the frame and any header.
1810 \sa maxViewY(), viewWidth(), contentsRect()
1813 int QtTableView::minViewX() const
1815 return frameWidth();
1820 Returns the top pixel of the table view in \e view
1821 coordinates. This excludes the frame and any header.
1823 \sa maxViewX(), viewHeight(), contentsRect()
1826 int QtTableView::minViewY() const
1828 return frameWidth();
1833 Returns the rightmost pixel of the table view in \e view
1834 coordinates. This excludes the frame and any scroll bar, but
1835 includes blank pixels to the right of the visible table data.
1837 \sa maxViewY(), viewWidth(), contentsRect()
1840 int QtTableView::maxViewX() const
1842 return width() - 1 - frameWidth()
1843 - (tFlags & Tbl_vScrollBar ? VSBEXT
1849 Returns the bottom pixel of the table view in \e view
1850 coordinates. This excludes the frame and any scroll bar, but
1851 includes blank pixels below the visible table data.
1853 \sa maxViewX(), viewHeight(), contentsRect()
1856 int QtTableView::maxViewY() const
1858 return height() - 1 - frameWidth()
1859 - (tFlags & Tbl_hScrollBar ? HSBEXT
1865 Returns the width of the table view, as such, in \e view
1866 coordinates. This does not include any header, scroll bar or frame,
1867 but it does include background pixels to the right of the table data.
1869 \sa minViewX() maxViewX(), viewHeight(), contentsRect() viewRect()
1872 int QtTableView::viewWidth() const
1874 return maxViewX() - minViewX() + 1;
1879 Returns the height of the table view, as such, in \e view
1880 coordinates. This does not include any header, scroll bar or frame,
1881 but it does include background pixels below the table data.
1883 \sa minViewY() maxViewY() viewWidth() contentsRect() viewRect()
1886 int QtTableView::viewHeight() const
1888 return maxViewY() - minViewY() + 1;
1892 void QtTableView::doAutoScrollBars()
1894 int viewW = width() - frameWidth() - minViewX();
1895 int viewH = height() - frameWidth() - minViewY();
1896 bool vScrollOn = testTableFlags(Tbl_vScrollBar);
1897 bool hScrollOn = testTableFlags(Tbl_hScrollBar);
1902 if ( testTableFlags(Tbl_autoHScrollBar) ) {
1907 while ( i < nCols && w <= viewW )
1908 w += cellWidth( i++ );
1916 if ( testTableFlags(Tbl_autoVScrollBar) ) {
1921 while ( i < nRows && h <= viewH )
1922 h += cellHeight( i++ );
1931 if ( testTableFlags(Tbl_autoHScrollBar) && vScrollOn && !hScrollOn )
1932 if ( w > viewW - VSBEXT )
1935 if ( testTableFlags(Tbl_autoVScrollBar) && hScrollOn && !vScrollOn )
1936 if ( h > viewH - HSBEXT )
1939 setHorScrollBar( hScrollOn, FALSE );
1940 setVerScrollBar( vScrollOn, FALSE );
1946 \fn void QtTableView::updateScrollBars()
1948 Updates the scroll bars' contents and presence to match the table's
1949 state. Generally, you should not need to call this.
1955 Updates the scroll bars' contents and presence to match the table's
1961 void QtTableView::updateScrollBars( uint f )
1963 sbDirty = sbDirty | f;
1968 if ( testTableFlags(Tbl_autoHScrollBar) && (sbDirty & horRange) ||
1969 testTableFlags(Tbl_autoVScrollBar) && (sbDirty & verRange) )
1970 // if range change and auto
1971 doAutoScrollBars(); // turn scroll bars on/off if needed
1973 if ( !autoUpdate() ) {
1977 if ( yOffset() > 0 && testTableFlags( Tbl_autoVScrollBar ) &&
1978 !testTableFlags( Tbl_vScrollBar ) ) {
1981 if ( xOffset() > 0 && testTableFlags( Tbl_autoHScrollBar ) &&
1982 !testTableFlags( Tbl_hScrollBar ) ) {
1985 if ( !isVisible() ) {
1990 if ( testTableFlags(Tbl_hScrollBar) && (sbDirty & horMask) != 0 ) {
1991 if ( sbDirty & horGeometry )
1992 hScrollBar->setGeometry( 0,height() - HSBEXT,
1993 viewWidth() + frameWidth()*2,
1996 if ( sbDirty & horSteps ) {
1998 hScrollBar->setSteps( QMIN(cellW,viewWidth()/2), viewWidth() );
2000 hScrollBar->setSteps( 16, viewWidth() );
2003 if ( sbDirty & horRange )
2004 hScrollBar->setRange( 0, maxXOffset() );
2006 if ( sbDirty & horValue )
2007 hScrollBar->setValue( xOffs );
2009 // show scrollbar only when it has a sane geometry
2010 if ( !hScrollBar->isVisible() )
2014 if ( testTableFlags(Tbl_vScrollBar) && (sbDirty & verMask) != 0 ) {
2015 if ( sbDirty & verGeometry )
2016 vScrollBar->setGeometry( width() - VSBEXT, 0,
2018 viewHeight() + frameWidth()*2 );
2020 if ( sbDirty & verSteps ) {
2022 vScrollBar->setSteps( QMIN(cellH,viewHeight()/2), viewHeight() );
2024 vScrollBar->setSteps( 16, viewHeight() ); // fttb! ###
2027 if ( sbDirty & verRange )
2028 vScrollBar->setRange( 0, maxYOffset() );
2030 if ( sbDirty & verValue )
2031 vScrollBar->setValue( yOffs );
2033 // show scrollbar only when it has a sane geometry
2034 if ( !vScrollBar->isVisible() )
2037 if ( coveringCornerSquare &&
2038 ( (sbDirty & verGeometry ) || (sbDirty & horGeometry)) )
2039 cornerSquare->move( maxViewX() + frameWidth() + 1,
2040 maxViewY() + frameWidth() + 1 );
2047 void QtTableView::updateFrameSize()
2049 int rw = width() - ( testTableFlags(Tbl_vScrollBar) ?
2051 int rh = height() - ( testTableFlags(Tbl_hScrollBar) ?
2058 if ( autoUpdate() ) {
2059 int fh = frameRect().height();
2060 int fw = frameRect().width();
2061 setFrameRect( QRect(0,0,rw,rh) );
2064 update( QMIN(fw,rw) - frameWidth() - 2, 0, frameWidth()+4, rh );
2066 update( 0, QMIN(fh,rh) - frameWidth() - 2, rw, frameWidth()+4 );
2072 Returns the maximum horizontal offset within the table of the
2073 view's left edge in \e table coordinates.
2075 This is used mainly to set the horizontal scroll bar's range.
2077 \sa maxColOffset(), maxYOffset(), totalWidth()
2080 int QtTableView::maxXOffset()
2082 int tw = totalWidth();
2084 if ( testTableFlags(Tbl_scrollLastHCell) ) {
2086 maxOffs = tw - ( cellW ? cellW : cellWidth( nCols - 1 ) );
2088 maxOffs = tw - viewWidth();
2090 if ( testTableFlags(Tbl_snapToHGrid) ) {
2092 maxOffs = tw - (viewWidth()/cellW)*cellW;
2094 int goal = tw - viewWidth();
2096 int nextCol = nCols - 1;
2097 int nextCellWidth = cellWidth( nextCol );
2098 while( nextCol > 0 && pos > goal + nextCellWidth ) {
2099 pos -= nextCellWidth;
2100 nextCellWidth = cellWidth( --nextCol );
2102 if ( goal + nextCellWidth == pos )
2104 else if ( goal < pos )
2110 maxOffs = tw - viewWidth();
2113 return maxOffs > 0 ? maxOffs : 0;
2118 Returns the maximum vertical offset within the table of the
2119 view's top edge in \e table coordinates.
2121 This is used mainly to set the vertical scroll bar's range.
2123 \sa maxRowOffset(), maxXOffset(), totalHeight()
2126 int QtTableView::maxYOffset()
2128 int th = totalHeight();
2130 if ( testTableFlags(Tbl_scrollLastVCell) ) {
2132 maxOffs = th - ( cellH ? cellH : cellHeight( nRows - 1 ) );
2134 maxOffs = th - viewHeight();
2136 if ( testTableFlags(Tbl_snapToVGrid) ) {
2138 maxOffs = th - (viewHeight()/cellH)*cellH;
2140 int goal = th - viewHeight();
2142 int nextRow = nRows - 1;
2143 int nextCellHeight = cellHeight( nextRow );
2144 while( nextRow > 0 && pos > goal + nextCellHeight ) {
2145 pos -= nextCellHeight;
2146 nextCellHeight = cellHeight( --nextRow );
2148 if ( goal + nextCellHeight == pos )
2150 else if ( goal < pos )
2156 maxOffs = th - viewHeight();
2159 return maxOffs > 0 ? maxOffs : 0;
2164 Returns the index of the last column, which may be at the left edge
2167 Depending on the \link setTableFlags() Tbl_scrollLastHCell\endlink flag,
2168 this may or may not be the last column.
2170 \sa maxXOffset(), maxRowOffset()
2173 int QtTableView::maxColOffset()
2175 int mx = maxXOffset();
2180 while ( col < nCols && mx > (xcd=cellWidth(col)) ) {
2190 Returns the index of the last row, which may be at the top edge of
2193 Depending on the \link setTableFlags() Tbl_scrollLastVCell\endlink flag,
2194 this may or may not be the last row.
2196 \sa maxYOffset(), maxColOffset()
2199 int QtTableView::maxRowOffset()
2201 int my = maxYOffset();
2206 while ( row < nRows && my > (ycd=cellHeight(row)) ) {
2215 void QtTableView::showOrHideScrollBars()
2217 if ( !autoUpdate() )
2220 if ( testTableFlags(Tbl_vScrollBar) ) {
2221 if ( !vScrollBar->isVisible() )
2222 sbDirty = sbDirty | verMask;
2224 if ( vScrollBar->isVisible() )
2229 if ( testTableFlags(Tbl_hScrollBar) ) {
2230 if ( !hScrollBar->isVisible() )
2231 sbDirty = sbDirty | horMask;
2233 if ( hScrollBar->isVisible() )
2237 if ( cornerSquare ) {
2238 if ( testTableFlags(Tbl_hScrollBar) &&
2239 testTableFlags(Tbl_vScrollBar) ) {
2240 if ( !cornerSquare->isVisible() )
2241 cornerSquare->show();
2243 if ( cornerSquare->isVisible() )
2244 cornerSquare->hide();
2251 Updates the scroll bars and internal state.
2253 Call this function when the table view's total size is changed;
2254 typically because the result of cellHeight() or cellWidth() have changed.
2256 This function does not repaint the widget.
2259 void QtTableView::updateTableSize()
2261 bool updateOn = autoUpdate();
2262 setAutoUpdate( FALSE );
2263 int xofs = xOffset();
2264 xOffs++; //so that setOffset will not return immediately
2265 setOffset(xofs,yOffset(),FALSE); //to calculate internal state correctly
2266 setAutoUpdate(updateOn);
2268 updateScrollBars( horSteps | horRange |
2269 verSteps | verRange );
2270 showOrHideScrollBars();