1 /**********************************************************************
2 ** $Id: qttableview.C,v 1.3 2002/03/21 21:19:37 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 **********************************************************************/
15 #include "qttableview.h"
16 #ifndef QT_NO_QTTABLEVIEW
17 #include "qscrollbar.h"
19 #include "qdrawutil.h"
22 /* Added by J. Levon for compilation with Qt 2.3.1 */
24 #define Q_CHECK_PTR CHECK_PTR
27 #define Q_ASSERT ASSERT
30 enum ScrollBarDirtyFlags {
44 #define HSBEXT horizontalScrollBar()->sizeHint().height()
45 #define VSBEXT verticalScrollBar()->sizeHint().width()
48 class QCornerSquare : public QWidget // internal class
51 QCornerSquare( QWidget *, const char* = 0 );
52 void paintEvent( QPaintEvent * );
55 QCornerSquare::QCornerSquare( QWidget *parent, const char *name )
56 : QWidget( parent, name )
60 void QCornerSquare::paintEvent( QPaintEvent * )
67 \class QtTableView qttableview.h
68 \brief The QtTableView class provides an abstract base for tables.
72 A table view consists of a number of abstract cells organized in rows
73 and columns, and a visible part called a view. The cells are identified
74 with a row index and a column index. The top-left cell is in row 0,
77 The behavior of the widget can be finely tuned using
78 setTableFlags(); a typical subclass will consist of little more than a
79 call to setTableFlags(), some table content manipulation and an
80 implementation of paintCell(). Subclasses that need cells with
81 variable width or height must reimplement cellHeight() and/or
82 cellWidth(). Use updateTableSize() to tell QtTableView when the
83 width or height has changed.
85 When you read this documentation, it is important to understand the
86 distinctions among the four pixel coordinate systems involved.
89 \i The \e cell coordinates. (0,0) is the top-left corner of a cell.
90 Cell coordinates are used by functions such as paintCell().
92 \i The \e table coordinates. (0,0) is the top-left corner of the cell at
93 row 0 and column 0. These coordinates are absolute; that is, they are
94 independent of what part of the table is visible at the moment. They are
95 used by functions such as setXOffset() or maxYOffset().
97 \i The \e widget coordinates. (0,0) is the top-left corner of the widget,
98 \e including the frame. They are used by functions such as repaint().
100 \i The \e view coordinates. (0,0) is the top-left corner of the view, \e
101 excluding the frame. This is the least-used coordinate system; it is used by
102 functions such as viewWidth(). \endlist
104 It is rather unfortunate that we have to use four different
105 coordinate systems, but there was no alternative to provide a flexible and
108 Note: The row,column indices are always given in that order,
109 i.e., first the vertical (row), then the horizontal (column). This is
110 the opposite order of all pixel operations, which take first the
111 horizontal (x) and then the vertical (y).
113 <img src=qtablevw-m.png> <img src=qtablevw-w.png>
115 \warning the functions setNumRows(), setNumCols(), setCellHeight(),
116 setCellWidth(), setTableFlags() and clearTableFlags() may cause
117 virtual functions such as cellWidth() and cellHeight() to be called,
118 even if autoUpdate() is FALSE. This may cause errors if relevant
119 state variables are not initialized.
121 \warning Experience has shown that use of this widget tends to cause
122 more bugs than expected and our analysis indicates that the widget's
123 very flexibility is the problem. If QScrollView or QListBox can
124 easily be made to do the job you need, we recommend subclassing
125 those widgets rather than QtTableView. In addition, QScrollView makes
126 it easy to have child widgets inside tables, which QtTableView
127 doesn't support at all.
130 \link guibooks.html#fowler GUI Design Handbook: Table\endlink
135 Constructs a table view. The \a parent, \a name and \f arguments
136 are passed to the QFrame constructor.
138 The \link setTableFlags() table flags\endlink are all cleared (set to 0).
139 Set \c Tbl_autoVScrollBar or \c Tbl_autoHScrollBar to get automatic scroll
140 bars and \c Tbl_clipCellPainting to get safe clipping.
142 The \link setCellHeight() cell height\endlink and \link setCellWidth()
143 cell width\endlink are set to 0.
145 Frame line shapes (QFrame::HLink and QFrame::VLine) are disallowed;
146 see QFrame::setFrameStyle().
148 Note that the \a f argument is \e not \link setTableFlags() table
149 flags \endlink but rather \link QWidget::QWidget() widget
154 QtTableView::QtTableView( QWidget *parent, const char *name, WFlags f )
155 : QFrame( parent, name, f )
157 nRows = nCols = 0; // zero rows/cols
158 xCellOffs = yCellOffs = 0; // zero offset
159 xCellDelta = yCellDelta = 0; // zero cell offset
160 xOffs = yOffs = 0; // zero total pixel offset
161 cellH = cellW = 0; // user defined cell size
163 vScrollBar = hScrollBar = 0; // no scroll bars
166 eraseInPaint = FALSE;
168 verSnappingOff = FALSE;
170 horSnappingOff = FALSE;
171 coveringCornerSquare = FALSE;
176 Destroys the table view.
179 QtTableView::~QtTableView()
189 Reimplements QWidget::setBackgroundColor() for binary compatibility.
193 void QtTableView::setBackgroundColor( const QColor &c )
195 QWidget::setBackgroundColor( c );
201 void QtTableView::setPalette( const QPalette &p )
203 QWidget::setPalette( p );
209 void QtTableView::show()
211 showOrHideScrollBars();
217 \overload void QtTableView::repaint( bool erase )
218 Repaints the entire view.
222 Repaints the table view directly by calling paintEvent() directly
223 unless updates are disabled.
225 Erases the view area \a (x,y,w,h) if \a erase is TRUE. Parameters \a
226 (x,y) are in \e widget coordinates.
228 If \a w is negative, it is replaced with <code>width() - x</code>.
229 If \a h is negative, it is replaced with <code>height() - y</code>.
231 Doing a repaint() usually is faster than doing an update(), but
232 calling update() many times in a row will generate a single paint
235 At present, QtTableView is the only widget that reimplements \link
236 QWidget::repaint() repaint()\endlink. It does this because by
237 clearing and then repainting one cell at at time, it can make the
238 screen flicker less than it would otherwise. */
240 void QtTableView::repaint( int x, int y, int w, int h, bool erase )
242 if ( !isVisible() || testWState(WState_BlockUpdates) )
248 QRect r( x, y, w, h );
250 return; // nothing to do
252 if ( erase && backgroundMode() != NoBackground )
253 eraseInPaint = TRUE; // erase when painting
255 eraseInPaint = FALSE;
259 \overload void QtTableView::repaint( const QRect &r, bool erase )
260 Replaints rectangle \a r. If \a erase is TRUE draws the background
261 using the palette's background.
266 \fn int QtTableView::numRows() const
267 Returns the number of rows in the table.
268 \sa numCols(), setNumRows()
272 Sets the number of rows of the table to \a rows (must be non-negative).
273 Does not change topCell().
275 The table repaints itself automatically if autoUpdate() is set.
277 \sa numCols(), setNumCols(), numRows()
280 void QtTableView::setNumRows( int rows )
283 #if defined(QT_CHECK_RANGE)
284 qWarning( "QtTableView::setNumRows: (%s) Negative argument %d.",
285 name( "unnamed" ), rows );
292 if ( autoUpdate() && isVisible() ) {
293 int oldLastVisible = lastRowVisible();
294 int oldTopCell = topCell();
296 if ( autoUpdate() && isVisible() &&
297 ( oldLastVisible != lastRowVisible() || oldTopCell != topCell() ) )
298 repaint( oldTopCell != topCell() );
300 // Be more careful - if destructing, bad things might happen.
303 updateScrollBars( verRange );
308 \fn int QtTableView::numCols() const
309 Returns the number of columns in the table.
310 \sa numRows(), setNumCols()
314 Sets the number of columns of the table to \a cols (must be non-negative).
315 Does not change leftCell().
317 The table repaints itself automatically if autoUpdate() is set.
319 \sa numCols(), numRows(), setNumRows()
322 void QtTableView::setNumCols( int cols )
325 #if defined(QT_CHECK_RANGE)
326 qWarning( "QtTableView::setNumCols: (%s) Negative argument %d.",
327 name( "unnamed" ), cols );
335 if ( autoUpdate() && isVisible() ) {
336 int maxCol = lastColVisible();
337 if ( maxCol >= oldCols || maxCol >= nCols )
340 updateScrollBars( horRange );
346 \fn int QtTableView::topCell() const
347 Returns the index of the first row in the table that is visible in
348 the view. The index of the first row is 0.
349 \sa leftCell(), setTopCell()
353 Scrolls the table so that \a row becomes the top row.
354 The index of the very first row is 0.
355 \sa setYOffset(), setTopLeftCell(), setLeftCell()
358 void QtTableView::setTopCell( int row )
360 setTopLeftCell( row, -1 );
365 \fn int QtTableView::leftCell() const
366 Returns the index of the first column in the table that is visible in
367 the view. The index of the very leftmost column is 0.
368 \sa topCell(), setLeftCell()
372 Scrolls the table so that \a col becomes the leftmost
373 column. The index of the leftmost column is 0.
374 \sa setXOffset(), setTopLeftCell(), setTopCell()
377 void QtTableView::setLeftCell( int col )
379 setTopLeftCell( -1, col );
384 Scrolls the table so that the cell at row \a row and colum \a
385 col becomes the top-left cell in the view. The cell at the extreme
386 top left of the table is at position (0,0).
387 \sa setLeftCell(), setTopCell(), setOffset()
390 void QtTableView::setTopLeftCell( int row, int col )
398 if ( newX > maxXOffset() )
403 newX += cellWidth( --col ); // optimize using current! ###
409 if ( newY > maxYOffset() )
414 newY += cellHeight( --row ); // optimize using current! ###
417 setOffset( newX, newY );
422 \fn int QtTableView::xOffset() const
424 Returns the x coordinate in \e table coordinates of the pixel that is
425 currently on the left edge of the view.
427 \sa setXOffset(), yOffset(), leftCell() */
430 Scrolls the table so that \a x becomes the leftmost pixel in the view.
431 The \a x parameter is in \e table coordinates.
433 The interaction with \link setTableFlags() Tbl_snapToHGrid
436 \sa xOffset(), setYOffset(), setOffset(), setLeftCell()
439 void QtTableView::setXOffset( int x )
441 setOffset( x, yOffset() );
445 \fn int QtTableView::yOffset() const
447 Returns the y coordinate in \e table coordinates of the pixel that is
448 currently on the top edge of the view.
450 \sa setYOffset(), xOffset(), topCell()
455 Scrolls the table so that \a y becomes the top pixel in the view.
456 The \a y parameter is in \e table coordinates.
458 The interaction with \link setTableFlags() Tbl_snapToVGrid
461 \sa yOffset(), setXOffset(), setOffset(), setTopCell()
464 void QtTableView::setYOffset( int y )
466 setOffset( xOffset(), y );
470 Scrolls the table so that \a (x,y) becomes the top-left pixel
471 in the view. Parameters \a (x,y) are in \e table coordinates.
473 The interaction with \link setTableFlags() Tbl_snapTo*Grid \endlink
474 is tricky. If \a updateScrBars is TRUE, the scroll bars are
477 \sa xOffset(), yOffset(), setXOffset(), setYOffset(), setTopLeftCell()
480 void QtTableView::setOffset( int x, int y, bool updateScrBars )
482 if ( (!testTableFlags(Tbl_snapToHGrid) || xCellDelta == 0) &&
483 (!testTableFlags(Tbl_snapToVGrid) || yCellDelta == 0) &&
484 (x == xOffs && y == yOffs) )
493 if ( x > maxXOffset() )
495 xCellOffs = x / cellW;
496 if ( !testTableFlags(Tbl_snapToHGrid) ) {
497 xCellDelta = (short)(x % cellW);
503 int xn=0, xcd=0, col = 0;
504 while ( col < nCols-1 && x >= xn+(xcd=cellWidth(col)) ) {
509 if ( testTableFlags(Tbl_snapToHGrid) ) {
513 xCellDelta = (short)(x-xn);
517 if ( y > maxYOffset() )
519 yCellOffs = y / cellH;
520 if ( !testTableFlags(Tbl_snapToVGrid) ) {
521 yCellDelta = (short)(y % cellH);
527 int yn=0, yrd=0, row=0;
528 while ( row < nRows-1 && y >= yn+(yrd=cellHeight(row)) ) {
533 if ( testTableFlags(Tbl_snapToVGrid) ) {
537 yCellDelta = (short)(y-yn);
540 int dx = (x - xOffs);
541 int dy = (y - yOffs);
544 if ( autoUpdate() && isVisible() )
547 updateScrollBars( verValue | horValue );
552 \overload int QtTableView::cellWidth() const
554 Returns the column width in pixels. Returns 0 if the columns have
557 \sa setCellWidth(), cellHeight()
561 Returns the width of column \a col in pixels.
563 This function is virtual and must be reimplemented by subclasses that
564 have variable cell widths. Note that if the total table width
565 changes, updateTableSize() must be called.
567 \sa setCellWidth(), cellHeight(), totalWidth(), updateTableSize()
570 int QtTableView::cellWidth( int )
577 Sets the width in pixels of the table cells to \a cellWidth.
579 Setting it to 0 means that the column width is variable. When
580 set to 0 (this is the default) QtTableView calls the virtual function
581 cellWidth() to get the width.
583 \sa cellWidth(), setCellHeight(), totalWidth(), numCols()
586 void QtTableView::setCellWidth( int cellWidth )
588 if ( cellW == cellWidth )
590 #if defined(QT_CHECK_RANGE)
591 if ( cellWidth < 0 || cellWidth > SHRT_MAX ) {
592 qWarning( "QtTableView::setCellWidth: (%s) Argument out of range (%d)",
593 name( "unnamed" ), cellWidth );
597 cellW = (short)cellWidth;
599 updateScrollBars( horSteps | horRange );
600 if ( autoUpdate() && isVisible() )
606 \overload int QtTableView::cellHeight() const
608 Returns the row height, in pixels. Returns 0 if the rows have
611 \sa setCellHeight(), cellWidth()
616 Returns the height of row \a row in pixels.
618 This function is virtual and must be reimplemented by subclasses that
619 have variable cell heights. Note that if the total table height
620 changes, updateTableSize() must be called.
622 \sa setCellHeight(), cellWidth(), totalHeight()
625 int QtTableView::cellHeight( int )
631 Sets the height in pixels of the table cells to \a cellHeight.
633 Setting it to 0 means that the row height is variable. When set
634 to 0 (this is the default), QtTableView calls the virtual function
635 cellHeight() to get the height.
637 \sa cellHeight(), setCellWidth(), totalHeight(), numRows()
640 void QtTableView::setCellHeight( int cellHeight )
642 if ( cellH == cellHeight )
644 #if defined(QT_CHECK_RANGE)
645 if ( cellHeight < 0 || cellHeight > SHRT_MAX ) {
646 qWarning( "QtTableView::setCellHeight: (%s) Argument out of range (%d)",
647 name( "unnamed" ), cellHeight );
651 cellH = (short)cellHeight;
652 if ( autoUpdate() && isVisible() )
654 updateScrollBars( verSteps | verRange );
659 Returns the total width of the table in pixels.
661 This function is virtual and should be reimplemented by subclasses that
662 have variable cell widths and a non-trivial cellWidth() function, or a
663 large number of columns in the table.
665 The default implementation may be slow for very wide tables.
667 \sa cellWidth(), totalHeight() */
669 int QtTableView::totalWidth()
675 for( int i = 0 ; i < nCols ; i++ )
676 tw += cellWidth( i );
682 Returns the total height of the table in pixels.
684 This function is virtual and should be reimplemented by subclasses that
685 have variable cell heights and a non-trivial cellHeight() function, or a
686 large number of rows in the table.
688 The default implementation may be slow for very tall tables.
690 \sa cellHeight(), totalWidth()
693 int QtTableView::totalHeight()
699 for( int i = 0 ; i < nRows ; i++ )
700 th += cellHeight( i );
707 \fn uint QtTableView::tableFlags() const
709 Returns the union of the table flags that are currently set.
711 \sa setTableFlags(), clearTableFlags(), testTableFlags()
715 \fn bool QtTableView::testTableFlags( uint f ) const
717 Returns TRUE if any of the table flags in \a f are currently set,
720 \sa setTableFlags(), clearTableFlags(), tableFlags()
724 Sets the table flags to \a f.
726 If a flag setting changes the appearance of the table, the table is
727 repainted if - and only if - autoUpdate() is TRUE.
729 The table flags are mostly single bits, though there are some multibit
730 flags for convenience. Here is a complete list:
733 <dt> Tbl_vScrollBar <dd> - The table has a vertical scroll bar.
734 <dt> Tbl_hScrollBar <dd> - The table has a horizontal scroll bar.
735 <dt> Tbl_autoVScrollBar <dd> - The table has a vertical scroll bar if
736 - and only if - the table is taller than the view.
737 <dt> Tbl_autoHScrollBar <dd> The table has a horizontal scroll bar if
738 - and only if - the table is wider than the view.
739 <dt> Tbl_autoScrollBars <dd> - The union of the previous two flags.
740 <dt> Tbl_clipCellPainting <dd> - The table uses QPainter::setClipRect() to
741 make sure that paintCell() will not draw outside the cell
743 <dt> Tbl_cutCellsV <dd> - The table will never show part of a
744 cell at the bottom of the table; if there is not space for all of
745 a cell, the space is left blank.
746 <dt> Tbl_cutCellsH <dd> - The table will never show part of a
747 cell at the right side of the table; if there is not space for all of
748 a cell, the space is left blank.
749 <dt> Tbl_cutCells <dd> - The union of the previous two flags.
750 <dt> Tbl_scrollLastHCell <dd> - When the user scrolls horizontally,
751 let him/her scroll the last cell left until it is at the left
752 edge of the view. If this flag is not set, the user can only scroll
753 to the point where the last cell is completely visible.
754 <dt> Tbl_scrollLastVCell <dd> - When the user scrolls vertically, let
755 him/her scroll the last cell up until it is at the top edge of
756 the view. If this flag is not set, the user can only scroll to the
757 point where the last cell is completely visible.
758 <dt> Tbl_scrollLastCell <dd> - The union of the previous two flags.
759 <dt> Tbl_smoothHScrolling <dd> - The table scrolls as smoothly as
760 possible when the user scrolls horizontally. When this flag is not
761 set, scrolling is done one cell at a time.
762 <dt> Tbl_smoothVScrolling <dd> - The table scrolls as smoothly as
763 possible when scrolling vertically. When this flag is not set,
764 scrolling is done one cell at a time.
765 <dt> Tbl_smoothScrolling <dd> - The union of the previous two flags.
766 <dt> Tbl_snapToHGrid <dd> - Except when the user is actually scrolling,
767 the leftmost column shown snaps to the leftmost edge of the view.
768 <dt> Tbl_snapToVGrid <dd> - Except when the user is actually
769 scrolling, the top row snaps to the top edge of the view.
770 <dt> Tbl_snapToGrid <dd> - The union of the previous two flags.
773 You can specify more than one flag at a time using bitwise OR.
777 setTableFlags( Tbl_smoothScrolling | Tbl_autoScrollBars );
780 \warning The cutCells options (\c Tbl_cutCells, \c Tbl_cutCellsH and
781 Tbl_cutCellsV) may cause painting problems when scrollbars are
782 enabled. Do not combine cutCells and scrollbars.
785 \sa clearTableFlags(), testTableFlags(), tableFlags()
788 void QtTableView::setTableFlags( uint f )
790 f = (f ^ tFlags) & f; // clear flags already set
793 bool updateOn = autoUpdate();
794 setAutoUpdate( FALSE );
796 uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
798 if ( f & Tbl_vScrollBar ) {
799 setVerScrollBar( TRUE );
801 if ( f & Tbl_hScrollBar ) {
802 setHorScrollBar( TRUE );
804 if ( f & Tbl_autoVScrollBar ) {
805 updateScrollBars( verRange );
807 if ( f & Tbl_autoHScrollBar ) {
808 updateScrollBars( horRange );
810 if ( f & Tbl_scrollLastHCell ) {
811 updateScrollBars( horRange );
813 if ( f & Tbl_scrollLastVCell ) {
814 updateScrollBars( verRange );
816 if ( f & Tbl_snapToHGrid ) {
817 updateScrollBars( horRange );
819 if ( f & Tbl_snapToVGrid ) {
820 updateScrollBars( verRange );
822 if ( f & Tbl_snapToGrid ) { // Note: checks for 2 flags
823 if ( (f & Tbl_snapToHGrid) != 0 && xCellDelta != 0 || //have to scroll?
824 (f & Tbl_snapToVGrid) != 0 && yCellDelta != 0 ) {
825 snapToGrid( (f & Tbl_snapToHGrid) != 0, // do snapping
826 (f & Tbl_snapToVGrid) != 0 );
827 repaintMask |= Tbl_snapToGrid; // repaint table
832 setAutoUpdate( TRUE );
834 if ( isVisible() && (f & repaintMask) )
841 Clears the \link setTableFlags() table flags\endlink that are set
844 Example (clears a single flag):
846 clearTableFlags( Tbl_snapToGrid );
849 The default argument clears all flags.
851 \sa setTableFlags(), testTableFlags(), tableFlags()
854 void QtTableView::clearTableFlags( uint f )
856 f = (f ^ ~tFlags) & f; // clear flags that are already 0
859 bool updateOn = autoUpdate();
860 setAutoUpdate( FALSE );
862 uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
864 if ( f & Tbl_vScrollBar ) {
865 setVerScrollBar( FALSE );
867 if ( f & Tbl_hScrollBar ) {
868 setHorScrollBar( FALSE );
870 if ( f & Tbl_scrollLastHCell ) {
871 int maxX = maxXOffset();
872 if ( xOffs > maxX ) {
873 setOffset( maxX, yOffs );
874 repaintMask |= Tbl_scrollLastHCell;
876 updateScrollBars( horRange );
878 if ( f & Tbl_scrollLastVCell ) {
879 int maxY = maxYOffset();
880 if ( yOffs > maxY ) {
881 setOffset( xOffs, maxY );
882 repaintMask |= Tbl_scrollLastVCell;
884 updateScrollBars( verRange );
886 if ( f & Tbl_smoothScrolling ) { // Note: checks for 2 flags
887 if ((f & Tbl_smoothHScrolling) != 0 && xCellDelta != 0 ||//must scroll?
888 (f & Tbl_smoothVScrolling) != 0 && yCellDelta != 0 ) {
889 snapToGrid( (f & Tbl_smoothHScrolling) != 0, // do snapping
890 (f & Tbl_smoothVScrolling) != 0 );
891 repaintMask |= Tbl_smoothScrolling; // repaint table
894 if ( f & Tbl_snapToHGrid ) {
895 updateScrollBars( horRange );
897 if ( f & Tbl_snapToVGrid ) {
898 updateScrollBars( verRange );
901 setAutoUpdate( TRUE );
902 updateScrollBars(); // returns immediately if nothing to do
903 if ( isVisible() && (f & repaintMask) )
911 \fn bool QtTableView::autoUpdate() const
913 Returns TRUE if the view updates itself automatically whenever it
914 is changed in some way.
920 Sets the auto-update option of the table view to \a enable.
922 If \a enable is TRUE (this is the default), the view updates itself
923 automatically whenever it has changed in some way (for example, when a
924 \link setTableFlags() flag\endlink is changed).
926 If \a enable is FALSE, the view does NOT repaint itself or update
927 its internal state variables when it is changed. This can be
928 useful to avoid flicker during large changes and is singularly
929 useless otherwise. Disable auto-update, do the changes, re-enable
930 auto-update and call repaint().
932 \warning Do not leave the view in this state for a long time
933 (i.e., between events). If, for example, the user interacts with the
934 view when auto-update is off, strange things can happen.
936 Setting auto-update to TRUE does not repaint the view; you must call
937 repaint() to do this.
939 \sa autoUpdate(), repaint()
942 void QtTableView::setAutoUpdate( bool enable )
944 if ( isUpdatesEnabled() == enable )
946 setUpdatesEnabled( enable );
948 showOrHideScrollBars();
955 Repaints the cell at row \a row, column \a col if it is inside the view.
957 If \a erase is TRUE, the relevant part of the view is cleared to the
958 background color/pixmap before the contents are repainted.
963 void QtTableView::updateCell( int row, int col, bool erase )
966 if ( !colXPos( col, &xPos ) )
968 if ( !rowYPos( row, &yPos ) )
970 QRect uR = QRect( xPos, yPos,
971 cellW ? cellW : cellWidth(col),
972 cellH ? cellH : cellHeight(row) );
973 repaint( uR.intersect(viewRect()), erase );
978 \fn QRect QtTableView::cellUpdateRect() const
980 This function should be called only from the paintCell() function in
981 subclasses. It returns the portion of a cell that actually needs to be
982 updated in \e cell coordinates. This is useful only for non-trivial
988 Returns the rectangle that is the actual table, excluding any
989 frame, in \e widget coordinates.
992 QRect QtTableView::viewRect() const
994 return QRect( frameWidth(), frameWidth(), viewWidth(), viewHeight() );
999 Returns the index of the last (bottom) row in the view.
1000 The index of the first row is 0.
1002 If no rows are visible it returns -1. This can happen if the
1003 view is too small for the first row and Tbl_cutCellsV is set.
1005 \sa lastColVisible()
1008 int QtTableView::lastRowVisible() const
1011 int row = findRawRow( maxViewY(), &cellMaxY );
1012 if ( row == -1 || row >= nRows ) { // maxViewY() past end?
1013 row = nRows - 1; // yes: return last row
1015 if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() ) {
1016 if ( row == yCellOffs ) // cut by right margin?
1017 return -1; // yes, nothing in the view
1019 row = row - 1; // cut by margin, one back
1026 Returns the index of the last (right) column in the view.
1027 The index of the first column is 0.
1029 If no columns are visible it returns -1. This can happen if the
1030 view is too narrow for the first column and Tbl_cutCellsH is set.
1032 \sa lastRowVisible()
1035 int QtTableView::lastColVisible() const
1038 int col = findRawCol( maxViewX(), &cellMaxX );
1039 if ( col == -1 || col >= nCols ) { // maxViewX() past end?
1040 col = nCols - 1; // yes: return last col
1042 if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() ) {
1043 if ( col == xCellOffs ) // cut by bottom margin?
1044 return -1; // yes, nothing in the view
1046 col = col - 1; // cell by margin, one back
1053 Returns TRUE if \a row is at least partially visible.
1057 bool QtTableView::rowIsVisible( int row ) const
1059 return rowYPos( row, 0 );
1063 Returns TRUE if \a col is at least partially visible.
1067 bool QtTableView::colIsVisible( int col ) const
1069 return colXPos( col, 0 );
1075 Called when both scroll bars are active at the same time. Covers the
1076 bottom left corner between the two scroll bars with an empty widget.
1079 void QtTableView::coverCornerSquare( bool enable )
1081 coveringCornerSquare = enable;
1082 if ( !cornerSquare && enable ) {
1083 cornerSquare = new QCornerSquare( this );
1084 Q_CHECK_PTR( cornerSquare );
1085 cornerSquare->setGeometry( maxViewX() + frameWidth() + 1,
1086 maxViewY() + frameWidth() + 1,
1090 if ( autoUpdate() && cornerSquare ) {
1092 cornerSquare->show();
1094 cornerSquare->hide();
1101 Scroll the view to a position such that:
1103 If \a horizontal is TRUE, the leftmost column shown fits snugly
1104 with the left edge of the view.
1106 If \a vertical is TRUE, the top row shown fits snugly with the top
1109 You can achieve the same effect automatically by setting any of the
1110 \link setTableFlags() Tbl_snapTo*Grid \endlink table flags.
1113 void QtTableView::snapToGrid( bool horizontal, bool vertical )
1117 if ( horizontal && xCellDelta != 0 ) {
1118 int w = cellW ? cellW : cellWidth( xCellOffs );
1119 if ( xCellDelta >= w/2 )
1120 newXCell = xCellOffs + 1;
1122 newXCell = xCellOffs;
1124 if ( vertical && yCellDelta != 0 ) {
1125 int h = cellH ? cellH : cellHeight( yCellOffs );
1126 if ( yCellDelta >= h/2 )
1127 newYCell = yCellOffs + 1;
1129 newYCell = yCellOffs;
1131 setTopLeftCell( newYCell, newXCell ); //row,column
1136 This internal slot is connected to the horizontal scroll bar's
1137 QScrollBar::valueChanged() signal.
1139 Moves the table horizontally to offset \a val without updating the
1143 void QtTableView::horSbValue( int val )
1147 if ( horSnappingOff ) {
1148 horSnappingOff = FALSE;
1149 tFlags |= Tbl_snapToHGrid;
1152 setOffset( val, yOffs, FALSE );
1157 This internal slot is connected to the horizontal scroll bar's
1158 QScrollBar::sliderMoved() signal.
1160 Scrolls the table smoothly horizontally even if \c Tbl_snapToHGrid is set.
1163 void QtTableView::horSbSliding( int val )
1165 if ( testTableFlags(Tbl_snapToHGrid) &&
1166 testTableFlags(Tbl_smoothHScrolling) ) {
1167 tFlags &= ~Tbl_snapToHGrid; // turn off snapping while sliding
1168 setOffset( val, yOffs, FALSE );
1169 tFlags |= Tbl_snapToHGrid; // turn on snapping again
1171 setOffset( val, yOffs, FALSE );
1177 This internal slot is connected to the horizontal scroll bar's
1178 QScrollBar::sliderReleased() signal.
1181 void QtTableView::horSbSlidingDone( )
1183 if ( testTableFlags(Tbl_snapToHGrid) &&
1184 testTableFlags(Tbl_smoothHScrolling) )
1185 snapToGrid( TRUE, FALSE );
1190 This internal slot is connected to the vertical scroll bar's
1191 QScrollBar::valueChanged() signal.
1193 Moves the table vertically to offset \a val without updating the
1197 void QtTableView::verSbValue( int val )
1201 if ( verSnappingOff ) {
1202 verSnappingOff = FALSE;
1203 tFlags |= Tbl_snapToVGrid;
1206 setOffset( xOffs, val, FALSE );
1211 This internal slot is connected to the vertical scroll bar's
1212 QScrollBar::sliderMoved() signal.
1214 Scrolls the table smoothly vertically even if \c Tbl_snapToVGrid is set.
1217 void QtTableView::verSbSliding( int val )
1219 if ( testTableFlags(Tbl_snapToVGrid) &&
1220 testTableFlags(Tbl_smoothVScrolling) ) {
1221 tFlags &= ~Tbl_snapToVGrid; // turn off snapping while sliding
1222 setOffset( xOffs, val, FALSE );
1223 tFlags |= Tbl_snapToVGrid; // turn on snapping again
1225 setOffset( xOffs, val, FALSE );
1231 This internal slot is connected to the vertical scroll bar's
1232 QScrollBar::sliderReleased() signal.
1235 void QtTableView::verSbSlidingDone( )
1237 if ( testTableFlags(Tbl_snapToVGrid) &&
1238 testTableFlags(Tbl_smoothVScrolling) )
1239 snapToGrid( FALSE, TRUE );
1244 This virtual function is called before painting of table cells
1245 is started. It can be reimplemented by subclasses that want to
1246 to set up the painter in a special way and that do not want to
1247 do so for each cell.
1250 void QtTableView::setupPainter( QPainter * )
1255 \fn void QtTableView::paintCell( QPainter *p, int row, int col )
1257 This pure virtual function is called to paint the single cell at \a
1258 (row,col) using \a p, which is open when paintCell() is called and
1261 The coordinate system is \link QPainter::translate() translated \endlink
1262 so that the origin is at the top-left corner of the cell to be
1263 painted, i.e. \e cell coordinates. Do not scale or shear the coordinate
1264 system (or if you do, restore the transformation matrix before you
1267 The painter is not clipped by default and for maximum efficiency. For safety,
1268 call setTableFlags(Tbl_clipCellPainting) to enable clipping.
1270 \sa paintEvent(), setTableFlags() */
1274 Handles paint events, \a e, for the table view.
1276 Calls paintCell() for the cells that needs to be repainted.
1279 void QtTableView::paintEvent( QPaintEvent *e )
1281 QRect updateR = e->rect(); // update rectangle
1283 bool e = eraseInPaint;
1288 QPainter paint( this );
1290 if ( !contentsRect().contains( updateR, TRUE ) ) {// update frame ?
1291 drawFrame( &paint );
1292 if ( updateR.left() < frameWidth() ) //###
1293 updateR.setLeft( frameWidth() );
1294 if ( updateR.top() < frameWidth() )
1295 updateR.setTop( frameWidth() );
1298 int maxWX = maxViewX();
1299 int maxWY = maxViewY();
1300 if ( updateR.right() > maxWX )
1301 updateR.setRight( maxWX );
1302 if ( updateR.bottom() > maxWY )
1303 updateR.setBottom( maxWY );
1305 setupPainter( &paint ); // prepare for painting table
1307 int firstRow = findRow( updateR.y() );
1308 int firstCol = findCol( updateR.x() );
1311 if ( !colXPos( firstCol, &xStart ) || !rowYPos( firstRow, &yStart ) ) {
1312 paint.eraseRect( updateR ); // erase area outside cells but in view
1315 int maxX = updateR.right();
1316 int maxY = updateR.bottom();
1320 int xPos = maxX + 1; // in case the while() is empty
1323 QRect winR = viewRect();
1326 #ifndef QT_NO_TRANSFORMATIONS
1330 while ( yPos <= maxY && row < nRows ) {
1331 nextY = yPos + (cellH ? cellH : cellHeight( row ));
1332 if ( testTableFlags( Tbl_cutCellsV ) && nextY > ( maxWY + 1 ) )
1336 while ( xPos <= maxX && col < nCols ) {
1337 nextX = xPos + (cellW ? cellW : cellWidth( col ));
1338 if ( testTableFlags( Tbl_cutCellsH ) && nextX > ( maxWX + 1 ) )
1341 cellR.setRect( xPos, yPos, cellW ? cellW : cellWidth(col),
1342 cellH ? cellH : cellHeight(row) );
1343 cellUR = cellR.intersect( updateR );
1344 if ( cellUR.isValid() ) {
1345 cellUpdateR = cellUR;
1346 cellUpdateR.moveBy( -xPos, -yPos ); // cell coordinates
1348 paint.eraseRect( cellUR );
1350 #ifndef QT_NO_TRANSFORMATIONS
1351 matrix.translate( xPos, yPos );
1352 paint.setWorldMatrix( matrix );
1353 if ( testTableFlags(Tbl_clipCellPainting) ||
1354 frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1355 paint.setClipRect( cellUR );
1356 paintCell( &paint, row, col );
1357 paint.setClipping( FALSE );
1359 paintCell( &paint, row, col );
1362 paint.setWorldMatrix( matrix );
1364 paint.translate( xPos, yPos );
1365 if ( testTableFlags(Tbl_clipCellPainting) ||
1366 frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1367 paint.setClipRect( cellUR );
1368 paintCell( &paint, row, col );
1369 paint.setClipping( FALSE );
1371 paintCell( &paint, row, col );
1373 paint.translate( -xPos, -yPos );
1383 // while painting we have to erase any areas in the view that
1384 // are not covered by cells but are covered by the paint event
1385 // rectangle these must be erased. We know that xPos is the last
1386 // x pixel updated + 1 and that yPos is the last y pixel updated + 1.
1388 // Note that this needs to be done regardless whether we do
1389 // eraseInPaint or not. Reason: a subclass may implement
1390 // flicker-freeness and encourage the use of repaint(FALSE).
1391 // The subclass, however, cannot draw all pixels, just those
1392 // inside the cells. So QtTableView is reponsible for all pixels
1393 // outside the cells.
1395 QRect viewR = viewRect();
1396 const QColorGroup g = colorGroup();
1398 if ( xPos <= maxX ) {
1401 r.setBottom( yPos<maxY?yPos:maxY );
1402 if ( inherits( "QMultiLineEdit" ) )
1403 paint.fillRect( r.intersect( updateR ), g.base() );
1405 paint.eraseRect( r.intersect( updateR ) );
1407 if ( yPos <= maxY ) {
1410 if ( inherits( "QMultiLineEdit" ) )
1411 paint.fillRect( r.intersect( updateR ), g.base() );
1413 paint.eraseRect( r.intersect( updateR ) );
1419 void QtTableView::resizeEvent( QResizeEvent * )
1421 updateScrollBars( horValue | verValue | horSteps | horGeometry | horRange |
1422 verSteps | verGeometry | verRange );
1423 showOrHideScrollBars();
1425 int maxX = QMIN( xOffs, maxXOffset() ); // ### can be slow
1426 int maxY = QMIN( yOffs, maxYOffset() );
1427 setOffset( maxX, maxY );
1432 Redraws all visible cells in the table view.
1435 void QtTableView::updateView()
1437 repaint( viewRect() );
1441 Returns a pointer to the vertical scroll bar mainly so you can
1442 connect() to its signals. Note that the scroll bar works in pixel
1443 values; use findRow() to translate to cell numbers.
1446 QScrollBar *QtTableView::verticalScrollBar() const
1448 QtTableView *that = (QtTableView*)this; // semantic const
1449 if ( !vScrollBar ) {
1450 QScrollBar *sb = new QScrollBar( QScrollBar::Vertical, that );
1451 #ifndef QT_NO_CURSOR
1452 sb->setCursor( arrowCursor );
1454 sb->resize( sb->sizeHint() ); // height is irrelevant
1456 sb->setTracking( FALSE );
1457 sb->setFocusPolicy( NoFocus );
1458 connect( sb, SIGNAL(valueChanged(int)),
1459 SLOT(verSbValue(int)));
1460 connect( sb, SIGNAL(sliderMoved(int)),
1461 SLOT(verSbSliding(int)));
1462 connect( sb, SIGNAL(sliderReleased()),
1463 SLOT(verSbSlidingDone()));
1465 that->vScrollBar = sb;
1472 Returns a pointer to the horizontal scroll bar mainly so you can
1473 connect() to its signals. Note that the scroll bar works in pixel
1474 values; use findCol() to translate to cell numbers.
1477 QScrollBar *QtTableView::horizontalScrollBar() const
1479 QtTableView *that = (QtTableView*)this; // semantic const
1480 if ( !hScrollBar ) {
1481 QScrollBar *sb = new QScrollBar( QScrollBar::Horizontal, that );
1482 #ifndef QT_NO_CURSOR
1483 sb->setCursor( arrowCursor );
1485 sb->resize( sb->sizeHint() ); // width is irrelevant
1486 sb->setFocusPolicy( NoFocus );
1488 sb->setTracking( FALSE );
1489 connect( sb, SIGNAL(valueChanged(int)),
1490 SLOT(horSbValue(int)));
1491 connect( sb, SIGNAL(sliderMoved(int)),
1492 SLOT(horSbSliding(int)));
1493 connect( sb, SIGNAL(sliderReleased()),
1494 SLOT(horSbSlidingDone()));
1496 that->hScrollBar = sb;
1503 Enables or disables the horizontal scroll bar, as required by
1504 setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1507 void QtTableView::setHorScrollBar( bool on, bool update )
1510 tFlags |= Tbl_hScrollBar;
1511 horizontalScrollBar(); // created
1513 updateScrollBars( horMask | verMask );
1515 sbDirty = sbDirty | (horMask | verMask);
1516 if ( testTableFlags( Tbl_vScrollBar ) )
1517 coverCornerSquare( TRUE );
1519 sbDirty = sbDirty | horMask;
1521 tFlags &= ~Tbl_hScrollBar;
1524 coverCornerSquare( FALSE );
1525 bool hideScrollBar = autoUpdate() && hScrollBar->isVisible();
1526 if ( hideScrollBar )
1529 updateScrollBars( verMask );
1531 sbDirty = sbDirty | verMask;
1532 if ( hideScrollBar && isVisible() )
1533 repaint( hScrollBar->x(), hScrollBar->y(),
1534 width() - hScrollBar->x(), hScrollBar->height() );
1542 Enables or disables the vertical scroll bar, as required by
1543 setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1546 void QtTableView::setVerScrollBar( bool on, bool update )
1549 tFlags |= Tbl_vScrollBar;
1550 verticalScrollBar(); // created
1552 updateScrollBars( verMask | horMask );
1554 sbDirty = sbDirty | (horMask | verMask);
1555 if ( testTableFlags( Tbl_hScrollBar ) )
1556 coverCornerSquare( TRUE );
1558 sbDirty = sbDirty | verMask;
1560 tFlags &= ~Tbl_vScrollBar;
1563 coverCornerSquare( FALSE );
1564 bool hideScrollBar = autoUpdate() && vScrollBar->isVisible();
1565 if ( hideScrollBar )
1568 updateScrollBars( horMask );
1570 sbDirty = sbDirty | horMask;
1571 if ( hideScrollBar && isVisible() )
1572 repaint( vScrollBar->x(), vScrollBar->y(),
1573 vScrollBar->width(), height() - vScrollBar->y() );
1582 int QtTableView::findRawRow( int yPos, int *cellMaxY, int *cellMinY,
1583 bool goOutsideView ) const
1588 if ( goOutsideView || yPos >= minViewY() && yPos <= maxViewY() ) {
1589 if ( yPos < minViewY() ) {
1590 #if defined(QT_CHECK_RANGE)
1591 qWarning( "QtTableView::findRawRow: (%s) internal error: "
1592 "yPos < minViewY() && goOutsideView "
1593 "not supported. (%d,%d)",
1594 name( "unnamed" ), yPos, yOffs );
1598 if ( cellH ) { // uniform cell height
1599 r = (yPos - minViewY() + yCellDelta)/cellH; // cell offs from top
1601 *cellMaxY = (r + 1)*cellH + minViewY() - yCellDelta - 1;
1603 *cellMinY = r*cellH + minViewY() - yCellDelta;
1604 r += yCellOffs; // absolute cell index
1605 } else { // variable cell height
1606 QtTableView *tw = (QtTableView *)this;
1608 int h = minViewY() - yCellDelta; //##arnt3
1610 Q_ASSERT( r < nRows );
1611 while ( r < nRows ) {
1613 h += tw->cellHeight( r ); // Start of next cell
1629 int QtTableView::findRawCol( int xPos, int *cellMaxX, int *cellMinX ,
1630 bool goOutsideView ) const
1635 if ( goOutsideView || xPos >= minViewX() && xPos <= maxViewX() ) {
1636 if ( xPos < minViewX() ) {
1637 #if defined(QT_CHECK_RANGE)
1638 qWarning( "QtTableView::findRawCol: (%s) internal error: "
1639 "xPos < minViewX() && goOutsideView "
1640 "not supported. (%d,%d)",
1641 name( "unnamed" ), xPos, xOffs );
1645 if ( cellW ) { // uniform cell width
1646 c = (xPos - minViewX() + xCellDelta)/cellW; //cell offs from left
1648 *cellMaxX = (c + 1)*cellW + minViewX() - xCellDelta - 1;
1650 *cellMinX = c*cellW + minViewX() - xCellDelta;
1651 c += xCellOffs; // absolute cell index
1652 } else { // variable cell width
1653 QtTableView *tw = (QtTableView *)this;
1655 int w = minViewX() - xCellDelta; //##arnt3
1657 Q_ASSERT( c < nCols );
1658 while ( c < nCols ) {
1660 w += tw->cellWidth( c ); // Start of next cell
1676 Returns the index of the row at position \a yPos, where \a yPos is in
1677 \e widget coordinates. Returns -1 if \a yPos is outside the valid
1680 \sa findCol(), rowYPos()
1683 int QtTableView::findRow( int yPos ) const
1686 int row = findRawRow( yPos, &cellMaxY );
1687 if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() )
1688 row = - 1; // cell cut by bottom margin
1696 Returns the index of the column at position \a xPos, where \a xPos is
1697 in \e widget coordinates. Returns -1 if \a xPos is outside the valid
1700 \sa findRow(), colXPos()
1703 int QtTableView::findCol( int xPos ) const
1706 int col = findRawCol( xPos, &cellMaxX );
1707 if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() )
1708 col = - 1; // cell cut by right margin
1716 Computes the position in the widget of row \a row.
1718 Returns TRUE and stores the result in \a *yPos (in \e widget
1719 coordinates) if the row is visible. Returns FALSE and does not modify
1720 \a *yPos if \a row is invisible or invalid.
1722 \sa colXPos(), findRow()
1725 bool QtTableView::rowYPos( int row, int *yPos ) const
1728 if ( row >= yCellOffs ) {
1730 int lastVisible = lastRowVisible();
1731 if ( row > lastVisible || lastVisible == -1 )
1733 y = (row - yCellOffs)*cellH + minViewY() - yCellDelta;
1736 y = minViewY() - yCellDelta; // y of leftmost cell in view
1738 QtTableView *tw = (QtTableView *)this;
1739 int maxY = maxViewY();
1740 while ( r < row && y <= maxY )
1741 y += tw->cellHeight( r++ );
1756 Computes the position in the widget of column \a col.
1758 Returns TRUE and stores the result in \a *xPos (in \e widget
1759 coordinates) if the column is visible. Returns FALSE and does not
1760 modify \a *xPos if \a col is invisible or invalid.
1762 \sa rowYPos(), findCol()
1765 bool QtTableView::colXPos( int col, int *xPos ) const
1768 if ( col >= xCellOffs ) {
1770 int lastVisible = lastColVisible();
1771 if ( col > lastVisible || lastVisible == -1 )
1773 x = (col - xCellOffs)*cellW + minViewX() - xCellDelta;
1776 x = minViewX() - xCellDelta; // x of uppermost cell in view
1778 QtTableView *tw = (QtTableView *)this;
1779 int maxX = maxViewX();
1780 while ( c < col && x <= maxX )
1781 x += tw->cellWidth( c++ );
1795 Moves the visible area of the table right by \a xPixels and
1796 down by \a yPixels pixels. Both may be negative.
1798 \warning You might find that QScrollView offers a higher-level of
1799 functionality than using QtTableView and this function.
1801 This function is \e not the same as QWidget::scroll(); in particular,
1802 the signs of \a xPixels and \a yPixels have the reverse semantics.
1804 \sa setXOffset(), setYOffset(), setOffset(), setTopCell(),
1808 void QtTableView::scroll( int xPixels, int yPixels )
1810 QWidget::scroll( -xPixels, -yPixels, contentsRect() );
1815 Returns the leftmost pixel of the table view in \e view
1816 coordinates. This excludes the frame and any header.
1818 \sa maxViewY(), viewWidth(), contentsRect()
1821 int QtTableView::minViewX() const
1823 return frameWidth();
1828 Returns the top pixel of the table view in \e view
1829 coordinates. This excludes the frame and any header.
1831 \sa maxViewX(), viewHeight(), contentsRect()
1834 int QtTableView::minViewY() const
1836 return frameWidth();
1841 Returns the rightmost pixel of the table view in \e view
1842 coordinates. This excludes the frame and any scroll bar, but
1843 includes blank pixels to the right of the visible table data.
1845 \sa maxViewY(), viewWidth(), contentsRect()
1848 int QtTableView::maxViewX() const
1850 return width() - 1 - frameWidth()
1851 - (tFlags & Tbl_vScrollBar ? VSBEXT
1857 Returns the bottom pixel of the table view in \e view
1858 coordinates. This excludes the frame and any scroll bar, but
1859 includes blank pixels below the visible table data.
1861 \sa maxViewX(), viewHeight(), contentsRect()
1864 int QtTableView::maxViewY() const
1866 return height() - 1 - frameWidth()
1867 - (tFlags & Tbl_hScrollBar ? HSBEXT
1873 Returns the width of the table view, as such, in \e view
1874 coordinates. This does not include any header, scroll bar or frame,
1875 but it does include background pixels to the right of the table data.
1877 \sa minViewX() maxViewX(), viewHeight(), contentsRect() viewRect()
1880 int QtTableView::viewWidth() const
1882 return maxViewX() - minViewX() + 1;
1887 Returns the height of the table view, as such, in \e view
1888 coordinates. This does not include any header, scroll bar or frame,
1889 but it does include background pixels below the table data.
1891 \sa minViewY() maxViewY() viewWidth() contentsRect() viewRect()
1894 int QtTableView::viewHeight() const
1896 return maxViewY() - minViewY() + 1;
1900 void QtTableView::doAutoScrollBars()
1902 int viewW = width() - frameWidth() - minViewX();
1903 int viewH = height() - frameWidth() - minViewY();
1904 bool vScrollOn = testTableFlags(Tbl_vScrollBar);
1905 bool hScrollOn = testTableFlags(Tbl_hScrollBar);
1910 if ( testTableFlags(Tbl_autoHScrollBar) ) {
1915 while ( i < nCols && w <= viewW )
1916 w += cellWidth( i++ );
1924 if ( testTableFlags(Tbl_autoVScrollBar) ) {
1929 while ( i < nRows && h <= viewH )
1930 h += cellHeight( i++ );
1939 if ( testTableFlags(Tbl_autoHScrollBar) && vScrollOn && !hScrollOn )
1940 if ( w > viewW - VSBEXT )
1943 if ( testTableFlags(Tbl_autoVScrollBar) && hScrollOn && !vScrollOn )
1944 if ( h > viewH - HSBEXT )
1947 setHorScrollBar( hScrollOn, FALSE );
1948 setVerScrollBar( vScrollOn, FALSE );
1954 \fn void QtTableView::updateScrollBars()
1956 Updates the scroll bars' contents and presence to match the table's
1957 state. Generally, you should not need to call this.
1963 Updates the scroll bars' contents and presence to match the table's
1969 void QtTableView::updateScrollBars( uint f )
1971 sbDirty = sbDirty | f;
1976 if ( testTableFlags(Tbl_autoHScrollBar) && (sbDirty & horRange) ||
1977 testTableFlags(Tbl_autoVScrollBar) && (sbDirty & verRange) )
1978 // if range change and auto
1979 doAutoScrollBars(); // turn scroll bars on/off if needed
1981 if ( !autoUpdate() ) {
1985 if ( yOffset() > 0 && testTableFlags( Tbl_autoVScrollBar ) &&
1986 !testTableFlags( Tbl_vScrollBar ) ) {
1989 if ( xOffset() > 0 && testTableFlags( Tbl_autoHScrollBar ) &&
1990 !testTableFlags( Tbl_hScrollBar ) ) {
1993 if ( !isVisible() ) {
1998 if ( testTableFlags(Tbl_hScrollBar) && (sbDirty & horMask) != 0 ) {
1999 if ( sbDirty & horGeometry )
2000 hScrollBar->setGeometry( 0,height() - HSBEXT,
2001 viewWidth() + frameWidth()*2,
2004 if ( sbDirty & horSteps ) {
2006 hScrollBar->setSteps( QMIN(cellW,viewWidth()/2), viewWidth() );
2008 hScrollBar->setSteps( 16, viewWidth() );
2011 if ( sbDirty & horRange )
2012 hScrollBar->setRange( 0, maxXOffset() );
2014 if ( sbDirty & horValue )
2015 hScrollBar->setValue( xOffs );
2017 // show scrollbar only when it has a sane geometry
2018 if ( !hScrollBar->isVisible() )
2022 if ( testTableFlags(Tbl_vScrollBar) && (sbDirty & verMask) != 0 ) {
2023 if ( sbDirty & verGeometry )
2024 vScrollBar->setGeometry( width() - VSBEXT, 0,
2026 viewHeight() + frameWidth()*2 );
2028 if ( sbDirty & verSteps ) {
2030 vScrollBar->setSteps( QMIN(cellH,viewHeight()/2), viewHeight() );
2032 vScrollBar->setSteps( 16, viewHeight() ); // fttb! ###
2035 if ( sbDirty & verRange )
2036 vScrollBar->setRange( 0, maxYOffset() );
2038 if ( sbDirty & verValue )
2039 vScrollBar->setValue( yOffs );
2041 // show scrollbar only when it has a sane geometry
2042 if ( !vScrollBar->isVisible() )
2045 if ( coveringCornerSquare &&
2046 ( (sbDirty & verGeometry ) || (sbDirty & horGeometry)) )
2047 cornerSquare->move( maxViewX() + frameWidth() + 1,
2048 maxViewY() + frameWidth() + 1 );
2055 void QtTableView::updateFrameSize()
2057 int rw = width() - ( testTableFlags(Tbl_vScrollBar) ?
2059 int rh = height() - ( testTableFlags(Tbl_hScrollBar) ?
2066 if ( autoUpdate() ) {
2067 int fh = frameRect().height();
2068 int fw = frameRect().width();
2069 setFrameRect( QRect(0,0,rw,rh) );
2072 update( QMIN(fw,rw) - frameWidth() - 2, 0, frameWidth()+4, rh );
2074 update( 0, QMIN(fh,rh) - frameWidth() - 2, rw, frameWidth()+4 );
2080 Returns the maximum horizontal offset within the table of the
2081 view's left edge in \e table coordinates.
2083 This is used mainly to set the horizontal scroll bar's range.
2085 \sa maxColOffset(), maxYOffset(), totalWidth()
2088 int QtTableView::maxXOffset()
2090 int tw = totalWidth();
2092 if ( testTableFlags(Tbl_scrollLastHCell) ) {
2094 maxOffs = tw - ( cellW ? cellW : cellWidth( nCols - 1 ) );
2096 maxOffs = tw - viewWidth();
2098 if ( testTableFlags(Tbl_snapToHGrid) ) {
2100 maxOffs = tw - (viewWidth()/cellW)*cellW;
2102 int goal = tw - viewWidth();
2104 int nextCol = nCols - 1;
2105 int nextCellWidth = cellWidth( nextCol );
2106 while ( nextCol > 0 && pos > goal + nextCellWidth ) {
2107 pos -= nextCellWidth;
2108 nextCellWidth = cellWidth( --nextCol );
2110 if ( goal + nextCellWidth == pos )
2112 else if ( goal < pos )
2118 maxOffs = tw - viewWidth();
2121 return maxOffs > 0 ? maxOffs : 0;
2126 Returns the maximum vertical offset within the table of the
2127 view's top edge in \e table coordinates.
2129 This is used mainly to set the vertical scroll bar's range.
2131 \sa maxRowOffset(), maxXOffset(), totalHeight()
2134 int QtTableView::maxYOffset()
2136 int th = totalHeight();
2138 if ( testTableFlags(Tbl_scrollLastVCell) ) {
2140 maxOffs = th - ( cellH ? cellH : cellHeight( nRows - 1 ) );
2142 maxOffs = th - viewHeight();
2144 if ( testTableFlags(Tbl_snapToVGrid) ) {
2146 maxOffs = th - (viewHeight()/cellH)*cellH;
2148 int goal = th - viewHeight();
2150 int nextRow = nRows - 1;
2151 int nextCellHeight = cellHeight( nextRow );
2152 while ( nextRow > 0 && pos > goal + nextCellHeight ) {
2153 pos -= nextCellHeight;
2154 nextCellHeight = cellHeight( --nextRow );
2156 if ( goal + nextCellHeight == pos )
2158 else if ( goal < pos )
2164 maxOffs = th - viewHeight();
2167 return maxOffs > 0 ? maxOffs : 0;
2172 Returns the index of the last column, which may be at the left edge
2175 Depending on the \link setTableFlags() Tbl_scrollLastHCell\endlink flag,
2176 this may or may not be the last column.
2178 \sa maxXOffset(), maxRowOffset()
2181 int QtTableView::maxColOffset()
2183 int mx = maxXOffset();
2188 while ( col < nCols && mx > (xcd=cellWidth(col)) ) {
2198 Returns the index of the last row, which may be at the top edge of
2201 Depending on the \link setTableFlags() Tbl_scrollLastVCell\endlink flag,
2202 this may or may not be the last row.
2204 \sa maxYOffset(), maxColOffset()
2207 int QtTableView::maxRowOffset()
2209 int my = maxYOffset();
2214 while ( row < nRows && my > (ycd=cellHeight(row)) ) {
2223 void QtTableView::showOrHideScrollBars()
2225 if ( !autoUpdate() )
2228 if ( testTableFlags(Tbl_vScrollBar) ) {
2229 if ( !vScrollBar->isVisible() )
2230 sbDirty = sbDirty | verMask;
2232 if ( vScrollBar->isVisible() )
2237 if ( testTableFlags(Tbl_hScrollBar) ) {
2238 if ( !hScrollBar->isVisible() )
2239 sbDirty = sbDirty | horMask;
2241 if ( hScrollBar->isVisible() )
2245 if ( cornerSquare ) {
2246 if ( testTableFlags(Tbl_hScrollBar) &&
2247 testTableFlags(Tbl_vScrollBar) ) {
2248 if ( !cornerSquare->isVisible() )
2249 cornerSquare->show();
2251 if ( cornerSquare->isVisible() )
2252 cornerSquare->hide();
2259 Updates the scroll bars and internal state.
2261 Call this function when the table view's total size is changed;
2262 typically because the result of cellHeight() or cellWidth() have changed.
2264 This function does not repaint the widget.
2267 void QtTableView::updateTableSize()
2269 bool updateOn = autoUpdate();
2270 setAutoUpdate( FALSE );
2271 int xofs = xOffset();
2272 xOffs++; //so that setOffset will not return immediately
2273 setOffset(xofs,yOffset(),FALSE); //to calculate internal state correctly
2274 setAutoUpdate(updateOn);
2276 updateScrollBars( horSteps | horRange |
2277 verSteps | verRange );
2278 showOrHideScrollBars();