1 /**********************************************************************
2 ** $Id: qttableview.C,v 1.4 2002/11/04 00:15:54 larsbj 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"
21 #include "qdrawutil.h"
24 /* Added by J. Levon for compilation with Qt 2.3.1 */
26 #define Q_CHECK_PTR CHECK_PTR
29 #define Q_ASSERT ASSERT
32 enum ScrollBarDirtyFlags {
46 #define HSBEXT horizontalScrollBar()->sizeHint().height()
47 #define VSBEXT verticalScrollBar()->sizeHint().width()
50 class QCornerSquare : public QWidget // internal class
53 QCornerSquare( QWidget *, const char* = 0 );
54 void paintEvent( QPaintEvent * );
57 QCornerSquare::QCornerSquare( QWidget *parent, const char *name )
58 : QWidget( parent, name )
62 void QCornerSquare::paintEvent( QPaintEvent * )
69 \class QtTableView qttableview.h
70 \brief The QtTableView class provides an abstract base for tables.
74 A table view consists of a number of abstract cells organized in rows
75 and columns, and a visible part called a view. The cells are identified
76 with a row index and a column index. The top-left cell is in row 0,
79 The behavior of the widget can be finely tuned using
80 setTableFlags(); a typical subclass will consist of little more than a
81 call to setTableFlags(), some table content manipulation and an
82 implementation of paintCell(). Subclasses that need cells with
83 variable width or height must reimplement cellHeight() and/or
84 cellWidth(). Use updateTableSize() to tell QtTableView when the
85 width or height has changed.
87 When you read this documentation, it is important to understand the
88 distinctions among the four pixel coordinate systems involved.
91 \i The \e cell coordinates. (0,0) is the top-left corner of a cell.
92 Cell coordinates are used by functions such as paintCell().
94 \i The \e table coordinates. (0,0) is the top-left corner of the cell at
95 row 0 and column 0. These coordinates are absolute; that is, they are
96 independent of what part of the table is visible at the moment. They are
97 used by functions such as setXOffset() or maxYOffset().
99 \i The \e widget coordinates. (0,0) is the top-left corner of the widget,
100 \e including the frame. They are used by functions such as repaint().
102 \i The \e view coordinates. (0,0) is the top-left corner of the view, \e
103 excluding the frame. This is the least-used coordinate system; it is used by
104 functions such as viewWidth(). \endlist
106 It is rather unfortunate that we have to use four different
107 coordinate systems, but there was no alternative to provide a flexible and
110 Note: The row,column indices are always given in that order,
111 i.e., first the vertical (row), then the horizontal (column). This is
112 the opposite order of all pixel operations, which take first the
113 horizontal (x) and then the vertical (y).
115 <img src=qtablevw-m.png> <img src=qtablevw-w.png>
117 \warning the functions setNumRows(), setNumCols(), setCellHeight(),
118 setCellWidth(), setTableFlags() and clearTableFlags() may cause
119 virtual functions such as cellWidth() and cellHeight() to be called,
120 even if autoUpdate() is FALSE. This may cause errors if relevant
121 state variables are not initialized.
123 \warning Experience has shown that use of this widget tends to cause
124 more bugs than expected and our analysis indicates that the widget's
125 very flexibility is the problem. If QScrollView or QListBox can
126 easily be made to do the job you need, we recommend subclassing
127 those widgets rather than QtTableView. In addition, QScrollView makes
128 it easy to have child widgets inside tables, which QtTableView
129 doesn't support at all.
132 \link guibooks.html#fowler GUI Design Handbook: Table\endlink
137 Constructs a table view. The \a parent, \a name and \f arguments
138 are passed to the QFrame constructor.
140 The \link setTableFlags() table flags\endlink are all cleared (set to 0).
141 Set \c Tbl_autoVScrollBar or \c Tbl_autoHScrollBar to get automatic scroll
142 bars and \c Tbl_clipCellPainting to get safe clipping.
144 The \link setCellHeight() cell height\endlink and \link setCellWidth()
145 cell width\endlink are set to 0.
147 Frame line shapes (QFrame::HLink and QFrame::VLine) are disallowed;
148 see QFrame::setFrameStyle().
150 Note that the \a f argument is \e not \link setTableFlags() table
151 flags \endlink but rather \link QWidget::QWidget() widget
156 QtTableView::QtTableView( QWidget *parent, const char *name, WFlags f )
157 : QFrame( parent, name, f )
159 nRows = nCols = 0; // zero rows/cols
160 xCellOffs = yCellOffs = 0; // zero offset
161 xCellDelta = yCellDelta = 0; // zero cell offset
162 xOffs = yOffs = 0; // zero total pixel offset
163 cellH = cellW = 0; // user defined cell size
165 vScrollBar = hScrollBar = 0; // no scroll bars
168 eraseInPaint = FALSE;
170 verSnappingOff = FALSE;
172 horSnappingOff = FALSE;
173 coveringCornerSquare = FALSE;
178 Destroys the table view.
181 QtTableView::~QtTableView()
191 Reimplements QWidget::setBackgroundColor() for binary compatibility.
195 void QtTableView::setBackgroundColor( const QColor &c )
197 QWidget::setBackgroundColor( c );
203 void QtTableView::setPalette( const QPalette &p )
205 QWidget::setPalette( p );
211 void QtTableView::show()
213 showOrHideScrollBars();
219 \overload void QtTableView::repaint( bool erase )
220 Repaints the entire view.
224 Repaints the table view directly by calling paintEvent() directly
225 unless updates are disabled.
227 Erases the view area \a (x,y,w,h) if \a erase is TRUE. Parameters \a
228 (x,y) are in \e widget coordinates.
230 If \a w is negative, it is replaced with <code>width() - x</code>.
231 If \a h is negative, it is replaced with <code>height() - y</code>.
233 Doing a repaint() usually is faster than doing an update(), but
234 calling update() many times in a row will generate a single paint
237 At present, QtTableView is the only widget that reimplements \link
238 QWidget::repaint() repaint()\endlink. It does this because by
239 clearing and then repainting one cell at at time, it can make the
240 screen flicker less than it would otherwise. */
242 void QtTableView::repaint( int x, int y, int w, int h, bool erase )
244 if ( !isVisible() || testWState(WState_BlockUpdates) )
250 QRect r( x, y, w, h );
252 return; // nothing to do
254 if ( erase && backgroundMode() != NoBackground )
255 eraseInPaint = TRUE; // erase when painting
257 eraseInPaint = FALSE;
261 \overload void QtTableView::repaint( const QRect &r, bool erase )
262 Replaints rectangle \a r. If \a erase is TRUE draws the background
263 using the palette's background.
268 \fn int QtTableView::numRows() const
269 Returns the number of rows in the table.
270 \sa numCols(), setNumRows()
274 Sets the number of rows of the table to \a rows (must be non-negative).
275 Does not change topCell().
277 The table repaints itself automatically if autoUpdate() is set.
279 \sa numCols(), setNumCols(), numRows()
282 void QtTableView::setNumRows( int rows )
285 #if defined(QT_CHECK_RANGE)
286 qWarning( "QtTableView::setNumRows: (%s) Negative argument %d.",
287 name( "unnamed" ), rows );
294 if ( autoUpdate() && isVisible() ) {
295 int oldLastVisible = lastRowVisible();
296 int oldTopCell = topCell();
298 if ( autoUpdate() && isVisible() &&
299 ( oldLastVisible != lastRowVisible() || oldTopCell != topCell() ) )
300 repaint( oldTopCell != topCell() );
302 // Be more careful - if destructing, bad things might happen.
305 updateScrollBars( verRange );
310 \fn int QtTableView::numCols() const
311 Returns the number of columns in the table.
312 \sa numRows(), setNumCols()
316 Sets the number of columns of the table to \a cols (must be non-negative).
317 Does not change leftCell().
319 The table repaints itself automatically if autoUpdate() is set.
321 \sa numCols(), numRows(), setNumRows()
324 void QtTableView::setNumCols( int cols )
327 #if defined(QT_CHECK_RANGE)
328 qWarning( "QtTableView::setNumCols: (%s) Negative argument %d.",
329 name( "unnamed" ), cols );
337 if ( autoUpdate() && isVisible() ) {
338 int maxCol = lastColVisible();
339 if ( maxCol >= oldCols || maxCol >= nCols )
342 updateScrollBars( horRange );
348 \fn int QtTableView::topCell() const
349 Returns the index of the first row in the table that is visible in
350 the view. The index of the first row is 0.
351 \sa leftCell(), setTopCell()
355 Scrolls the table so that \a row becomes the top row.
356 The index of the very first row is 0.
357 \sa setYOffset(), setTopLeftCell(), setLeftCell()
360 void QtTableView::setTopCell( int row )
362 setTopLeftCell( row, -1 );
367 \fn int QtTableView::leftCell() const
368 Returns the index of the first column in the table that is visible in
369 the view. The index of the very leftmost column is 0.
370 \sa topCell(), setLeftCell()
374 Scrolls the table so that \a col becomes the leftmost
375 column. The index of the leftmost column is 0.
376 \sa setXOffset(), setTopLeftCell(), setTopCell()
379 void QtTableView::setLeftCell( int col )
381 setTopLeftCell( -1, col );
386 Scrolls the table so that the cell at row \a row and colum \a
387 col becomes the top-left cell in the view. The cell at the extreme
388 top left of the table is at position (0,0).
389 \sa setLeftCell(), setTopCell(), setOffset()
392 void QtTableView::setTopLeftCell( int row, int col )
400 if ( newX > maxXOffset() )
405 newX += cellWidth( --col ); // optimize using current! ###
411 if ( newY > maxYOffset() )
416 newY += cellHeight( --row ); // optimize using current! ###
419 setOffset( newX, newY );
424 \fn int QtTableView::xOffset() const
426 Returns the x coordinate in \e table coordinates of the pixel that is
427 currently on the left edge of the view.
429 \sa setXOffset(), yOffset(), leftCell() */
432 Scrolls the table so that \a x becomes the leftmost pixel in the view.
433 The \a x parameter is in \e table coordinates.
435 The interaction with \link setTableFlags() Tbl_snapToHGrid
438 \sa xOffset(), setYOffset(), setOffset(), setLeftCell()
441 void QtTableView::setXOffset( int x )
443 setOffset( x, yOffset() );
447 \fn int QtTableView::yOffset() const
449 Returns the y coordinate in \e table coordinates of the pixel that is
450 currently on the top edge of the view.
452 \sa setYOffset(), xOffset(), topCell()
457 Scrolls the table so that \a y becomes the top pixel in the view.
458 The \a y parameter is in \e table coordinates.
460 The interaction with \link setTableFlags() Tbl_snapToVGrid
463 \sa yOffset(), setXOffset(), setOffset(), setTopCell()
466 void QtTableView::setYOffset( int y )
468 setOffset( xOffset(), y );
472 Scrolls the table so that \a (x,y) becomes the top-left pixel
473 in the view. Parameters \a (x,y) are in \e table coordinates.
475 The interaction with \link setTableFlags() Tbl_snapTo*Grid \endlink
476 is tricky. If \a updateScrBars is TRUE, the scroll bars are
479 \sa xOffset(), yOffset(), setXOffset(), setYOffset(), setTopLeftCell()
482 void QtTableView::setOffset( int x, int y, bool updateScrBars )
484 if ( (!testTableFlags(Tbl_snapToHGrid) || xCellDelta == 0) &&
485 (!testTableFlags(Tbl_snapToVGrid) || yCellDelta == 0) &&
486 (x == xOffs && y == yOffs) )
495 if ( x > maxXOffset() )
497 xCellOffs = x / cellW;
498 if ( !testTableFlags(Tbl_snapToHGrid) ) {
499 xCellDelta = (short)(x % cellW);
505 int xn=0, xcd=0, col = 0;
506 while ( col < nCols-1 && x >= xn+(xcd=cellWidth(col)) ) {
511 if ( testTableFlags(Tbl_snapToHGrid) ) {
515 xCellDelta = (short)(x-xn);
519 if ( y > maxYOffset() )
521 yCellOffs = y / cellH;
522 if ( !testTableFlags(Tbl_snapToVGrid) ) {
523 yCellDelta = (short)(y % cellH);
529 int yn=0, yrd=0, row=0;
530 while ( row < nRows-1 && y >= yn+(yrd=cellHeight(row)) ) {
535 if ( testTableFlags(Tbl_snapToVGrid) ) {
539 yCellDelta = (short)(y-yn);
542 int dx = (x - xOffs);
543 int dy = (y - yOffs);
546 if ( autoUpdate() && isVisible() )
549 updateScrollBars( verValue | horValue );
554 \overload int QtTableView::cellWidth() const
556 Returns the column width in pixels. Returns 0 if the columns have
559 \sa setCellWidth(), cellHeight()
563 Returns the width of column \a col in pixels.
565 This function is virtual and must be reimplemented by subclasses that
566 have variable cell widths. Note that if the total table width
567 changes, updateTableSize() must be called.
569 \sa setCellWidth(), cellHeight(), totalWidth(), updateTableSize()
572 int QtTableView::cellWidth( int )
579 Sets the width in pixels of the table cells to \a cellWidth.
581 Setting it to 0 means that the column width is variable. When
582 set to 0 (this is the default) QtTableView calls the virtual function
583 cellWidth() to get the width.
585 \sa cellWidth(), setCellHeight(), totalWidth(), numCols()
588 void QtTableView::setCellWidth( int cellWidth )
590 if ( cellW == cellWidth )
592 #if defined(QT_CHECK_RANGE)
593 if ( cellWidth < 0 || cellWidth > SHRT_MAX ) {
594 qWarning( "QtTableView::setCellWidth: (%s) Argument out of range (%d)",
595 name( "unnamed" ), cellWidth );
599 cellW = (short)cellWidth;
601 updateScrollBars( horSteps | horRange );
602 if ( autoUpdate() && isVisible() )
608 \overload int QtTableView::cellHeight() const
610 Returns the row height, in pixels. Returns 0 if the rows have
613 \sa setCellHeight(), cellWidth()
618 Returns the height of row \a row in pixels.
620 This function is virtual and must be reimplemented by subclasses that
621 have variable cell heights. Note that if the total table height
622 changes, updateTableSize() must be called.
624 \sa setCellHeight(), cellWidth(), totalHeight()
627 int QtTableView::cellHeight( int )
633 Sets the height in pixels of the table cells to \a cellHeight.
635 Setting it to 0 means that the row height is variable. When set
636 to 0 (this is the default), QtTableView calls the virtual function
637 cellHeight() to get the height.
639 \sa cellHeight(), setCellWidth(), totalHeight(), numRows()
642 void QtTableView::setCellHeight( int cellHeight )
644 if ( cellH == cellHeight )
646 #if defined(QT_CHECK_RANGE)
647 if ( cellHeight < 0 || cellHeight > SHRT_MAX ) {
648 qWarning( "QtTableView::setCellHeight: (%s) Argument out of range (%d)",
649 name( "unnamed" ), cellHeight );
653 cellH = (short)cellHeight;
654 if ( autoUpdate() && isVisible() )
656 updateScrollBars( verSteps | verRange );
661 Returns the total width of the table in pixels.
663 This function is virtual and should be reimplemented by subclasses that
664 have variable cell widths and a non-trivial cellWidth() function, or a
665 large number of columns in the table.
667 The default implementation may be slow for very wide tables.
669 \sa cellWidth(), totalHeight() */
671 int QtTableView::totalWidth()
677 for( int i = 0 ; i < nCols ; i++ )
678 tw += cellWidth( i );
684 Returns the total height of the table in pixels.
686 This function is virtual and should be reimplemented by subclasses that
687 have variable cell heights and a non-trivial cellHeight() function, or a
688 large number of rows in the table.
690 The default implementation may be slow for very tall tables.
692 \sa cellHeight(), totalWidth()
695 int QtTableView::totalHeight()
701 for( int i = 0 ; i < nRows ; i++ )
702 th += cellHeight( i );
709 \fn uint QtTableView::tableFlags() const
711 Returns the union of the table flags that are currently set.
713 \sa setTableFlags(), clearTableFlags(), testTableFlags()
717 \fn bool QtTableView::testTableFlags( uint f ) const
719 Returns TRUE if any of the table flags in \a f are currently set,
722 \sa setTableFlags(), clearTableFlags(), tableFlags()
726 Sets the table flags to \a f.
728 If a flag setting changes the appearance of the table, the table is
729 repainted if - and only if - autoUpdate() is TRUE.
731 The table flags are mostly single bits, though there are some multibit
732 flags for convenience. Here is a complete list:
735 <dt> Tbl_vScrollBar <dd> - The table has a vertical scroll bar.
736 <dt> Tbl_hScrollBar <dd> - The table has a horizontal scroll bar.
737 <dt> Tbl_autoVScrollBar <dd> - The table has a vertical scroll bar if
738 - and only if - the table is taller than the view.
739 <dt> Tbl_autoHScrollBar <dd> The table has a horizontal scroll bar if
740 - and only if - the table is wider than the view.
741 <dt> Tbl_autoScrollBars <dd> - The union of the previous two flags.
742 <dt> Tbl_clipCellPainting <dd> - The table uses QPainter::setClipRect() to
743 make sure that paintCell() will not draw outside the cell
745 <dt> Tbl_cutCellsV <dd> - The table will never show part of a
746 cell at the bottom of the table; if there is not space for all of
747 a cell, the space is left blank.
748 <dt> Tbl_cutCellsH <dd> - The table will never show part of a
749 cell at the right side of the table; if there is not space for all of
750 a cell, the space is left blank.
751 <dt> Tbl_cutCells <dd> - The union of the previous two flags.
752 <dt> Tbl_scrollLastHCell <dd> - When the user scrolls horizontally,
753 let him/her scroll the last cell left until it is at the left
754 edge of the view. If this flag is not set, the user can only scroll
755 to the point where the last cell is completely visible.
756 <dt> Tbl_scrollLastVCell <dd> - When the user scrolls vertically, let
757 him/her scroll the last cell up until it is at the top edge of
758 the view. If this flag is not set, the user can only scroll to the
759 point where the last cell is completely visible.
760 <dt> Tbl_scrollLastCell <dd> - The union of the previous two flags.
761 <dt> Tbl_smoothHScrolling <dd> - The table scrolls as smoothly as
762 possible when the user scrolls horizontally. When this flag is not
763 set, scrolling is done one cell at a time.
764 <dt> Tbl_smoothVScrolling <dd> - The table scrolls as smoothly as
765 possible when scrolling vertically. When this flag is not set,
766 scrolling is done one cell at a time.
767 <dt> Tbl_smoothScrolling <dd> - The union of the previous two flags.
768 <dt> Tbl_snapToHGrid <dd> - Except when the user is actually scrolling,
769 the leftmost column shown snaps to the leftmost edge of the view.
770 <dt> Tbl_snapToVGrid <dd> - Except when the user is actually
771 scrolling, the top row snaps to the top edge of the view.
772 <dt> Tbl_snapToGrid <dd> - The union of the previous two flags.
775 You can specify more than one flag at a time using bitwise OR.
779 setTableFlags( Tbl_smoothScrolling | Tbl_autoScrollBars );
782 \warning The cutCells options (\c Tbl_cutCells, \c Tbl_cutCellsH and
783 Tbl_cutCellsV) may cause painting problems when scrollbars are
784 enabled. Do not combine cutCells and scrollbars.
787 \sa clearTableFlags(), testTableFlags(), tableFlags()
790 void QtTableView::setTableFlags( uint f )
792 f = (f ^ tFlags) & f; // clear flags already set
795 bool updateOn = autoUpdate();
796 setAutoUpdate( FALSE );
798 uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
800 if ( f & Tbl_vScrollBar ) {
801 setVerScrollBar( TRUE );
803 if ( f & Tbl_hScrollBar ) {
804 setHorScrollBar( TRUE );
806 if ( f & Tbl_autoVScrollBar ) {
807 updateScrollBars( verRange );
809 if ( f & Tbl_autoHScrollBar ) {
810 updateScrollBars( horRange );
812 if ( f & Tbl_scrollLastHCell ) {
813 updateScrollBars( horRange );
815 if ( f & Tbl_scrollLastVCell ) {
816 updateScrollBars( verRange );
818 if ( f & Tbl_snapToHGrid ) {
819 updateScrollBars( horRange );
821 if ( f & Tbl_snapToVGrid ) {
822 updateScrollBars( verRange );
824 if ( f & Tbl_snapToGrid ) { // Note: checks for 2 flags
825 if ( (f & Tbl_snapToHGrid) != 0 && xCellDelta != 0 || //have to scroll?
826 (f & Tbl_snapToVGrid) != 0 && yCellDelta != 0 ) {
827 snapToGrid( (f & Tbl_snapToHGrid) != 0, // do snapping
828 (f & Tbl_snapToVGrid) != 0 );
829 repaintMask |= Tbl_snapToGrid; // repaint table
834 setAutoUpdate( TRUE );
836 if ( isVisible() && (f & repaintMask) )
843 Clears the \link setTableFlags() table flags\endlink that are set
846 Example (clears a single flag):
848 clearTableFlags( Tbl_snapToGrid );
851 The default argument clears all flags.
853 \sa setTableFlags(), testTableFlags(), tableFlags()
856 void QtTableView::clearTableFlags( uint f )
858 f = (f ^ ~tFlags) & f; // clear flags that are already 0
861 bool updateOn = autoUpdate();
862 setAutoUpdate( FALSE );
864 uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
866 if ( f & Tbl_vScrollBar ) {
867 setVerScrollBar( FALSE );
869 if ( f & Tbl_hScrollBar ) {
870 setHorScrollBar( FALSE );
872 if ( f & Tbl_scrollLastHCell ) {
873 int maxX = maxXOffset();
874 if ( xOffs > maxX ) {
875 setOffset( maxX, yOffs );
876 repaintMask |= Tbl_scrollLastHCell;
878 updateScrollBars( horRange );
880 if ( f & Tbl_scrollLastVCell ) {
881 int maxY = maxYOffset();
882 if ( yOffs > maxY ) {
883 setOffset( xOffs, maxY );
884 repaintMask |= Tbl_scrollLastVCell;
886 updateScrollBars( verRange );
888 if ( f & Tbl_smoothScrolling ) { // Note: checks for 2 flags
889 if ((f & Tbl_smoothHScrolling) != 0 && xCellDelta != 0 ||//must scroll?
890 (f & Tbl_smoothVScrolling) != 0 && yCellDelta != 0 ) {
891 snapToGrid( (f & Tbl_smoothHScrolling) != 0, // do snapping
892 (f & Tbl_smoothVScrolling) != 0 );
893 repaintMask |= Tbl_smoothScrolling; // repaint table
896 if ( f & Tbl_snapToHGrid ) {
897 updateScrollBars( horRange );
899 if ( f & Tbl_snapToVGrid ) {
900 updateScrollBars( verRange );
903 setAutoUpdate( TRUE );
904 updateScrollBars(); // returns immediately if nothing to do
905 if ( isVisible() && (f & repaintMask) )
913 \fn bool QtTableView::autoUpdate() const
915 Returns TRUE if the view updates itself automatically whenever it
916 is changed in some way.
922 Sets the auto-update option of the table view to \a enable.
924 If \a enable is TRUE (this is the default), the view updates itself
925 automatically whenever it has changed in some way (for example, when a
926 \link setTableFlags() flag\endlink is changed).
928 If \a enable is FALSE, the view does NOT repaint itself or update
929 its internal state variables when it is changed. This can be
930 useful to avoid flicker during large changes and is singularly
931 useless otherwise. Disable auto-update, do the changes, re-enable
932 auto-update and call repaint().
934 \warning Do not leave the view in this state for a long time
935 (i.e., between events). If, for example, the user interacts with the
936 view when auto-update is off, strange things can happen.
938 Setting auto-update to TRUE does not repaint the view; you must call
939 repaint() to do this.
941 \sa autoUpdate(), repaint()
944 void QtTableView::setAutoUpdate( bool enable )
946 if ( isUpdatesEnabled() == enable )
948 setUpdatesEnabled( enable );
950 showOrHideScrollBars();
957 Repaints the cell at row \a row, column \a col if it is inside the view.
959 If \a erase is TRUE, the relevant part of the view is cleared to the
960 background color/pixmap before the contents are repainted.
965 void QtTableView::updateCell( int row, int col, bool erase )
968 if ( !colXPos( col, &xPos ) )
970 if ( !rowYPos( row, &yPos ) )
972 QRect uR = QRect( xPos, yPos,
973 cellW ? cellW : cellWidth(col),
974 cellH ? cellH : cellHeight(row) );
975 repaint( uR.intersect(viewRect()), erase );
980 \fn QRect QtTableView::cellUpdateRect() const
982 This function should be called only from the paintCell() function in
983 subclasses. It returns the portion of a cell that actually needs to be
984 updated in \e cell coordinates. This is useful only for non-trivial
990 Returns the rectangle that is the actual table, excluding any
991 frame, in \e widget coordinates.
994 QRect QtTableView::viewRect() const
996 return QRect( frameWidth(), frameWidth(), viewWidth(), viewHeight() );
1001 Returns the index of the last (bottom) row in the view.
1002 The index of the first row is 0.
1004 If no rows are visible it returns -1. This can happen if the
1005 view is too small for the first row and Tbl_cutCellsV is set.
1007 \sa lastColVisible()
1010 int QtTableView::lastRowVisible() const
1013 int row = findRawRow( maxViewY(), &cellMaxY );
1014 if ( row == -1 || row >= nRows ) { // maxViewY() past end?
1015 row = nRows - 1; // yes: return last row
1017 if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() ) {
1018 if ( row == yCellOffs ) // cut by right margin?
1019 return -1; // yes, nothing in the view
1021 row = row - 1; // cut by margin, one back
1028 Returns the index of the last (right) column in the view.
1029 The index of the first column is 0.
1031 If no columns are visible it returns -1. This can happen if the
1032 view is too narrow for the first column and Tbl_cutCellsH is set.
1034 \sa lastRowVisible()
1037 int QtTableView::lastColVisible() const
1040 int col = findRawCol( maxViewX(), &cellMaxX );
1041 if ( col == -1 || col >= nCols ) { // maxViewX() past end?
1042 col = nCols - 1; // yes: return last col
1044 if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() ) {
1045 if ( col == xCellOffs ) // cut by bottom margin?
1046 return -1; // yes, nothing in the view
1048 col = col - 1; // cell by margin, one back
1055 Returns TRUE if \a row is at least partially visible.
1059 bool QtTableView::rowIsVisible( int row ) const
1061 return rowYPos( row, 0 );
1065 Returns TRUE if \a col is at least partially visible.
1069 bool QtTableView::colIsVisible( int col ) const
1071 return colXPos( col, 0 );
1077 Called when both scroll bars are active at the same time. Covers the
1078 bottom left corner between the two scroll bars with an empty widget.
1081 void QtTableView::coverCornerSquare( bool enable )
1083 coveringCornerSquare = enable;
1084 if ( !cornerSquare && enable ) {
1085 cornerSquare = new QCornerSquare( this );
1086 Q_CHECK_PTR( cornerSquare );
1087 cornerSquare->setGeometry( maxViewX() + frameWidth() + 1,
1088 maxViewY() + frameWidth() + 1,
1092 if ( autoUpdate() && cornerSquare ) {
1094 cornerSquare->show();
1096 cornerSquare->hide();
1103 Scroll the view to a position such that:
1105 If \a horizontal is TRUE, the leftmost column shown fits snugly
1106 with the left edge of the view.
1108 If \a vertical is TRUE, the top row shown fits snugly with the top
1111 You can achieve the same effect automatically by setting any of the
1112 \link setTableFlags() Tbl_snapTo*Grid \endlink table flags.
1115 void QtTableView::snapToGrid( bool horizontal, bool vertical )
1119 if ( horizontal && xCellDelta != 0 ) {
1120 int w = cellW ? cellW : cellWidth( xCellOffs );
1121 if ( xCellDelta >= w/2 )
1122 newXCell = xCellOffs + 1;
1124 newXCell = xCellOffs;
1126 if ( vertical && yCellDelta != 0 ) {
1127 int h = cellH ? cellH : cellHeight( yCellOffs );
1128 if ( yCellDelta >= h/2 )
1129 newYCell = yCellOffs + 1;
1131 newYCell = yCellOffs;
1133 setTopLeftCell( newYCell, newXCell ); //row,column
1138 This internal slot is connected to the horizontal scroll bar's
1139 QScrollBar::valueChanged() signal.
1141 Moves the table horizontally to offset \a val without updating the
1145 void QtTableView::horSbValue( int val )
1149 if ( horSnappingOff ) {
1150 horSnappingOff = FALSE;
1151 tFlags |= Tbl_snapToHGrid;
1154 setOffset( val, yOffs, FALSE );
1159 This internal slot is connected to the horizontal scroll bar's
1160 QScrollBar::sliderMoved() signal.
1162 Scrolls the table smoothly horizontally even if \c Tbl_snapToHGrid is set.
1165 void QtTableView::horSbSliding( int val )
1167 if ( testTableFlags(Tbl_snapToHGrid) &&
1168 testTableFlags(Tbl_smoothHScrolling) ) {
1169 tFlags &= ~Tbl_snapToHGrid; // turn off snapping while sliding
1170 setOffset( val, yOffs, FALSE );
1171 tFlags |= Tbl_snapToHGrid; // turn on snapping again
1173 setOffset( val, yOffs, FALSE );
1179 This internal slot is connected to the horizontal scroll bar's
1180 QScrollBar::sliderReleased() signal.
1183 void QtTableView::horSbSlidingDone( )
1185 if ( testTableFlags(Tbl_snapToHGrid) &&
1186 testTableFlags(Tbl_smoothHScrolling) )
1187 snapToGrid( TRUE, FALSE );
1192 This internal slot is connected to the vertical scroll bar's
1193 QScrollBar::valueChanged() signal.
1195 Moves the table vertically to offset \a val without updating the
1199 void QtTableView::verSbValue( int val )
1203 if ( verSnappingOff ) {
1204 verSnappingOff = FALSE;
1205 tFlags |= Tbl_snapToVGrid;
1208 setOffset( xOffs, val, FALSE );
1213 This internal slot is connected to the vertical scroll bar's
1214 QScrollBar::sliderMoved() signal.
1216 Scrolls the table smoothly vertically even if \c Tbl_snapToVGrid is set.
1219 void QtTableView::verSbSliding( int val )
1221 if ( testTableFlags(Tbl_snapToVGrid) &&
1222 testTableFlags(Tbl_smoothVScrolling) ) {
1223 tFlags &= ~Tbl_snapToVGrid; // turn off snapping while sliding
1224 setOffset( xOffs, val, FALSE );
1225 tFlags |= Tbl_snapToVGrid; // turn on snapping again
1227 setOffset( xOffs, val, FALSE );
1233 This internal slot is connected to the vertical scroll bar's
1234 QScrollBar::sliderReleased() signal.
1237 void QtTableView::verSbSlidingDone( )
1239 if ( testTableFlags(Tbl_snapToVGrid) &&
1240 testTableFlags(Tbl_smoothVScrolling) )
1241 snapToGrid( FALSE, TRUE );
1246 This virtual function is called before painting of table cells
1247 is started. It can be reimplemented by subclasses that want to
1248 to set up the painter in a special way and that do not want to
1249 do so for each cell.
1252 void QtTableView::setupPainter( QPainter * )
1257 \fn void QtTableView::paintCell( QPainter *p, int row, int col )
1259 This pure virtual function is called to paint the single cell at \a
1260 (row,col) using \a p, which is open when paintCell() is called and
1263 The coordinate system is \link QPainter::translate() translated \endlink
1264 so that the origin is at the top-left corner of the cell to be
1265 painted, i.e. \e cell coordinates. Do not scale or shear the coordinate
1266 system (or if you do, restore the transformation matrix before you
1269 The painter is not clipped by default and for maximum efficiency. For safety,
1270 call setTableFlags(Tbl_clipCellPainting) to enable clipping.
1272 \sa paintEvent(), setTableFlags() */
1276 Handles paint events, \a e, for the table view.
1278 Calls paintCell() for the cells that needs to be repainted.
1281 void QtTableView::paintEvent( QPaintEvent *e )
1283 QRect updateR = e->rect(); // update rectangle
1285 bool e = eraseInPaint;
1290 QPainter paint( this );
1292 if ( !contentsRect().contains( updateR, TRUE ) ) {// update frame ?
1293 drawFrame( &paint );
1294 if ( updateR.left() < frameWidth() ) //###
1295 updateR.setLeft( frameWidth() );
1296 if ( updateR.top() < frameWidth() )
1297 updateR.setTop( frameWidth() );
1300 int maxWX = maxViewX();
1301 int maxWY = maxViewY();
1302 if ( updateR.right() > maxWX )
1303 updateR.setRight( maxWX );
1304 if ( updateR.bottom() > maxWY )
1305 updateR.setBottom( maxWY );
1307 setupPainter( &paint ); // prepare for painting table
1309 int firstRow = findRow( updateR.y() );
1310 int firstCol = findCol( updateR.x() );
1313 if ( !colXPos( firstCol, &xStart ) || !rowYPos( firstRow, &yStart ) ) {
1314 paint.eraseRect( updateR ); // erase area outside cells but in view
1317 int maxX = updateR.right();
1318 int maxY = updateR.bottom();
1322 int xPos = maxX + 1; // in case the while() is empty
1325 QRect winR = viewRect();
1328 #ifndef QT_NO_TRANSFORMATIONS
1332 while ( yPos <= maxY && row < nRows ) {
1333 nextY = yPos + (cellH ? cellH : cellHeight( row ));
1334 if ( testTableFlags( Tbl_cutCellsV ) && nextY > ( maxWY + 1 ) )
1338 while ( xPos <= maxX && col < nCols ) {
1339 nextX = xPos + (cellW ? cellW : cellWidth( col ));
1340 if ( testTableFlags( Tbl_cutCellsH ) && nextX > ( maxWX + 1 ) )
1343 cellR.setRect( xPos, yPos, cellW ? cellW : cellWidth(col),
1344 cellH ? cellH : cellHeight(row) );
1345 cellUR = cellR.intersect( updateR );
1346 if ( cellUR.isValid() ) {
1347 cellUpdateR = cellUR;
1348 cellUpdateR.moveBy( -xPos, -yPos ); // cell coordinates
1350 paint.eraseRect( cellUR );
1352 #ifndef QT_NO_TRANSFORMATIONS
1353 matrix.translate( xPos, yPos );
1354 paint.setWorldMatrix( matrix );
1355 if ( testTableFlags(Tbl_clipCellPainting) ||
1356 frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1357 paint.setClipRect( cellUR );
1358 paintCell( &paint, row, col );
1359 paint.setClipping( FALSE );
1361 paintCell( &paint, row, col );
1364 paint.setWorldMatrix( matrix );
1366 paint.translate( xPos, yPos );
1367 if ( testTableFlags(Tbl_clipCellPainting) ||
1368 frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1369 paint.setClipRect( cellUR );
1370 paintCell( &paint, row, col );
1371 paint.setClipping( FALSE );
1373 paintCell( &paint, row, col );
1375 paint.translate( -xPos, -yPos );
1385 // while painting we have to erase any areas in the view that
1386 // are not covered by cells but are covered by the paint event
1387 // rectangle these must be erased. We know that xPos is the last
1388 // x pixel updated + 1 and that yPos is the last y pixel updated + 1.
1390 // Note that this needs to be done regardless whether we do
1391 // eraseInPaint or not. Reason: a subclass may implement
1392 // flicker-freeness and encourage the use of repaint(FALSE).
1393 // The subclass, however, cannot draw all pixels, just those
1394 // inside the cells. So QtTableView is reponsible for all pixels
1395 // outside the cells.
1397 QRect viewR = viewRect();
1398 const QColorGroup g = colorGroup();
1400 if ( xPos <= maxX ) {
1403 r.setBottom( yPos<maxY?yPos:maxY );
1404 if ( inherits( "QMultiLineEdit" ) )
1405 paint.fillRect( r.intersect( updateR ), g.base() );
1407 paint.eraseRect( r.intersect( updateR ) );
1409 if ( yPos <= maxY ) {
1412 if ( inherits( "QMultiLineEdit" ) )
1413 paint.fillRect( r.intersect( updateR ), g.base() );
1415 paint.eraseRect( r.intersect( updateR ) );
1421 void QtTableView::resizeEvent( QResizeEvent * )
1423 updateScrollBars( horValue | verValue | horSteps | horGeometry | horRange |
1424 verSteps | verGeometry | verRange );
1425 showOrHideScrollBars();
1427 int maxX = QMIN( xOffs, maxXOffset() ); // ### can be slow
1428 int maxY = QMIN( yOffs, maxYOffset() );
1429 setOffset( maxX, maxY );
1434 Redraws all visible cells in the table view.
1437 void QtTableView::updateView()
1439 repaint( viewRect() );
1443 Returns a pointer to the vertical scroll bar mainly so you can
1444 connect() to its signals. Note that the scroll bar works in pixel
1445 values; use findRow() to translate to cell numbers.
1448 QScrollBar *QtTableView::verticalScrollBar() const
1450 QtTableView *that = (QtTableView*)this; // semantic const
1451 if ( !vScrollBar ) {
1452 QScrollBar *sb = new QScrollBar( QScrollBar::Vertical, that );
1453 #ifndef QT_NO_CURSOR
1454 sb->setCursor( arrowCursor );
1456 sb->resize( sb->sizeHint() ); // height is irrelevant
1458 sb->setTracking( FALSE );
1459 sb->setFocusPolicy( NoFocus );
1460 connect( sb, SIGNAL(valueChanged(int)),
1461 SLOT(verSbValue(int)));
1462 connect( sb, SIGNAL(sliderMoved(int)),
1463 SLOT(verSbSliding(int)));
1464 connect( sb, SIGNAL(sliderReleased()),
1465 SLOT(verSbSlidingDone()));
1467 that->vScrollBar = sb;
1474 Returns a pointer to the horizontal scroll bar mainly so you can
1475 connect() to its signals. Note that the scroll bar works in pixel
1476 values; use findCol() to translate to cell numbers.
1479 QScrollBar *QtTableView::horizontalScrollBar() const
1481 QtTableView *that = (QtTableView*)this; // semantic const
1482 if ( !hScrollBar ) {
1483 QScrollBar *sb = new QScrollBar( QScrollBar::Horizontal, that );
1484 #ifndef QT_NO_CURSOR
1485 sb->setCursor( arrowCursor );
1487 sb->resize( sb->sizeHint() ); // width is irrelevant
1488 sb->setFocusPolicy( NoFocus );
1490 sb->setTracking( FALSE );
1491 connect( sb, SIGNAL(valueChanged(int)),
1492 SLOT(horSbValue(int)));
1493 connect( sb, SIGNAL(sliderMoved(int)),
1494 SLOT(horSbSliding(int)));
1495 connect( sb, SIGNAL(sliderReleased()),
1496 SLOT(horSbSlidingDone()));
1498 that->hScrollBar = sb;
1505 Enables or disables the horizontal scroll bar, as required by
1506 setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1509 void QtTableView::setHorScrollBar( bool on, bool update )
1512 tFlags |= Tbl_hScrollBar;
1513 horizontalScrollBar(); // created
1515 updateScrollBars( horMask | verMask );
1517 sbDirty = sbDirty | (horMask | verMask);
1518 if ( testTableFlags( Tbl_vScrollBar ) )
1519 coverCornerSquare( TRUE );
1521 sbDirty = sbDirty | horMask;
1523 tFlags &= ~Tbl_hScrollBar;
1526 coverCornerSquare( FALSE );
1527 bool hideScrollBar = autoUpdate() && hScrollBar->isVisible();
1528 if ( hideScrollBar )
1531 updateScrollBars( verMask );
1533 sbDirty = sbDirty | verMask;
1534 if ( hideScrollBar && isVisible() )
1535 repaint( hScrollBar->x(), hScrollBar->y(),
1536 width() - hScrollBar->x(), hScrollBar->height() );
1544 Enables or disables the vertical scroll bar, as required by
1545 setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1548 void QtTableView::setVerScrollBar( bool on, bool update )
1551 tFlags |= Tbl_vScrollBar;
1552 verticalScrollBar(); // created
1554 updateScrollBars( verMask | horMask );
1556 sbDirty = sbDirty | (horMask | verMask);
1557 if ( testTableFlags( Tbl_hScrollBar ) )
1558 coverCornerSquare( TRUE );
1560 sbDirty = sbDirty | verMask;
1562 tFlags &= ~Tbl_vScrollBar;
1565 coverCornerSquare( FALSE );
1566 bool hideScrollBar = autoUpdate() && vScrollBar->isVisible();
1567 if ( hideScrollBar )
1570 updateScrollBars( horMask );
1572 sbDirty = sbDirty | horMask;
1573 if ( hideScrollBar && isVisible() )
1574 repaint( vScrollBar->x(), vScrollBar->y(),
1575 vScrollBar->width(), height() - vScrollBar->y() );
1584 int QtTableView::findRawRow( int yPos, int *cellMaxY, int *cellMinY,
1585 bool goOutsideView ) const
1590 if ( goOutsideView || yPos >= minViewY() && yPos <= maxViewY() ) {
1591 if ( yPos < minViewY() ) {
1592 #if defined(QT_CHECK_RANGE)
1593 qWarning( "QtTableView::findRawRow: (%s) internal error: "
1594 "yPos < minViewY() && goOutsideView "
1595 "not supported. (%d,%d)",
1596 name( "unnamed" ), yPos, yOffs );
1600 if ( cellH ) { // uniform cell height
1601 r = (yPos - minViewY() + yCellDelta)/cellH; // cell offs from top
1603 *cellMaxY = (r + 1)*cellH + minViewY() - yCellDelta - 1;
1605 *cellMinY = r*cellH + minViewY() - yCellDelta;
1606 r += yCellOffs; // absolute cell index
1607 } else { // variable cell height
1608 QtTableView *tw = (QtTableView *)this;
1610 int h = minViewY() - yCellDelta; //##arnt3
1612 Q_ASSERT( r < nRows );
1613 while ( r < nRows ) {
1615 h += tw->cellHeight( r ); // Start of next cell
1631 int QtTableView::findRawCol( int xPos, int *cellMaxX, int *cellMinX ,
1632 bool goOutsideView ) const
1637 if ( goOutsideView || xPos >= minViewX() && xPos <= maxViewX() ) {
1638 if ( xPos < minViewX() ) {
1639 #if defined(QT_CHECK_RANGE)
1640 qWarning( "QtTableView::findRawCol: (%s) internal error: "
1641 "xPos < minViewX() && goOutsideView "
1642 "not supported. (%d,%d)",
1643 name( "unnamed" ), xPos, xOffs );
1647 if ( cellW ) { // uniform cell width
1648 c = (xPos - minViewX() + xCellDelta)/cellW; //cell offs from left
1650 *cellMaxX = (c + 1)*cellW + minViewX() - xCellDelta - 1;
1652 *cellMinX = c*cellW + minViewX() - xCellDelta;
1653 c += xCellOffs; // absolute cell index
1654 } else { // variable cell width
1655 QtTableView *tw = (QtTableView *)this;
1657 int w = minViewX() - xCellDelta; //##arnt3
1659 Q_ASSERT( c < nCols );
1660 while ( c < nCols ) {
1662 w += tw->cellWidth( c ); // Start of next cell
1678 Returns the index of the row at position \a yPos, where \a yPos is in
1679 \e widget coordinates. Returns -1 if \a yPos is outside the valid
1682 \sa findCol(), rowYPos()
1685 int QtTableView::findRow( int yPos ) const
1688 int row = findRawRow( yPos, &cellMaxY );
1689 if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() )
1690 row = - 1; // cell cut by bottom margin
1698 Returns the index of the column at position \a xPos, where \a xPos is
1699 in \e widget coordinates. Returns -1 if \a xPos is outside the valid
1702 \sa findRow(), colXPos()
1705 int QtTableView::findCol( int xPos ) const
1708 int col = findRawCol( xPos, &cellMaxX );
1709 if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() )
1710 col = - 1; // cell cut by right margin
1718 Computes the position in the widget of row \a row.
1720 Returns TRUE and stores the result in \a *yPos (in \e widget
1721 coordinates) if the row is visible. Returns FALSE and does not modify
1722 \a *yPos if \a row is invisible or invalid.
1724 \sa colXPos(), findRow()
1727 bool QtTableView::rowYPos( int row, int *yPos ) const
1730 if ( row >= yCellOffs ) {
1732 int lastVisible = lastRowVisible();
1733 if ( row > lastVisible || lastVisible == -1 )
1735 y = (row - yCellOffs)*cellH + minViewY() - yCellDelta;
1738 y = minViewY() - yCellDelta; // y of leftmost cell in view
1740 QtTableView *tw = (QtTableView *)this;
1741 int maxY = maxViewY();
1742 while ( r < row && y <= maxY )
1743 y += tw->cellHeight( r++ );
1758 Computes the position in the widget of column \a col.
1760 Returns TRUE and stores the result in \a *xPos (in \e widget
1761 coordinates) if the column is visible. Returns FALSE and does not
1762 modify \a *xPos if \a col is invisible or invalid.
1764 \sa rowYPos(), findCol()
1767 bool QtTableView::colXPos( int col, int *xPos ) const
1770 if ( col >= xCellOffs ) {
1772 int lastVisible = lastColVisible();
1773 if ( col > lastVisible || lastVisible == -1 )
1775 x = (col - xCellOffs)*cellW + minViewX() - xCellDelta;
1778 x = minViewX() - xCellDelta; // x of uppermost cell in view
1780 QtTableView *tw = (QtTableView *)this;
1781 int maxX = maxViewX();
1782 while ( c < col && x <= maxX )
1783 x += tw->cellWidth( c++ );
1797 Moves the visible area of the table right by \a xPixels and
1798 down by \a yPixels pixels. Both may be negative.
1800 \warning You might find that QScrollView offers a higher-level of
1801 functionality than using QtTableView and this function.
1803 This function is \e not the same as QWidget::scroll(); in particular,
1804 the signs of \a xPixels and \a yPixels have the reverse semantics.
1806 \sa setXOffset(), setYOffset(), setOffset(), setTopCell(),
1810 void QtTableView::scroll( int xPixels, int yPixels )
1812 QWidget::scroll( -xPixels, -yPixels, contentsRect() );
1817 Returns the leftmost pixel of the table view in \e view
1818 coordinates. This excludes the frame and any header.
1820 \sa maxViewY(), viewWidth(), contentsRect()
1823 int QtTableView::minViewX() const
1825 return frameWidth();
1830 Returns the top pixel of the table view in \e view
1831 coordinates. This excludes the frame and any header.
1833 \sa maxViewX(), viewHeight(), contentsRect()
1836 int QtTableView::minViewY() const
1838 return frameWidth();
1843 Returns the rightmost pixel of the table view in \e view
1844 coordinates. This excludes the frame and any scroll bar, but
1845 includes blank pixels to the right of the visible table data.
1847 \sa maxViewY(), viewWidth(), contentsRect()
1850 int QtTableView::maxViewX() const
1852 return width() - 1 - frameWidth()
1853 - (tFlags & Tbl_vScrollBar ? VSBEXT
1859 Returns the bottom pixel of the table view in \e view
1860 coordinates. This excludes the frame and any scroll bar, but
1861 includes blank pixels below the visible table data.
1863 \sa maxViewX(), viewHeight(), contentsRect()
1866 int QtTableView::maxViewY() const
1868 return height() - 1 - frameWidth()
1869 - (tFlags & Tbl_hScrollBar ? HSBEXT
1875 Returns the width of the table view, as such, in \e view
1876 coordinates. This does not include any header, scroll bar or frame,
1877 but it does include background pixels to the right of the table data.
1879 \sa minViewX() maxViewX(), viewHeight(), contentsRect() viewRect()
1882 int QtTableView::viewWidth() const
1884 return maxViewX() - minViewX() + 1;
1889 Returns the height of the table view, as such, in \e view
1890 coordinates. This does not include any header, scroll bar or frame,
1891 but it does include background pixels below the table data.
1893 \sa minViewY() maxViewY() viewWidth() contentsRect() viewRect()
1896 int QtTableView::viewHeight() const
1898 return maxViewY() - minViewY() + 1;
1902 void QtTableView::doAutoScrollBars()
1904 int viewW = width() - frameWidth() - minViewX();
1905 int viewH = height() - frameWidth() - minViewY();
1906 bool vScrollOn = testTableFlags(Tbl_vScrollBar);
1907 bool hScrollOn = testTableFlags(Tbl_hScrollBar);
1912 if ( testTableFlags(Tbl_autoHScrollBar) ) {
1917 while ( i < nCols && w <= viewW )
1918 w += cellWidth( i++ );
1926 if ( testTableFlags(Tbl_autoVScrollBar) ) {
1931 while ( i < nRows && h <= viewH )
1932 h += cellHeight( i++ );
1941 if ( testTableFlags(Tbl_autoHScrollBar) && vScrollOn && !hScrollOn )
1942 if ( w > viewW - VSBEXT )
1945 if ( testTableFlags(Tbl_autoVScrollBar) && hScrollOn && !vScrollOn )
1946 if ( h > viewH - HSBEXT )
1949 setHorScrollBar( hScrollOn, FALSE );
1950 setVerScrollBar( vScrollOn, FALSE );
1956 \fn void QtTableView::updateScrollBars()
1958 Updates the scroll bars' contents and presence to match the table's
1959 state. Generally, you should not need to call this.
1965 Updates the scroll bars' contents and presence to match the table's
1971 void QtTableView::updateScrollBars( uint f )
1973 sbDirty = sbDirty | f;
1978 if ( testTableFlags(Tbl_autoHScrollBar) && (sbDirty & horRange) ||
1979 testTableFlags(Tbl_autoVScrollBar) && (sbDirty & verRange) )
1980 // if range change and auto
1981 doAutoScrollBars(); // turn scroll bars on/off if needed
1983 if ( !autoUpdate() ) {
1987 if ( yOffset() > 0 && testTableFlags( Tbl_autoVScrollBar ) &&
1988 !testTableFlags( Tbl_vScrollBar ) ) {
1991 if ( xOffset() > 0 && testTableFlags( Tbl_autoHScrollBar ) &&
1992 !testTableFlags( Tbl_hScrollBar ) ) {
1995 if ( !isVisible() ) {
2000 if ( testTableFlags(Tbl_hScrollBar) && (sbDirty & horMask) != 0 ) {
2001 if ( sbDirty & horGeometry )
2002 hScrollBar->setGeometry( 0,height() - HSBEXT,
2003 viewWidth() + frameWidth()*2,
2006 if ( sbDirty & horSteps ) {
2008 hScrollBar->setSteps( QMIN(cellW,viewWidth()/2), viewWidth() );
2010 hScrollBar->setSteps( 16, viewWidth() );
2013 if ( sbDirty & horRange )
2014 hScrollBar->setRange( 0, maxXOffset() );
2016 if ( sbDirty & horValue )
2017 hScrollBar->setValue( xOffs );
2019 // show scrollbar only when it has a sane geometry
2020 if ( !hScrollBar->isVisible() )
2024 if ( testTableFlags(Tbl_vScrollBar) && (sbDirty & verMask) != 0 ) {
2025 if ( sbDirty & verGeometry )
2026 vScrollBar->setGeometry( width() - VSBEXT, 0,
2028 viewHeight() + frameWidth()*2 );
2030 if ( sbDirty & verSteps ) {
2032 vScrollBar->setSteps( QMIN(cellH,viewHeight()/2), viewHeight() );
2034 vScrollBar->setSteps( 16, viewHeight() ); // fttb! ###
2037 if ( sbDirty & verRange )
2038 vScrollBar->setRange( 0, maxYOffset() );
2040 if ( sbDirty & verValue )
2041 vScrollBar->setValue( yOffs );
2043 // show scrollbar only when it has a sane geometry
2044 if ( !vScrollBar->isVisible() )
2047 if ( coveringCornerSquare &&
2048 ( (sbDirty & verGeometry ) || (sbDirty & horGeometry)) )
2049 cornerSquare->move( maxViewX() + frameWidth() + 1,
2050 maxViewY() + frameWidth() + 1 );
2057 void QtTableView::updateFrameSize()
2059 int rw = width() - ( testTableFlags(Tbl_vScrollBar) ?
2061 int rh = height() - ( testTableFlags(Tbl_hScrollBar) ?
2068 if ( autoUpdate() ) {
2069 int fh = frameRect().height();
2070 int fw = frameRect().width();
2071 setFrameRect( QRect(0,0,rw,rh) );
2074 update( QMIN(fw,rw) - frameWidth() - 2, 0, frameWidth()+4, rh );
2076 update( 0, QMIN(fh,rh) - frameWidth() - 2, rw, frameWidth()+4 );
2082 Returns the maximum horizontal offset within the table of the
2083 view's left edge in \e table coordinates.
2085 This is used mainly to set the horizontal scroll bar's range.
2087 \sa maxColOffset(), maxYOffset(), totalWidth()
2090 int QtTableView::maxXOffset()
2092 int tw = totalWidth();
2094 if ( testTableFlags(Tbl_scrollLastHCell) ) {
2096 maxOffs = tw - ( cellW ? cellW : cellWidth( nCols - 1 ) );
2098 maxOffs = tw - viewWidth();
2100 if ( testTableFlags(Tbl_snapToHGrid) ) {
2102 maxOffs = tw - (viewWidth()/cellW)*cellW;
2104 int goal = tw - viewWidth();
2106 int nextCol = nCols - 1;
2107 int nextCellWidth = cellWidth( nextCol );
2108 while ( nextCol > 0 && pos > goal + nextCellWidth ) {
2109 pos -= nextCellWidth;
2110 nextCellWidth = cellWidth( --nextCol );
2112 if ( goal + nextCellWidth == pos )
2114 else if ( goal < pos )
2120 maxOffs = tw - viewWidth();
2123 return maxOffs > 0 ? maxOffs : 0;
2128 Returns the maximum vertical offset within the table of the
2129 view's top edge in \e table coordinates.
2131 This is used mainly to set the vertical scroll bar's range.
2133 \sa maxRowOffset(), maxXOffset(), totalHeight()
2136 int QtTableView::maxYOffset()
2138 int th = totalHeight();
2140 if ( testTableFlags(Tbl_scrollLastVCell) ) {
2142 maxOffs = th - ( cellH ? cellH : cellHeight( nRows - 1 ) );
2144 maxOffs = th - viewHeight();
2146 if ( testTableFlags(Tbl_snapToVGrid) ) {
2148 maxOffs = th - (viewHeight()/cellH)*cellH;
2150 int goal = th - viewHeight();
2152 int nextRow = nRows - 1;
2153 int nextCellHeight = cellHeight( nextRow );
2154 while ( nextRow > 0 && pos > goal + nextCellHeight ) {
2155 pos -= nextCellHeight;
2156 nextCellHeight = cellHeight( --nextRow );
2158 if ( goal + nextCellHeight == pos )
2160 else if ( goal < pos )
2166 maxOffs = th - viewHeight();
2169 return maxOffs > 0 ? maxOffs : 0;
2174 Returns the index of the last column, which may be at the left edge
2177 Depending on the \link setTableFlags() Tbl_scrollLastHCell\endlink flag,
2178 this may or may not be the last column.
2180 \sa maxXOffset(), maxRowOffset()
2183 int QtTableView::maxColOffset()
2185 int mx = maxXOffset();
2190 while ( col < nCols && mx > (xcd=cellWidth(col)) ) {
2200 Returns the index of the last row, which may be at the top edge of
2203 Depending on the \link setTableFlags() Tbl_scrollLastVCell\endlink flag,
2204 this may or may not be the last row.
2206 \sa maxYOffset(), maxColOffset()
2209 int QtTableView::maxRowOffset()
2211 int my = maxYOffset();
2216 while ( row < nRows && my > (ycd=cellHeight(row)) ) {
2225 void QtTableView::showOrHideScrollBars()
2227 if ( !autoUpdate() )
2230 if ( testTableFlags(Tbl_vScrollBar) ) {
2231 if ( !vScrollBar->isVisible() )
2232 sbDirty = sbDirty | verMask;
2234 if ( vScrollBar->isVisible() )
2239 if ( testTableFlags(Tbl_hScrollBar) ) {
2240 if ( !hScrollBar->isVisible() )
2241 sbDirty = sbDirty | horMask;
2243 if ( hScrollBar->isVisible() )
2247 if ( cornerSquare ) {
2248 if ( testTableFlags(Tbl_hScrollBar) &&
2249 testTableFlags(Tbl_vScrollBar) ) {
2250 if ( !cornerSquare->isVisible() )
2251 cornerSquare->show();
2253 if ( cornerSquare->isVisible() )
2254 cornerSquare->hide();
2261 Updates the scroll bars and internal state.
2263 Call this function when the table view's total size is changed;
2264 typically because the result of cellHeight() or cellWidth() have changed.
2266 This function does not repaint the widget.
2269 void QtTableView::updateTableSize()
2271 bool updateOn = autoUpdate();
2272 setAutoUpdate( FALSE );
2273 int xofs = xOffset();
2274 xOffs++; //so that setOffset will not return immediately
2275 setOffset(xofs,yOffset(),FALSE); //to calculate internal state correctly
2276 setAutoUpdate(updateOn);
2278 updateScrollBars( horSteps | horRange |
2279 verSteps | verRange );
2280 showOrHideScrollBars();