1 /**********************************************************************
2 ** $Id: qttableview.C,v 1.1 2001/12/01 02:24:27 levon 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() );
1310 if ( !colXPos( firstCol, &xStart ) || !rowYPos( firstRow, &yStart ) ) {
1311 paint.eraseRect( updateR ); // erase area outside cells but in view
1314 int maxX = updateR.right();
1315 int maxY = updateR.bottom();
1319 int xPos = maxX+1; // in case the while() is empty
1322 QRect winR = viewRect();
1325 #ifndef QT_NO_TRANSFORMATIONS
1329 while ( yPos <= maxY && row < nRows ) {
1330 nextY = yPos + (cellH ? cellH : cellHeight( row ));
1331 if ( testTableFlags( Tbl_cutCellsV ) && nextY > ( maxWY + 1 ) )
1335 while ( xPos <= maxX && col < nCols ) {
1336 nextX = xPos + (cellW ? cellW : cellWidth( col ));
1337 if ( testTableFlags( Tbl_cutCellsH ) && nextX > ( maxWX + 1 ) )
1340 cellR.setRect( xPos, yPos, cellW ? cellW : cellWidth(col),
1341 cellH ? cellH : cellHeight(row) );
1342 cellUR = cellR.intersect( updateR );
1343 if ( cellUR.isValid() ) {
1344 cellUpdateR = cellUR;
1345 cellUpdateR.moveBy( -xPos, -yPos ); // cell coordinates
1347 paint.eraseRect( cellUR );
1349 #ifndef QT_NO_TRANSFORMATIONS
1350 matrix.translate( xPos, yPos );
1351 paint.setWorldMatrix( matrix );
1352 if ( testTableFlags(Tbl_clipCellPainting) ||
1353 frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1354 paint.setClipRect( cellUR );
1355 paintCell( &paint, row, col );
1356 paint.setClipping( FALSE );
1358 paintCell( &paint, row, col );
1361 paint.setWorldMatrix( matrix );
1363 paint.translate( xPos, yPos );
1364 if ( testTableFlags(Tbl_clipCellPainting) ||
1365 frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1366 paint.setClipRect( cellUR );
1367 paintCell( &paint, row, col );
1368 paint.setClipping( FALSE );
1370 paintCell( &paint, row, col );
1372 paint.translate( -xPos, -yPos );
1382 // while painting we have to erase any areas in the view that
1383 // are not covered by cells but are covered by the paint event
1384 // rectangle these must be erased. We know that xPos is the last
1385 // x pixel updated + 1 and that yPos is the last y pixel updated + 1.
1387 // Note that this needs to be done regardless whether we do
1388 // eraseInPaint or not. Reason: a subclass may implement
1389 // flicker-freeness and encourage the use of repaint(FALSE).
1390 // The subclass, however, cannot draw all pixels, just those
1391 // inside the cells. So QtTableView is reponsible for all pixels
1392 // outside the cells.
1394 QRect viewR = viewRect();
1395 const QColorGroup g = colorGroup();
1397 if ( xPos <= maxX ) {
1400 r.setBottom( yPos<maxY?yPos:maxY );
1401 if ( inherits( "QMultiLineEdit" ) )
1402 paint.fillRect( r.intersect( updateR ), g.base() );
1404 paint.eraseRect( r.intersect( updateR ) );
1406 if ( yPos <= maxY ) {
1409 if ( inherits( "QMultiLineEdit" ) )
1410 paint.fillRect( r.intersect( updateR ), g.base() );
1412 paint.eraseRect( r.intersect( updateR ) );
1418 void QtTableView::resizeEvent( QResizeEvent * )
1420 updateScrollBars( horValue | verValue | horSteps | horGeometry | horRange |
1421 verSteps | verGeometry | verRange );
1422 showOrHideScrollBars();
1424 int maxX = QMIN( xOffs, maxXOffset() ); // ### can be slow
1425 int maxY = QMIN( yOffs, maxYOffset() );
1426 setOffset( maxX, maxY );
1431 Redraws all visible cells in the table view.
1434 void QtTableView::updateView()
1436 repaint( viewRect() );
1440 Returns a pointer to the vertical scroll bar mainly so you can
1441 connect() to its signals. Note that the scroll bar works in pixel
1442 values; use findRow() to translate to cell numbers.
1445 QScrollBar *QtTableView::verticalScrollBar() const
1447 QtTableView *that = (QtTableView*)this; // semantic const
1448 if ( !vScrollBar ) {
1449 QScrollBar *sb = new QScrollBar( QScrollBar::Vertical, that );
1450 #ifndef QT_NO_CURSOR
1451 sb->setCursor( arrowCursor );
1453 sb->resize( sb->sizeHint() ); // height is irrelevant
1455 sb->setTracking( FALSE );
1456 sb->setFocusPolicy( NoFocus );
1457 connect( sb, SIGNAL(valueChanged(int)),
1458 SLOT(verSbValue(int)));
1459 connect( sb, SIGNAL(sliderMoved(int)),
1460 SLOT(verSbSliding(int)));
1461 connect( sb, SIGNAL(sliderReleased()),
1462 SLOT(verSbSlidingDone()));
1464 that->vScrollBar = sb;
1471 Returns a pointer to the horizontal scroll bar mainly so you can
1472 connect() to its signals. Note that the scroll bar works in pixel
1473 values; use findCol() to translate to cell numbers.
1476 QScrollBar *QtTableView::horizontalScrollBar() const
1478 QtTableView *that = (QtTableView*)this; // semantic const
1479 if ( !hScrollBar ) {
1480 QScrollBar *sb = new QScrollBar( QScrollBar::Horizontal, that );
1481 #ifndef QT_NO_CURSOR
1482 sb->setCursor( arrowCursor );
1484 sb->resize( sb->sizeHint() ); // width is irrelevant
1485 sb->setFocusPolicy( NoFocus );
1487 sb->setTracking( FALSE );
1488 connect( sb, SIGNAL(valueChanged(int)),
1489 SLOT(horSbValue(int)));
1490 connect( sb, SIGNAL(sliderMoved(int)),
1491 SLOT(horSbSliding(int)));
1492 connect( sb, SIGNAL(sliderReleased()),
1493 SLOT(horSbSlidingDone()));
1495 that->hScrollBar = sb;
1502 Enables or disables the horizontal scroll bar, as required by
1503 setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1506 void QtTableView::setHorScrollBar( bool on, bool update )
1509 tFlags |= Tbl_hScrollBar;
1510 horizontalScrollBar(); // created
1512 updateScrollBars( horMask | verMask );
1514 sbDirty = sbDirty | (horMask | verMask);
1515 if ( testTableFlags( Tbl_vScrollBar ) )
1516 coverCornerSquare( TRUE );
1518 sbDirty = sbDirty | horMask;
1520 tFlags &= ~Tbl_hScrollBar;
1523 coverCornerSquare( FALSE );
1524 bool hideScrollBar = autoUpdate() && hScrollBar->isVisible();
1525 if ( hideScrollBar )
1528 updateScrollBars( verMask );
1530 sbDirty = sbDirty | verMask;
1531 if ( hideScrollBar && isVisible() )
1532 repaint( hScrollBar->x(), hScrollBar->y(),
1533 width() - hScrollBar->x(), hScrollBar->height() );
1541 Enables or disables the vertical scroll bar, as required by
1542 setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1545 void QtTableView::setVerScrollBar( bool on, bool update )
1548 tFlags |= Tbl_vScrollBar;
1549 verticalScrollBar(); // created
1551 updateScrollBars( verMask | horMask );
1553 sbDirty = sbDirty | (horMask | verMask);
1554 if ( testTableFlags( Tbl_hScrollBar ) )
1555 coverCornerSquare( TRUE );
1557 sbDirty = sbDirty | verMask;
1559 tFlags &= ~Tbl_vScrollBar;
1562 coverCornerSquare( FALSE );
1563 bool hideScrollBar = autoUpdate() && vScrollBar->isVisible();
1564 if ( hideScrollBar )
1567 updateScrollBars( horMask );
1569 sbDirty = sbDirty | horMask;
1570 if ( hideScrollBar && isVisible() )
1571 repaint( vScrollBar->x(), vScrollBar->y(),
1572 vScrollBar->width(), height() - vScrollBar->y() );
1581 int QtTableView::findRawRow( int yPos, int *cellMaxY, int *cellMinY,
1582 bool goOutsideView ) const
1587 if ( goOutsideView || yPos >= minViewY() && yPos <= maxViewY() ) {
1588 if ( yPos < minViewY() ) {
1589 #if defined(QT_CHECK_RANGE)
1590 qWarning( "QtTableView::findRawRow: (%s) internal error: "
1591 "yPos < minViewY() && goOutsideView "
1592 "not supported. (%d,%d)",
1593 name( "unnamed" ), yPos, yOffs );
1597 if ( cellH ) { // uniform cell height
1598 r = (yPos - minViewY() + yCellDelta)/cellH; // cell offs from top
1600 *cellMaxY = (r + 1)*cellH + minViewY() - yCellDelta - 1;
1602 *cellMinY = r*cellH + minViewY() - yCellDelta;
1603 r += yCellOffs; // absolute cell index
1604 } else { // variable cell height
1605 QtTableView *tw = (QtTableView *)this;
1607 int h = minViewY() - yCellDelta; //##arnt3
1609 Q_ASSERT( r < nRows );
1610 while ( r < nRows ) {
1612 h += tw->cellHeight( r ); // Start of next cell
1628 int QtTableView::findRawCol( int xPos, int *cellMaxX, int *cellMinX ,
1629 bool goOutsideView ) const
1634 if ( goOutsideView || xPos >= minViewX() && xPos <= maxViewX() ) {
1635 if ( xPos < minViewX() ) {
1636 #if defined(QT_CHECK_RANGE)
1637 qWarning( "QtTableView::findRawCol: (%s) internal error: "
1638 "xPos < minViewX() && goOutsideView "
1639 "not supported. (%d,%d)",
1640 name( "unnamed" ), xPos, xOffs );
1644 if ( cellW ) { // uniform cell width
1645 c = (xPos - minViewX() + xCellDelta)/cellW; //cell offs from left
1647 *cellMaxX = (c + 1)*cellW + minViewX() - xCellDelta - 1;
1649 *cellMinX = c*cellW + minViewX() - xCellDelta;
1650 c += xCellOffs; // absolute cell index
1651 } else { // variable cell width
1652 QtTableView *tw = (QtTableView *)this;
1654 int w = minViewX() - xCellDelta; //##arnt3
1656 Q_ASSERT( c < nCols );
1657 while ( c < nCols ) {
1659 w += tw->cellWidth( c ); // Start of next cell
1675 Returns the index of the row at position \a yPos, where \a yPos is in
1676 \e widget coordinates. Returns -1 if \a yPos is outside the valid
1679 \sa findCol(), rowYPos()
1682 int QtTableView::findRow( int yPos ) const
1685 int row = findRawRow( yPos, &cellMaxY );
1686 if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() )
1687 row = - 1; // cell cut by bottom margin
1695 Returns the index of the column at position \a xPos, where \a xPos is
1696 in \e widget coordinates. Returns -1 if \a xPos is outside the valid
1699 \sa findRow(), colXPos()
1702 int QtTableView::findCol( int xPos ) const
1705 int col = findRawCol( xPos, &cellMaxX );
1706 if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() )
1707 col = - 1; // cell cut by right margin
1715 Computes the position in the widget of row \a row.
1717 Returns TRUE and stores the result in \a *yPos (in \e widget
1718 coordinates) if the row is visible. Returns FALSE and does not modify
1719 \a *yPos if \a row is invisible or invalid.
1721 \sa colXPos(), findRow()
1724 bool QtTableView::rowYPos( int row, int *yPos ) const
1727 if ( row >= yCellOffs ) {
1729 int lastVisible = lastRowVisible();
1730 if ( row > lastVisible || lastVisible == -1 )
1732 y = (row - yCellOffs)*cellH + minViewY() - yCellDelta;
1735 y = minViewY() - yCellDelta; // y of leftmost cell in view
1737 QtTableView *tw = (QtTableView *)this;
1738 int maxY = maxViewY();
1739 while ( r < row && y <= maxY )
1740 y += tw->cellHeight( r++ );
1755 Computes the position in the widget of column \a col.
1757 Returns TRUE and stores the result in \a *xPos (in \e widget
1758 coordinates) if the column is visible. Returns FALSE and does not
1759 modify \a *xPos if \a col is invisible or invalid.
1761 \sa rowYPos(), findCol()
1764 bool QtTableView::colXPos( int col, int *xPos ) const
1767 if ( col >= xCellOffs ) {
1769 int lastVisible = lastColVisible();
1770 if ( col > lastVisible || lastVisible == -1 )
1772 x = (col - xCellOffs)*cellW + minViewX() - xCellDelta;
1775 x = minViewX() - xCellDelta; // x of uppermost cell in view
1777 QtTableView *tw = (QtTableView *)this;
1778 int maxX = maxViewX();
1779 while ( c < col && x <= maxX )
1780 x += tw->cellWidth( c++ );
1794 Moves the visible area of the table right by \a xPixels and
1795 down by \a yPixels pixels. Both may be negative.
1797 \warning You might find that QScrollView offers a higher-level of
1798 functionality than using QtTableView and this function.
1800 This function is \e not the same as QWidget::scroll(); in particular,
1801 the signs of \a xPixels and \a yPixels have the reverse semantics.
1803 \sa setXOffset(), setYOffset(), setOffset(), setTopCell(),
1807 void QtTableView::scroll( int xPixels, int yPixels )
1809 QWidget::scroll( -xPixels, -yPixels, contentsRect() );
1814 Returns the leftmost pixel of the table view in \e view
1815 coordinates. This excludes the frame and any header.
1817 \sa maxViewY(), viewWidth(), contentsRect()
1820 int QtTableView::minViewX() const
1822 return frameWidth();
1827 Returns the top pixel of the table view in \e view
1828 coordinates. This excludes the frame and any header.
1830 \sa maxViewX(), viewHeight(), contentsRect()
1833 int QtTableView::minViewY() const
1835 return frameWidth();
1840 Returns the rightmost pixel of the table view in \e view
1841 coordinates. This excludes the frame and any scroll bar, but
1842 includes blank pixels to the right of the visible table data.
1844 \sa maxViewY(), viewWidth(), contentsRect()
1847 int QtTableView::maxViewX() const
1849 return width() - 1 - frameWidth()
1850 - (tFlags & Tbl_vScrollBar ? VSBEXT
1856 Returns the bottom pixel of the table view in \e view
1857 coordinates. This excludes the frame and any scroll bar, but
1858 includes blank pixels below the visible table data.
1860 \sa maxViewX(), viewHeight(), contentsRect()
1863 int QtTableView::maxViewY() const
1865 return height() - 1 - frameWidth()
1866 - (tFlags & Tbl_hScrollBar ? HSBEXT
1872 Returns the width of the table view, as such, in \e view
1873 coordinates. This does not include any header, scroll bar or frame,
1874 but it does include background pixels to the right of the table data.
1876 \sa minViewX() maxViewX(), viewHeight(), contentsRect() viewRect()
1879 int QtTableView::viewWidth() const
1881 return maxViewX() - minViewX() + 1;
1886 Returns the height of the table view, as such, in \e view
1887 coordinates. This does not include any header, scroll bar or frame,
1888 but it does include background pixels below the table data.
1890 \sa minViewY() maxViewY() viewWidth() contentsRect() viewRect()
1893 int QtTableView::viewHeight() const
1895 return maxViewY() - minViewY() + 1;
1899 void QtTableView::doAutoScrollBars()
1901 int viewW = width() - frameWidth() - minViewX();
1902 int viewH = height() - frameWidth() - minViewY();
1903 bool vScrollOn = testTableFlags(Tbl_vScrollBar);
1904 bool hScrollOn = testTableFlags(Tbl_hScrollBar);
1909 if ( testTableFlags(Tbl_autoHScrollBar) ) {
1914 while ( i < nCols && w <= viewW )
1915 w += cellWidth( i++ );
1923 if ( testTableFlags(Tbl_autoVScrollBar) ) {
1928 while ( i < nRows && h <= viewH )
1929 h += cellHeight( i++ );
1938 if ( testTableFlags(Tbl_autoHScrollBar) && vScrollOn && !hScrollOn )
1939 if ( w > viewW - VSBEXT )
1942 if ( testTableFlags(Tbl_autoVScrollBar) && hScrollOn && !vScrollOn )
1943 if ( h > viewH - HSBEXT )
1946 setHorScrollBar( hScrollOn, FALSE );
1947 setVerScrollBar( vScrollOn, FALSE );
1953 \fn void QtTableView::updateScrollBars()
1955 Updates the scroll bars' contents and presence to match the table's
1956 state. Generally, you should not need to call this.
1962 Updates the scroll bars' contents and presence to match the table's
1968 void QtTableView::updateScrollBars( uint f )
1970 sbDirty = sbDirty | f;
1975 if ( testTableFlags(Tbl_autoHScrollBar) && (sbDirty & horRange) ||
1976 testTableFlags(Tbl_autoVScrollBar) && (sbDirty & verRange) )
1977 // if range change and auto
1978 doAutoScrollBars(); // turn scroll bars on/off if needed
1980 if ( !autoUpdate() ) {
1984 if ( yOffset() > 0 && testTableFlags( Tbl_autoVScrollBar ) &&
1985 !testTableFlags( Tbl_vScrollBar ) ) {
1988 if ( xOffset() > 0 && testTableFlags( Tbl_autoHScrollBar ) &&
1989 !testTableFlags( Tbl_hScrollBar ) ) {
1992 if ( !isVisible() ) {
1997 if ( testTableFlags(Tbl_hScrollBar) && (sbDirty & horMask) != 0 ) {
1998 if ( sbDirty & horGeometry )
1999 hScrollBar->setGeometry( 0,height() - HSBEXT,
2000 viewWidth() + frameWidth()*2,
2003 if ( sbDirty & horSteps ) {
2005 hScrollBar->setSteps( QMIN(cellW,viewWidth()/2), viewWidth() );
2007 hScrollBar->setSteps( 16, viewWidth() );
2010 if ( sbDirty & horRange )
2011 hScrollBar->setRange( 0, maxXOffset() );
2013 if ( sbDirty & horValue )
2014 hScrollBar->setValue( xOffs );
2016 // show scrollbar only when it has a sane geometry
2017 if ( !hScrollBar->isVisible() )
2021 if ( testTableFlags(Tbl_vScrollBar) && (sbDirty & verMask) != 0 ) {
2022 if ( sbDirty & verGeometry )
2023 vScrollBar->setGeometry( width() - VSBEXT, 0,
2025 viewHeight() + frameWidth()*2 );
2027 if ( sbDirty & verSteps ) {
2029 vScrollBar->setSteps( QMIN(cellH,viewHeight()/2), viewHeight() );
2031 vScrollBar->setSteps( 16, viewHeight() ); // fttb! ###
2034 if ( sbDirty & verRange )
2035 vScrollBar->setRange( 0, maxYOffset() );
2037 if ( sbDirty & verValue )
2038 vScrollBar->setValue( yOffs );
2040 // show scrollbar only when it has a sane geometry
2041 if ( !vScrollBar->isVisible() )
2044 if ( coveringCornerSquare &&
2045 ( (sbDirty & verGeometry ) || (sbDirty & horGeometry)) )
2046 cornerSquare->move( maxViewX() + frameWidth() + 1,
2047 maxViewY() + frameWidth() + 1 );
2054 void QtTableView::updateFrameSize()
2056 int rw = width() - ( testTableFlags(Tbl_vScrollBar) ?
2058 int rh = height() - ( testTableFlags(Tbl_hScrollBar) ?
2065 if ( autoUpdate() ) {
2066 int fh = frameRect().height();
2067 int fw = frameRect().width();
2068 setFrameRect( QRect(0,0,rw,rh) );
2071 update( QMIN(fw,rw) - frameWidth() - 2, 0, frameWidth()+4, rh );
2073 update( 0, QMIN(fh,rh) - frameWidth() - 2, rw, frameWidth()+4 );
2079 Returns the maximum horizontal offset within the table of the
2080 view's left edge in \e table coordinates.
2082 This is used mainly to set the horizontal scroll bar's range.
2084 \sa maxColOffset(), maxYOffset(), totalWidth()
2087 int QtTableView::maxXOffset()
2089 int tw = totalWidth();
2091 if ( testTableFlags(Tbl_scrollLastHCell) ) {
2093 maxOffs = tw - ( cellW ? cellW : cellWidth( nCols - 1 ) );
2095 maxOffs = tw - viewWidth();
2097 if ( testTableFlags(Tbl_snapToHGrid) ) {
2099 maxOffs = tw - (viewWidth()/cellW)*cellW;
2101 int goal = tw - viewWidth();
2103 int nextCol = nCols - 1;
2104 int nextCellWidth = cellWidth( nextCol );
2105 while( nextCol > 0 && pos > goal + nextCellWidth ) {
2106 pos -= nextCellWidth;
2107 nextCellWidth = cellWidth( --nextCol );
2109 if ( goal + nextCellWidth == pos )
2111 else if ( goal < pos )
2117 maxOffs = tw - viewWidth();
2120 return maxOffs > 0 ? maxOffs : 0;
2125 Returns the maximum vertical offset within the table of the
2126 view's top edge in \e table coordinates.
2128 This is used mainly to set the vertical scroll bar's range.
2130 \sa maxRowOffset(), maxXOffset(), totalHeight()
2133 int QtTableView::maxYOffset()
2135 int th = totalHeight();
2137 if ( testTableFlags(Tbl_scrollLastVCell) ) {
2139 maxOffs = th - ( cellH ? cellH : cellHeight( nRows - 1 ) );
2141 maxOffs = th - viewHeight();
2143 if ( testTableFlags(Tbl_snapToVGrid) ) {
2145 maxOffs = th - (viewHeight()/cellH)*cellH;
2147 int goal = th - viewHeight();
2149 int nextRow = nRows - 1;
2150 int nextCellHeight = cellHeight( nextRow );
2151 while( nextRow > 0 && pos > goal + nextCellHeight ) {
2152 pos -= nextCellHeight;
2153 nextCellHeight = cellHeight( --nextRow );
2155 if ( goal + nextCellHeight == pos )
2157 else if ( goal < pos )
2163 maxOffs = th - viewHeight();
2166 return maxOffs > 0 ? maxOffs : 0;
2171 Returns the index of the last column, which may be at the left edge
2174 Depending on the \link setTableFlags() Tbl_scrollLastHCell\endlink flag,
2175 this may or may not be the last column.
2177 \sa maxXOffset(), maxRowOffset()
2180 int QtTableView::maxColOffset()
2182 int mx = maxXOffset();
2187 while ( col < nCols && mx > (xcd=cellWidth(col)) ) {
2197 Returns the index of the last row, which may be at the top edge of
2200 Depending on the \link setTableFlags() Tbl_scrollLastVCell\endlink flag,
2201 this may or may not be the last row.
2203 \sa maxYOffset(), maxColOffset()
2206 int QtTableView::maxRowOffset()
2208 int my = maxYOffset();
2213 while ( row < nRows && my > (ycd=cellHeight(row)) ) {
2222 void QtTableView::showOrHideScrollBars()
2224 if ( !autoUpdate() )
2227 if ( testTableFlags(Tbl_vScrollBar) ) {
2228 if ( !vScrollBar->isVisible() )
2229 sbDirty = sbDirty | verMask;
2231 if ( vScrollBar->isVisible() )
2236 if ( testTableFlags(Tbl_hScrollBar) ) {
2237 if ( !hScrollBar->isVisible() )
2238 sbDirty = sbDirty | horMask;
2240 if ( hScrollBar->isVisible() )
2244 if ( cornerSquare ) {
2245 if ( testTableFlags(Tbl_hScrollBar) &&
2246 testTableFlags(Tbl_vScrollBar) ) {
2247 if ( !cornerSquare->isVisible() )
2248 cornerSquare->show();
2250 if ( cornerSquare->isVisible() )
2251 cornerSquare->hide();
2258 Updates the scroll bars and internal state.
2260 Call this function when the table view's total size is changed;
2261 typically because the result of cellHeight() or cellWidth() have changed.
2263 This function does not repaint the widget.
2266 void QtTableView::updateTableSize()
2268 bool updateOn = autoUpdate();
2269 setAutoUpdate( FALSE );
2270 int xofs = xOffset();
2271 xOffs++; //so that setOffset will not return immediately
2272 setOffset(xofs,yOffset(),FALSE); //to calculate internal state correctly
2273 setAutoUpdate(updateOn);
2275 updateScrollBars( horSteps | horRange |
2276 verSteps | verRange );
2277 showOrHideScrollBars();