NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / win / Qt / qttableview.cpp
blob55bac5c5f0773900e413661dd1a4869365397619
1 /**********************************************************************
2 ** $ANH-Branch$:$ANH-Revision$ $ANH-Date$
3 ** $Id: qttableview.cpp,v 1.2 2002/03/09 03:13:15 jwalz Exp $
4 **
5 ** Implementation of QtTableView class
6 **
7 ** Created : 941115
8 **
9 ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
11 ** This file contains a class moved out of the Qt GUI Toolkit API. It
12 ** may be used, distributed and modified without limitation.
14 **********************************************************************/
16 #include "qttableview.h"
17 #if QT_VERSION >= 300
18 #ifndef QT_NO_QTTABLEVIEW
19 #include <qscrollbar.h>
20 #include <qpainter.h>
21 #include <qdrawutil.h>
22 #include <limits.h>
24 enum ScrollBarDirtyFlags {
25 verGeometry = 0x01,
26 verSteps = 0x02,
27 verRange = 0x04,
28 verValue = 0x08,
29 horGeometry = 0x10,
30 horSteps = 0x20,
31 horRange = 0x40,
32 horValue = 0x80,
33 verMask = 0x0F,
34 horMask = 0xF0
38 #define HSBEXT horizontalScrollBar()->sizeHint().height()
39 #define VSBEXT verticalScrollBar()->sizeHint().width()
42 class QCornerSquare : public QWidget // internal class
44 public:
45 QCornerSquare( QWidget *, const char* = 0 );
46 void paintEvent( QPaintEvent * );
49 QCornerSquare::QCornerSquare( QWidget *parent, const char *name )
50 : QWidget( parent, name )
54 void QCornerSquare::paintEvent( QPaintEvent * )
59 // NOT REVISED
60 /*!
61 \class QtTableView qttableview.h
62 \brief The QtTableView class provides an abstract base for tables.
64 \obsolete
66 A table view consists of a number of abstract cells organized in rows
67 and columns, and a visible part called a view. The cells are identified
68 with a row index and a column index. The top-left cell is in row 0,
69 column 0.
71 The behavior of the widget can be finely tuned using
72 setTableFlags(); a typical subclass will consist of little more than a
73 call to setTableFlags(), some table content manipulation and an
74 implementation of paintCell(). Subclasses that need cells with
75 variable width or height must reimplement cellHeight() and/or
76 cellWidth(). Use updateTableSize() to tell QtTableView when the
77 width or height has changed.
79 When you read this documentation, it is important to understand the
80 distinctions among the four pixel coordinate systems involved.
82 \list 1
83 \i The \e cell coordinates. (0,0) is the top-left corner of a cell.
84 Cell coordinates are used by functions such as paintCell().
86 \i The \e table coordinates. (0,0) is the top-left corner of the cell at
87 row 0 and column 0. These coordinates are absolute; that is, they are
88 independent of what part of the table is visible at the moment. They are
89 used by functions such as setXOffset() or maxYOffset().
91 \i The \e widget coordinates. (0,0) is the top-left corner of the widget,
92 \e including the frame. They are used by functions such as repaint().
94 \i The \e view coordinates. (0,0) is the top-left corner of the view, \e
95 excluding the frame. This is the least-used coordinate system; it is used by
96 functions such as viewWidth(). \endlist
98 It is rather unfortunate that we have to use four different
99 coordinate systems, but there was no alternative to provide a flexible and
100 powerful base class.
102 Note: The row,column indices are always given in that order,
103 i.e., first the vertical (row), then the horizontal (column). This is
104 the opposite order of all pixel operations, which take first the
105 horizontal (x) and then the vertical (y).
107 <img src=qtablevw-m.png> <img src=qtablevw-w.png>
109 \warning the functions setNumRows(), setNumCols(), setCellHeight(),
110 setCellWidth(), setTableFlags() and clearTableFlags() may cause
111 virtual functions such as cellWidth() and cellHeight() to be called,
112 even if autoUpdate() is FALSE. This may cause errors if relevant
113 state variables are not initialized.
115 \warning Experience has shown that use of this widget tends to cause
116 more bugs than expected and our analysis indicates that the widget's
117 very flexibility is the problem. If QScrollView or QListBox can
118 easily be made to do the job you need, we recommend subclassing
119 those widgets rather than QtTableView. In addition, QScrollView makes
120 it easy to have child widgets inside tables, which QtTableView
121 doesn't support at all.
123 \sa QScrollView
124 \link guibooks.html#fowler GUI Design Handbook: Table\endlink
129 Constructs a table view. The \a parent, \a name and \f arguments
130 are passed to the QFrame constructor.
132 The \link setTableFlags() table flags\endlink are all cleared (set to 0).
133 Set \c Tbl_autoVScrollBar or \c Tbl_autoHScrollBar to get automatic scroll
134 bars and \c Tbl_clipCellPainting to get safe clipping.
136 The \link setCellHeight() cell height\endlink and \link setCellWidth()
137 cell width\endlink are set to 0.
139 Frame line shapes (QFrame::HLink and QFrame::VLine) are disallowed;
140 see QFrame::setFrameStyle().
142 Note that the \a f argument is \e not \link setTableFlags() table
143 flags \endlink but rather \link QWidget::QWidget() widget
144 flags. \endlink
148 QtTableView::QtTableView( QWidget *parent, const char *name, WFlags f )
149 : QFrame( parent, name, f )
151 nRows = nCols = 0; // zero rows/cols
152 xCellOffs = yCellOffs = 0; // zero offset
153 xCellDelta = yCellDelta = 0; // zero cell offset
154 xOffs = yOffs = 0; // zero total pixel offset
155 cellH = cellW = 0; // user defined cell size
156 tFlags = 0;
157 vScrollBar = hScrollBar = 0; // no scroll bars
158 cornerSquare = 0;
159 sbDirty = 0;
160 eraseInPaint = FALSE;
161 verSliding = FALSE;
162 verSnappingOff = FALSE;
163 horSliding = FALSE;
164 horSnappingOff = FALSE;
165 coveringCornerSquare = FALSE;
166 inSbUpdate = FALSE;
170 Destroys the table view.
173 QtTableView::~QtTableView()
175 delete vScrollBar;
176 delete hScrollBar;
177 delete cornerSquare;
182 \internal
183 Reimplements QWidget::setBackgroundColor() for binary compatibility.
184 \sa setPalette()
187 void QtTableView::setBackgroundColor( const QColor &c )
189 QWidget::setBackgroundColor( c );
192 /*!\reimp
195 void QtTableView::setPalette( const QPalette &p )
197 QWidget::setPalette( p );
200 /*!\reimp
203 void QtTableView::show()
205 showOrHideScrollBars();
206 QWidget::show();
211 \overload void QtTableView::repaint( bool erase )
212 Repaints the entire view.
216 Repaints the table view directly by calling paintEvent() directly
217 unless updates are disabled.
219 Erases the view area \a (x,y,w,h) if \a erase is TRUE. Parameters \a
220 (x,y) are in \e widget coordinates.
222 If \a w is negative, it is replaced with <code>width() - x</code>.
223 If \a h is negative, it is replaced with <code>height() - y</code>.
225 Doing a repaint() usually is faster than doing an update(), but
226 calling update() many times in a row will generate a single paint
227 event.
229 At present, QtTableView is the only widget that reimplements \link
230 QWidget::repaint() repaint()\endlink. It does this because by
231 clearing and then repainting one cell at at time, it can make the
232 screen flicker less than it would otherwise. */
234 void QtTableView::repaint( int x, int y, int w, int h, bool erase )
236 if ( !isVisible() || testWState(WState_BlockUpdates) )
237 return;
238 if ( w < 0 )
239 w = width() - x;
240 if ( h < 0 )
241 h = height() - y;
242 QRect r( x, y, w, h );
243 if ( r.isEmpty() )
244 return; // nothing to do
245 QPaintEvent e( r );
246 if ( erase && backgroundMode() != NoBackground )
247 eraseInPaint = TRUE; // erase when painting
248 paintEvent( &e );
249 eraseInPaint = FALSE;
253 \overload void QtTableView::repaint( const QRect &r, bool erase )
254 Replaints rectangle \a r. If \a erase is TRUE draws the background
255 using the palette's background.
260 \fn int QtTableView::numRows() const
261 Returns the number of rows in the table.
262 \sa numCols(), setNumRows()
266 Sets the number of rows of the table to \a rows (must be non-negative).
267 Does not change topCell().
269 The table repaints itself automatically if autoUpdate() is set.
271 \sa numCols(), setNumCols(), numRows()
274 void QtTableView::setNumRows( int rows )
276 if ( rows < 0 ) {
277 #if defined(QT_CHECK_RANGE)
278 qWarning( "QtTableView::setNumRows: (%s) Negative argument %d.",
279 name( "unnamed" ), rows );
280 #endif
281 return;
283 if ( nRows == rows )
284 return;
286 if ( autoUpdate() && isVisible() ) {
287 int oldLastVisible = lastRowVisible();
288 int oldTopCell = topCell();
289 nRows = rows;
290 if ( autoUpdate() && isVisible() &&
291 ( oldLastVisible != lastRowVisible() || oldTopCell != topCell() ) )
292 repaint( oldTopCell != topCell() );
293 } else {
294 // Be more careful - if destructing, bad things might happen.
295 nRows = rows;
297 updateScrollBars( verRange );
298 updateFrameSize();
302 \fn int QtTableView::numCols() const
303 Returns the number of columns in the table.
304 \sa numRows(), setNumCols()
308 Sets the number of columns of the table to \a cols (must be non-negative).
309 Does not change leftCell().
311 The table repaints itself automatically if autoUpdate() is set.
313 \sa numCols(), numRows(), setNumRows()
316 void QtTableView::setNumCols( int cols )
318 if ( cols < 0 ) {
319 #if defined(QT_CHECK_RANGE)
320 qWarning( "QtTableView::setNumCols: (%s) Negative argument %d.",
321 name( "unnamed" ), cols );
322 #endif
323 return;
325 if ( nCols == cols )
326 return;
327 int oldCols = nCols;
328 nCols = cols;
329 if ( autoUpdate() && isVisible() ) {
330 int maxCol = lastColVisible();
331 if ( maxCol >= oldCols || maxCol >= nCols )
332 repaint();
334 updateScrollBars( horRange );
335 updateFrameSize();
340 \fn int QtTableView::topCell() const
341 Returns the index of the first row in the table that is visible in
342 the view. The index of the first row is 0.
343 \sa leftCell(), setTopCell()
347 Scrolls the table so that \a row becomes the top row.
348 The index of the very first row is 0.
349 \sa setYOffset(), setTopLeftCell(), setLeftCell()
352 void QtTableView::setTopCell( int row )
354 setTopLeftCell( row, -1 );
355 return;
359 \fn int QtTableView::leftCell() const
360 Returns the index of the first column in the table that is visible in
361 the view. The index of the very leftmost column is 0.
362 \sa topCell(), setLeftCell()
366 Scrolls the table so that \a col becomes the leftmost
367 column. The index of the leftmost column is 0.
368 \sa setXOffset(), setTopLeftCell(), setTopCell()
371 void QtTableView::setLeftCell( int col )
373 setTopLeftCell( -1, col );
374 return;
378 Scrolls the table so that the cell at row \a row and colum \a
379 col becomes the top-left cell in the view. The cell at the extreme
380 top left of the table is at position (0,0).
381 \sa setLeftCell(), setTopCell(), setOffset()
384 void QtTableView::setTopLeftCell( int row, int col )
386 int newX = xOffs;
387 int newY = yOffs;
389 if ( col >= 0 ) {
390 if ( cellW ) {
391 newX = col*cellW;
392 if ( newX > maxXOffset() )
393 newX = maxXOffset();
394 } else {
395 newX = 0;
396 while ( col )
397 newX += cellWidth( --col ); // optimize using current! ###
400 if ( row >= 0 ) {
401 if ( cellH ) {
402 newY = row*cellH;
403 if ( newY > maxYOffset() )
404 newY = maxYOffset();
405 } else {
406 newY = 0;
407 while ( row )
408 newY += cellHeight( --row ); // optimize using current! ###
411 setOffset( newX, newY );
416 \fn int QtTableView::xOffset() const
418 Returns the x coordinate in \e table coordinates of the pixel that is
419 currently on the left edge of the view.
421 \sa setXOffset(), yOffset(), leftCell() */
424 Scrolls the table so that \a x becomes the leftmost pixel in the view.
425 The \a x parameter is in \e table coordinates.
427 The interaction with \link setTableFlags() Tbl_snapToHGrid
428 \endlink is tricky.
430 \sa xOffset(), setYOffset(), setOffset(), setLeftCell()
433 void QtTableView::setXOffset( int x )
435 setOffset( x, yOffset() );
439 \fn int QtTableView::yOffset() const
441 Returns the y coordinate in \e table coordinates of the pixel that is
442 currently on the top edge of the view.
444 \sa setYOffset(), xOffset(), topCell()
449 Scrolls the table so that \a y becomes the top pixel in the view.
450 The \a y parameter is in \e table coordinates.
452 The interaction with \link setTableFlags() Tbl_snapToVGrid
453 \endlink is tricky.
455 \sa yOffset(), setXOffset(), setOffset(), setTopCell()
458 void QtTableView::setYOffset( int y )
460 setOffset( xOffset(), y );
464 Scrolls the table so that \a (x,y) becomes the top-left pixel
465 in the view. Parameters \a (x,y) are in \e table coordinates.
467 The interaction with \link setTableFlags() Tbl_snapTo*Grid \endlink
468 is tricky. If \a updateScrBars is TRUE, the scroll bars are
469 updated.
471 \sa xOffset(), yOffset(), setXOffset(), setYOffset(), setTopLeftCell()
474 void QtTableView::setOffset( int x, int y, bool updateScrBars )
476 if ( (!testTableFlags(Tbl_snapToHGrid) || xCellDelta == 0) &&
477 (!testTableFlags(Tbl_snapToVGrid) || yCellDelta == 0) &&
478 (x == xOffs && y == yOffs) )
479 return;
481 if ( x < 0 )
482 x = 0;
483 if ( y < 0 )
484 y = 0;
486 if ( cellW ) {
487 if ( x > maxXOffset() )
488 x = maxXOffset();
489 xCellOffs = x / cellW;
490 if ( !testTableFlags(Tbl_snapToHGrid) ) {
491 xCellDelta = (short)(x % cellW);
492 } else {
493 x = xCellOffs*cellW;
494 xCellDelta = 0;
496 } else {
497 int xn=0, xcd=0, col = 0;
498 while ( col < nCols-1 && x >= xn+(xcd=cellWidth(col)) ) {
499 xn += xcd;
500 col++;
502 xCellOffs = col;
503 if ( testTableFlags(Tbl_snapToHGrid) ) {
504 xCellDelta = 0;
505 x = xn;
506 } else {
507 xCellDelta = (short)(x-xn);
510 if ( cellH ) {
511 if ( y > maxYOffset() )
512 y = maxYOffset();
513 yCellOffs = y / cellH;
514 if ( !testTableFlags(Tbl_snapToVGrid) ) {
515 yCellDelta = (short)(y % cellH);
516 } else {
517 y = yCellOffs*cellH;
518 yCellDelta = 0;
520 } else {
521 int yn=0, yrd=0, row=0;
522 while ( row < nRows-1 && y >= yn+(yrd=cellHeight(row)) ) {
523 yn += yrd;
524 row++;
526 yCellOffs = row;
527 if ( testTableFlags(Tbl_snapToVGrid) ) {
528 yCellDelta = 0;
529 y = yn;
530 } else {
531 yCellDelta = (short)(y-yn);
534 int dx = (x - xOffs);
535 int dy = (y - yOffs);
536 xOffs = x;
537 yOffs = y;
538 if ( autoUpdate() && isVisible() )
539 scroll( dx, dy );
540 if ( updateScrBars )
541 updateScrollBars( verValue | horValue );
546 \overload int QtTableView::cellWidth() const
548 Returns the column width in pixels. Returns 0 if the columns have
549 variable widths.
551 \sa setCellWidth(), cellHeight()
555 Returns the width of column \a col in pixels.
557 This function is virtual and must be reimplemented by subclasses that
558 have variable cell widths. Note that if the total table width
559 changes, updateTableSize() must be called.
561 \sa setCellWidth(), cellHeight(), totalWidth(), updateTableSize()
564 int QtTableView::cellWidth( int )
566 return cellW;
571 Sets the width in pixels of the table cells to \a cellWidth.
573 Setting it to 0 means that the column width is variable. When
574 set to 0 (this is the default) QtTableView calls the virtual function
575 cellWidth() to get the width.
577 \sa cellWidth(), setCellHeight(), totalWidth(), numCols()
580 void QtTableView::setCellWidth( int cellWidth )
582 if ( cellW == cellWidth )
583 return;
584 #if defined(QT_CHECK_RANGE)
585 if ( cellWidth < 0 || cellWidth > SHRT_MAX ) {
586 qWarning( "QtTableView::setCellWidth: (%s) Argument out of range (%d)",
587 name( "unnamed" ), cellWidth );
588 return;
590 #endif
591 cellW = (short)cellWidth;
593 updateScrollBars( horSteps | horRange );
594 if ( autoUpdate() && isVisible() )
595 repaint();
600 \overload int QtTableView::cellHeight() const
602 Returns the row height, in pixels. Returns 0 if the rows have
603 variable heights.
605 \sa setCellHeight(), cellWidth()
610 Returns the height of row \a row in pixels.
612 This function is virtual and must be reimplemented by subclasses that
613 have variable cell heights. Note that if the total table height
614 changes, updateTableSize() must be called.
616 \sa setCellHeight(), cellWidth(), totalHeight()
619 int QtTableView::cellHeight( int )
621 return cellH;
625 Sets the height in pixels of the table cells to \a cellHeight.
627 Setting it to 0 means that the row height is variable. When set
628 to 0 (this is the default), QtTableView calls the virtual function
629 cellHeight() to get the height.
631 \sa cellHeight(), setCellWidth(), totalHeight(), numRows()
634 void QtTableView::setCellHeight( int cellHeight )
636 if ( cellH == cellHeight )
637 return;
638 #if defined(QT_CHECK_RANGE)
639 if ( cellHeight < 0 || cellHeight > SHRT_MAX ) {
640 qWarning( "QtTableView::setCellHeight: (%s) Argument out of range (%d)",
641 name( "unnamed" ), cellHeight );
642 return;
644 #endif
645 cellH = (short)cellHeight;
646 if ( autoUpdate() && isVisible() )
647 repaint();
648 updateScrollBars( verSteps | verRange );
653 Returns the total width of the table in pixels.
655 This function is virtual and should be reimplemented by subclasses that
656 have variable cell widths and a non-trivial cellWidth() function, or a
657 large number of columns in the table.
659 The default implementation may be slow for very wide tables.
661 \sa cellWidth(), totalHeight() */
663 int QtTableView::totalWidth()
665 if ( cellW ) {
666 return cellW*nCols;
667 } else {
668 int tw = 0;
669 for( int i = 0 ; i < nCols ; i++ )
670 tw += cellWidth( i );
671 return tw;
676 Returns the total height of the table in pixels.
678 This function is virtual and should be reimplemented by subclasses that
679 have variable cell heights and a non-trivial cellHeight() function, or a
680 large number of rows in the table.
682 The default implementation may be slow for very tall tables.
684 \sa cellHeight(), totalWidth()
687 int QtTableView::totalHeight()
689 if ( cellH ) {
690 return cellH*nRows;
691 } else {
692 int th = 0;
693 for( int i = 0 ; i < nRows ; i++ )
694 th += cellHeight( i );
695 return th;
701 \fn uint QtTableView::tableFlags() const
703 Returns the union of the table flags that are currently set.
705 \sa setTableFlags(), clearTableFlags(), testTableFlags()
709 \fn bool QtTableView::testTableFlags( uint f ) const
711 Returns TRUE if any of the table flags in \a f are currently set,
712 otherwise FALSE.
714 \sa setTableFlags(), clearTableFlags(), tableFlags()
718 Sets the table flags to \a f.
720 If a flag setting changes the appearance of the table, the table is
721 repainted if - and only if - autoUpdate() is TRUE.
723 The table flags are mostly single bits, though there are some multibit
724 flags for convenience. Here is a complete list:
726 <dl compact>
727 <dt> Tbl_vScrollBar <dd> - The table has a vertical scroll bar.
728 <dt> Tbl_hScrollBar <dd> - The table has a horizontal scroll bar.
729 <dt> Tbl_autoVScrollBar <dd> - The table has a vertical scroll bar if
730 - and only if - the table is taller than the view.
731 <dt> Tbl_autoHScrollBar <dd> The table has a horizontal scroll bar if
732 - and only if - the table is wider than the view.
733 <dt> Tbl_autoScrollBars <dd> - The union of the previous two flags.
734 <dt> Tbl_clipCellPainting <dd> - The table uses QPainter::setClipRect() to
735 make sure that paintCell() will not draw outside the cell
736 boundaries.
737 <dt> Tbl_cutCellsV <dd> - The table will never show part of a
738 cell at the bottom of the table; if there is not space for all of
739 a cell, the space is left blank.
740 <dt> Tbl_cutCellsH <dd> - The table will never show part of a
741 cell at the right side of the table; if there is not space for all of
742 a cell, the space is left blank.
743 <dt> Tbl_cutCells <dd> - The union of the previous two flags.
744 <dt> Tbl_scrollLastHCell <dd> - When the user scrolls horizontally,
745 let him/her scroll the last cell left until it is at the left
746 edge of the view. If this flag is not set, the user can only scroll
747 to the point where the last cell is completely visible.
748 <dt> Tbl_scrollLastVCell <dd> - When the user scrolls vertically, let
749 him/her scroll the last cell up until it is at the top edge of
750 the view. If this flag is not set, the user can only scroll to the
751 point where the last cell is completely visible.
752 <dt> Tbl_scrollLastCell <dd> - The union of the previous two flags.
753 <dt> Tbl_smoothHScrolling <dd> - The table scrolls as smoothly as
754 possible when the user scrolls horizontally. When this flag is not
755 set, scrolling is done one cell at a time.
756 <dt> Tbl_smoothVScrolling <dd> - The table scrolls as smoothly as
757 possible when scrolling vertically. When this flag is not set,
758 scrolling is done one cell at a time.
759 <dt> Tbl_smoothScrolling <dd> - The union of the previous two flags.
760 <dt> Tbl_snapToHGrid <dd> - Except when the user is actually scrolling,
761 the leftmost column shown snaps to the leftmost edge of the view.
762 <dt> Tbl_snapToVGrid <dd> - Except when the user is actually
763 scrolling, the top row snaps to the top edge of the view.
764 <dt> Tbl_snapToGrid <dd> - The union of the previous two flags.
765 </dl>
767 You can specify more than one flag at a time using bitwise OR.
769 Example:
770 \code
771 setTableFlags( Tbl_smoothScrolling | Tbl_autoScrollBars );
772 \endcode
774 \warning The cutCells options (\c Tbl_cutCells, \c Tbl_cutCellsH and
775 Tbl_cutCellsV) may cause painting problems when scrollbars are
776 enabled. Do not combine cutCells and scrollbars.
779 \sa clearTableFlags(), testTableFlags(), tableFlags()
782 void QtTableView::setTableFlags( uint f )
784 f = (f ^ tFlags) & f; // clear flags already set
785 tFlags |= f;
787 bool updateOn = autoUpdate();
788 setAutoUpdate( FALSE );
790 uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
792 if ( f & Tbl_vScrollBar ) {
793 setVerScrollBar( TRUE );
795 if ( f & Tbl_hScrollBar ) {
796 setHorScrollBar( TRUE );
798 if ( f & Tbl_autoVScrollBar ) {
799 updateScrollBars( verRange );
801 if ( f & Tbl_autoHScrollBar ) {
802 updateScrollBars( horRange );
804 if ( f & Tbl_scrollLastHCell ) {
805 updateScrollBars( horRange );
807 if ( f & Tbl_scrollLastVCell ) {
808 updateScrollBars( verRange );
810 if ( f & Tbl_snapToHGrid ) {
811 updateScrollBars( horRange );
813 if ( f & Tbl_snapToVGrid ) {
814 updateScrollBars( verRange );
816 if ( f & Tbl_snapToGrid ) { // Note: checks for 2 flags
817 if ( (f & Tbl_snapToHGrid) != 0 && xCellDelta != 0 || //have to scroll?
818 (f & Tbl_snapToVGrid) != 0 && yCellDelta != 0 ) {
819 snapToGrid( (f & Tbl_snapToHGrid) != 0, // do snapping
820 (f & Tbl_snapToVGrid) != 0 );
821 repaintMask |= Tbl_snapToGrid; // repaint table
825 if ( updateOn ) {
826 setAutoUpdate( TRUE );
827 updateScrollBars();
828 if ( isVisible() && (f & repaintMask) )
829 repaint();
835 Clears the \link setTableFlags() table flags\endlink that are set
836 in \a f.
838 Example (clears a single flag):
839 \code
840 clearTableFlags( Tbl_snapToGrid );
841 \endcode
843 The default argument clears all flags.
845 \sa setTableFlags(), testTableFlags(), tableFlags()
848 void QtTableView::clearTableFlags( uint f )
850 f = (f ^ ~tFlags) & f; // clear flags that are already 0
851 tFlags &= ~f;
853 bool updateOn = autoUpdate();
854 setAutoUpdate( FALSE );
856 uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
858 if ( f & Tbl_vScrollBar ) {
859 setVerScrollBar( FALSE );
861 if ( f & Tbl_hScrollBar ) {
862 setHorScrollBar( FALSE );
864 if ( f & Tbl_scrollLastHCell ) {
865 int maxX = maxXOffset();
866 if ( xOffs > maxX ) {
867 setOffset( maxX, yOffs );
868 repaintMask |= Tbl_scrollLastHCell;
870 updateScrollBars( horRange );
872 if ( f & Tbl_scrollLastVCell ) {
873 int maxY = maxYOffset();
874 if ( yOffs > maxY ) {
875 setOffset( xOffs, maxY );
876 repaintMask |= Tbl_scrollLastVCell;
878 updateScrollBars( verRange );
880 if ( f & Tbl_smoothScrolling ) { // Note: checks for 2 flags
881 if ((f & Tbl_smoothHScrolling) != 0 && xCellDelta != 0 ||//must scroll?
882 (f & Tbl_smoothVScrolling) != 0 && yCellDelta != 0 ) {
883 snapToGrid( (f & Tbl_smoothHScrolling) != 0, // do snapping
884 (f & Tbl_smoothVScrolling) != 0 );
885 repaintMask |= Tbl_smoothScrolling; // repaint table
888 if ( f & Tbl_snapToHGrid ) {
889 updateScrollBars( horRange );
891 if ( f & Tbl_snapToVGrid ) {
892 updateScrollBars( verRange );
894 if ( updateOn ) {
895 setAutoUpdate( TRUE );
896 updateScrollBars(); // returns immediately if nothing to do
897 if ( isVisible() && (f & repaintMask) )
898 repaint();
905 \fn bool QtTableView::autoUpdate() const
907 Returns TRUE if the view updates itself automatically whenever it
908 is changed in some way.
910 \sa setAutoUpdate()
914 Sets the auto-update option of the table view to \a enable.
916 If \a enable is TRUE (this is the default), the view updates itself
917 automatically whenever it has changed in some way (for example, when a
918 \link setTableFlags() flag\endlink is changed).
920 If \a enable is FALSE, the view does NOT repaint itself or update
921 its internal state variables when it is changed. This can be
922 useful to avoid flicker during large changes and is singularly
923 useless otherwise. Disable auto-update, do the changes, re-enable
924 auto-update and call repaint().
926 \warning Do not leave the view in this state for a long time
927 (i.e., between events). If, for example, the user interacts with the
928 view when auto-update is off, strange things can happen.
930 Setting auto-update to TRUE does not repaint the view; you must call
931 repaint() to do this.
933 \sa autoUpdate(), repaint()
936 void QtTableView::setAutoUpdate( bool enable )
938 if ( isUpdatesEnabled() == enable )
939 return;
940 setUpdatesEnabled( enable );
941 if ( enable ) {
942 showOrHideScrollBars();
943 updateScrollBars();
949 Repaints the cell at row \a row, column \a col if it is inside the view.
951 If \a erase is TRUE, the relevant part of the view is cleared to the
952 background color/pixmap before the contents are repainted.
954 \sa isVisible()
957 void QtTableView::updateCell( int row, int col, bool erase )
959 int xPos, yPos;
960 if ( !colXPos( col, &xPos ) )
961 return;
962 if ( !rowYPos( row, &yPos ) )
963 return;
964 QRect uR = QRect( xPos, yPos,
965 cellW ? cellW : cellWidth(col),
966 cellH ? cellH : cellHeight(row) );
967 repaint( uR.intersect(viewRect()), erase );
972 \fn QRect QtTableView::cellUpdateRect() const
974 This function should be called only from the paintCell() function in
975 subclasses. It returns the portion of a cell that actually needs to be
976 updated in \e cell coordinates. This is useful only for non-trivial
977 paintCell().
982 Returns the rectangle that is the actual table, excluding any
983 frame, in \e widget coordinates.
986 QRect QtTableView::viewRect() const
988 return QRect( frameWidth(), frameWidth(), viewWidth(), viewHeight() );
993 Returns the index of the last (bottom) row in the view.
994 The index of the first row is 0.
996 If no rows are visible it returns -1. This can happen if the
997 view is too small for the first row and Tbl_cutCellsV is set.
999 \sa lastColVisible()
1002 int QtTableView::lastRowVisible() const
1004 int cellMaxY;
1005 int row = findRawRow( maxViewY(), &cellMaxY );
1006 if ( row == -1 || row >= nRows ) { // maxViewY() past end?
1007 row = nRows - 1; // yes: return last row
1008 } else {
1009 if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() ) {
1010 if ( row == yCellOffs ) // cut by right margin?
1011 return -1; // yes, nothing in the view
1012 else
1013 row = row - 1; // cut by margin, one back
1016 return row;
1020 Returns the index of the last (right) column in the view.
1021 The index of the first column is 0.
1023 If no columns are visible it returns -1. This can happen if the
1024 view is too narrow for the first column and Tbl_cutCellsH is set.
1026 \sa lastRowVisible()
1029 int QtTableView::lastColVisible() const
1031 int cellMaxX;
1032 int col = findRawCol( maxViewX(), &cellMaxX );
1033 if ( col == -1 || col >= nCols ) { // maxViewX() past end?
1034 col = nCols - 1; // yes: return last col
1035 } else {
1036 if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() ) {
1037 if ( col == xCellOffs ) // cut by bottom margin?
1038 return -1; // yes, nothing in the view
1039 else
1040 col = col - 1; // cell by margin, one back
1043 return col;
1047 Returns TRUE if \a row is at least partially visible.
1048 \sa colIsVisible()
1051 bool QtTableView::rowIsVisible( int row ) const
1053 return rowYPos( row, 0 );
1057 Returns TRUE if \a col is at least partially visible.
1058 \sa rowIsVisible()
1061 bool QtTableView::colIsVisible( int col ) const
1063 return colXPos( col, 0 );
1068 \internal
1069 Called when both scroll bars are active at the same time. Covers the
1070 bottom left corner between the two scroll bars with an empty widget.
1073 void QtTableView::coverCornerSquare( bool enable )
1075 coveringCornerSquare = enable;
1076 if ( !cornerSquare && enable ) {
1077 cornerSquare = new QCornerSquare( this );
1078 Q_CHECK_PTR( cornerSquare );
1079 cornerSquare->setGeometry( maxViewX() + frameWidth() + 1,
1080 maxViewY() + frameWidth() + 1,
1081 VSBEXT,
1082 HSBEXT);
1084 if ( autoUpdate() && cornerSquare ) {
1085 if ( enable )
1086 cornerSquare->show();
1087 else
1088 cornerSquare->hide();
1094 \internal
1095 Scroll the view to a position such that:
1097 If \a horizontal is TRUE, the leftmost column shown fits snugly
1098 with the left edge of the view.
1100 If \a vertical is TRUE, the top row shown fits snugly with the top
1101 of the view.
1103 You can achieve the same effect automatically by setting any of the
1104 \link setTableFlags() Tbl_snapTo*Grid \endlink table flags.
1107 void QtTableView::snapToGrid( bool horizontal, bool vertical )
1109 int newXCell = -1;
1110 int newYCell = -1;
1111 if ( horizontal && xCellDelta != 0 ) {
1112 int w = cellW ? cellW : cellWidth( xCellOffs );
1113 if ( xCellDelta >= w/2 )
1114 newXCell = xCellOffs + 1;
1115 else
1116 newXCell = xCellOffs;
1118 if ( vertical && yCellDelta != 0 ) {
1119 int h = cellH ? cellH : cellHeight( yCellOffs );
1120 if ( yCellDelta >= h/2 )
1121 newYCell = yCellOffs + 1;
1122 else
1123 newYCell = yCellOffs;
1125 setTopLeftCell( newYCell, newXCell ); //row,column
1129 \internal
1130 This internal slot is connected to the horizontal scroll bar's
1131 QScrollBar::valueChanged() signal.
1133 Moves the table horizontally to offset \a val without updating the
1134 scroll bar.
1137 void QtTableView::horSbValue( int val )
1139 if ( horSliding ) {
1140 horSliding = FALSE;
1141 if ( horSnappingOff ) {
1142 horSnappingOff = FALSE;
1143 tFlags |= Tbl_snapToHGrid;
1146 setOffset( val, yOffs, FALSE );
1150 \internal
1151 This internal slot is connected to the horizontal scroll bar's
1152 QScrollBar::sliderMoved() signal.
1154 Scrolls the table smoothly horizontally even if \c Tbl_snapToHGrid is set.
1157 void QtTableView::horSbSliding( int val )
1159 if ( testTableFlags(Tbl_snapToHGrid) &&
1160 testTableFlags(Tbl_smoothHScrolling) ) {
1161 tFlags &= ~Tbl_snapToHGrid; // turn off snapping while sliding
1162 setOffset( val, yOffs, FALSE );
1163 tFlags |= Tbl_snapToHGrid; // turn on snapping again
1164 } else {
1165 setOffset( val, yOffs, FALSE );
1170 \internal
1171 This internal slot is connected to the horizontal scroll bar's
1172 QScrollBar::sliderReleased() signal.
1175 void QtTableView::horSbSlidingDone( )
1177 if ( testTableFlags(Tbl_snapToHGrid) &&
1178 testTableFlags(Tbl_smoothHScrolling) )
1179 snapToGrid( TRUE, FALSE );
1183 \internal
1184 This internal slot is connected to the vertical scroll bar's
1185 QScrollBar::valueChanged() signal.
1187 Moves the table vertically to offset \a val without updating the
1188 scroll bar.
1191 void QtTableView::verSbValue( int val )
1193 if ( verSliding ) {
1194 verSliding = FALSE;
1195 if ( verSnappingOff ) {
1196 verSnappingOff = FALSE;
1197 tFlags |= Tbl_snapToVGrid;
1200 setOffset( xOffs, val, FALSE );
1204 \internal
1205 This internal slot is connected to the vertical scroll bar's
1206 QScrollBar::sliderMoved() signal.
1208 Scrolls the table smoothly vertically even if \c Tbl_snapToVGrid is set.
1211 void QtTableView::verSbSliding( int val )
1213 if ( testTableFlags(Tbl_snapToVGrid) &&
1214 testTableFlags(Tbl_smoothVScrolling) ) {
1215 tFlags &= ~Tbl_snapToVGrid; // turn off snapping while sliding
1216 setOffset( xOffs, val, FALSE );
1217 tFlags |= Tbl_snapToVGrid; // turn on snapping again
1218 } else {
1219 setOffset( xOffs, val, FALSE );
1224 \internal
1225 This internal slot is connected to the vertical scroll bar's
1226 QScrollBar::sliderReleased() signal.
1229 void QtTableView::verSbSlidingDone( )
1231 if ( testTableFlags(Tbl_snapToVGrid) &&
1232 testTableFlags(Tbl_smoothVScrolling) )
1233 snapToGrid( FALSE, TRUE );
1238 This virtual function is called before painting of table cells
1239 is started. It can be reimplemented by subclasses that want to
1240 to set up the painter in a special way and that do not want to
1241 do so for each cell.
1244 void QtTableView::setupPainter( QPainter * )
1249 \fn void QtTableView::paintCell( QPainter *p, int row, int col )
1251 This pure virtual function is called to paint the single cell at \a
1252 (row,col) using \a p, which is open when paintCell() is called and
1253 must remain open.
1255 The coordinate system is \link QPainter::translate() translated \endlink
1256 so that the origin is at the top-left corner of the cell to be
1257 painted, i.e. \e cell coordinates. Do not scale or shear the coordinate
1258 system (or if you do, restore the transformation matrix before you
1259 return).
1261 The painter is not clipped by default and for maximum efficiency. For safety,
1262 call setTableFlags(Tbl_clipCellPainting) to enable clipping.
1264 \sa paintEvent(), setTableFlags() */
1268 Handles paint events, \a e, for the table view.
1270 Calls paintCell() for the cells that needs to be repainted.
1273 void QtTableView::paintEvent( QPaintEvent *e )
1275 QRect updateR = e->rect(); // update rectangle
1276 if ( sbDirty ) {
1277 bool e = eraseInPaint;
1278 updateScrollBars();
1279 eraseInPaint = e;
1282 QPainter paint( this );
1284 if ( !contentsRect().contains( updateR, TRUE ) ) {// update frame ?
1285 drawFrame( &paint );
1286 if ( updateR.left() < frameWidth() ) //###
1287 updateR.setLeft( frameWidth() );
1288 if ( updateR.top() < frameWidth() )
1289 updateR.setTop( frameWidth() );
1292 int maxWX = maxViewX();
1293 int maxWY = maxViewY();
1294 if ( updateR.right() > maxWX )
1295 updateR.setRight( maxWX );
1296 if ( updateR.bottom() > maxWY )
1297 updateR.setBottom( maxWY );
1299 setupPainter( &paint ); // prepare for painting table
1301 int firstRow = findRow( updateR.y() );
1302 int firstCol = findCol( updateR.x() );
1303 int xStart, yStart;
1304 if ( !colXPos( firstCol, &xStart ) || !rowYPos( firstRow, &yStart ) ) {
1305 paint.eraseRect( updateR ); // erase area outside cells but in view
1306 return;
1308 int maxX = updateR.right();
1309 int maxY = updateR.bottom();
1310 int row = firstRow;
1311 int col;
1312 int yPos = yStart;
1313 int xPos = maxX+1; // in case the while() is empty
1314 int nextX;
1315 int nextY;
1316 QRect winR = viewRect();
1317 QRect cellR;
1318 QRect cellUR;
1319 #ifndef QT_NO_TRANSFORMATIONS
1320 QWMatrix matrix;
1321 #endif
1323 while ( yPos <= maxY && row < nRows ) {
1324 nextY = yPos + (cellH ? cellH : cellHeight( row ));
1325 if ( testTableFlags( Tbl_cutCellsV ) && nextY > ( maxWY + 1 ) )
1326 break;
1327 col = firstCol;
1328 xPos = xStart;
1329 while ( xPos <= maxX && col < nCols ) {
1330 nextX = xPos + (cellW ? cellW : cellWidth( col ));
1331 if ( testTableFlags( Tbl_cutCellsH ) && nextX > ( maxWX + 1 ) )
1332 break;
1334 cellR.setRect( xPos, yPos, cellW ? cellW : cellWidth(col),
1335 cellH ? cellH : cellHeight(row) );
1336 cellUR = cellR.intersect( updateR );
1337 if ( cellUR.isValid() ) {
1338 cellUpdateR = cellUR;
1339 cellUpdateR.moveBy( -xPos, -yPos ); // cell coordinates
1340 if ( eraseInPaint )
1341 paint.eraseRect( cellUR );
1343 #ifndef QT_NO_TRANSFORMATIONS
1344 matrix.translate( xPos, yPos );
1345 paint.setWorldMatrix( matrix );
1346 if ( testTableFlags(Tbl_clipCellPainting) ||
1347 frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1348 paint.setClipRect( cellUR );
1349 paintCell( &paint, row, col );
1350 paint.setClipping( FALSE );
1351 } else {
1352 paintCell( &paint, row, col );
1354 matrix.reset();
1355 paint.setWorldMatrix( matrix );
1356 #else
1357 paint.translate( xPos, yPos );
1358 if ( testTableFlags(Tbl_clipCellPainting) ||
1359 frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1360 paint.setClipRect( cellUR );
1361 paintCell( &paint, row, col );
1362 paint.setClipping( FALSE );
1363 } else {
1364 paintCell( &paint, row, col );
1366 paint.translate( -xPos, -yPos );
1367 #endif
1369 col++;
1370 xPos = nextX;
1372 row++;
1373 yPos = nextY;
1376 // while painting we have to erase any areas in the view that
1377 // are not covered by cells but are covered by the paint event
1378 // rectangle these must be erased. We know that xPos is the last
1379 // x pixel updated + 1 and that yPos is the last y pixel updated + 1.
1381 // Note that this needs to be done regardless whether we do
1382 // eraseInPaint or not. Reason: a subclass may implement
1383 // flicker-freeness and encourage the use of repaint(FALSE).
1384 // The subclass, however, cannot draw all pixels, just those
1385 // inside the cells. So QtTableView is reponsible for all pixels
1386 // outside the cells.
1388 QRect viewR = viewRect();
1389 const QColorGroup g = colorGroup();
1391 if ( xPos <= maxX ) {
1392 QRect r = viewR;
1393 r.setLeft( xPos );
1394 r.setBottom( yPos<maxY?yPos:maxY );
1395 if ( inherits( "QMultiLineEdit" ) )
1396 paint.fillRect( r.intersect( updateR ), g.base() );
1397 else
1398 paint.eraseRect( r.intersect( updateR ) );
1400 if ( yPos <= maxY ) {
1401 QRect r = viewR;
1402 r.setTop( yPos );
1403 if ( inherits( "QMultiLineEdit" ) )
1404 paint.fillRect( r.intersect( updateR ), g.base() );
1405 else
1406 paint.eraseRect( r.intersect( updateR ) );
1410 /*!\reimp
1412 void QtTableView::resizeEvent( QResizeEvent * )
1414 updateScrollBars( horValue | verValue | horSteps | horGeometry | horRange |
1415 verSteps | verGeometry | verRange );
1416 showOrHideScrollBars();
1417 updateFrameSize();
1418 int maxX = QMIN( xOffs, maxXOffset() ); // ### can be slow
1419 int maxY = QMIN( yOffs, maxYOffset() );
1420 setOffset( maxX, maxY );
1425 Redraws all visible cells in the table view.
1428 void QtTableView::updateView()
1430 repaint( viewRect() );
1434 Returns a pointer to the vertical scroll bar mainly so you can
1435 connect() to its signals. Note that the scroll bar works in pixel
1436 values; use findRow() to translate to cell numbers.
1439 QScrollBar *QtTableView::verticalScrollBar() const
1441 QtTableView *that = (QtTableView*)this; // semantic const
1442 if ( !vScrollBar ) {
1443 QScrollBar *sb = new QScrollBar( QScrollBar::Vertical, that );
1444 #ifndef QT_NO_CURSOR
1445 sb->setCursor( arrowCursor );
1446 #endif
1447 sb->resize( sb->sizeHint() ); // height is irrelevant
1448 Q_CHECK_PTR(sb);
1449 sb->setTracking( FALSE );
1450 sb->setFocusPolicy( NoFocus );
1451 connect( sb, SIGNAL(valueChanged(int)),
1452 SLOT(verSbValue(int)));
1453 connect( sb, SIGNAL(sliderMoved(int)),
1454 SLOT(verSbSliding(int)));
1455 connect( sb, SIGNAL(sliderReleased()),
1456 SLOT(verSbSlidingDone()));
1457 sb->hide();
1458 that->vScrollBar = sb;
1459 return sb;
1461 return vScrollBar;
1465 Returns a pointer to the horizontal scroll bar mainly so you can
1466 connect() to its signals. Note that the scroll bar works in pixel
1467 values; use findCol() to translate to cell numbers.
1470 QScrollBar *QtTableView::horizontalScrollBar() const
1472 QtTableView *that = (QtTableView*)this; // semantic const
1473 if ( !hScrollBar ) {
1474 QScrollBar *sb = new QScrollBar( QScrollBar::Horizontal, that );
1475 #ifndef QT_NO_CURSOR
1476 sb->setCursor( arrowCursor );
1477 #endif
1478 sb->resize( sb->sizeHint() ); // width is irrelevant
1479 sb->setFocusPolicy( NoFocus );
1480 Q_CHECK_PTR(sb);
1481 sb->setTracking( FALSE );
1482 connect( sb, SIGNAL(valueChanged(int)),
1483 SLOT(horSbValue(int)));
1484 connect( sb, SIGNAL(sliderMoved(int)),
1485 SLOT(horSbSliding(int)));
1486 connect( sb, SIGNAL(sliderReleased()),
1487 SLOT(horSbSlidingDone()));
1488 sb->hide();
1489 that->hScrollBar = sb;
1490 return sb;
1492 return hScrollBar;
1496 Enables or disables the horizontal scroll bar, as required by
1497 setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1500 void QtTableView::setHorScrollBar( bool on, bool update )
1502 if ( on ) {
1503 tFlags |= Tbl_hScrollBar;
1504 horizontalScrollBar(); // created
1505 if ( update )
1506 updateScrollBars( horMask | verMask );
1507 else
1508 sbDirty = sbDirty | (horMask | verMask);
1509 if ( testTableFlags( Tbl_vScrollBar ) )
1510 coverCornerSquare( TRUE );
1511 if ( autoUpdate() )
1512 sbDirty = sbDirty | horMask;
1513 } else {
1514 tFlags &= ~Tbl_hScrollBar;
1515 if ( !hScrollBar )
1516 return;
1517 coverCornerSquare( FALSE );
1518 bool hideScrollBar = autoUpdate() && hScrollBar->isVisible();
1519 if ( hideScrollBar )
1520 hScrollBar->hide();
1521 if ( update )
1522 updateScrollBars( verMask );
1523 else
1524 sbDirty = sbDirty | verMask;
1525 if ( hideScrollBar && isVisible() )
1526 repaint( hScrollBar->x(), hScrollBar->y(),
1527 width() - hScrollBar->x(), hScrollBar->height() );
1529 if ( update )
1530 updateFrameSize();
1535 Enables or disables the vertical scroll bar, as required by
1536 setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1539 void QtTableView::setVerScrollBar( bool on, bool update )
1541 if ( on ) {
1542 tFlags |= Tbl_vScrollBar;
1543 verticalScrollBar(); // created
1544 if ( update )
1545 updateScrollBars( verMask | horMask );
1546 else
1547 sbDirty = sbDirty | (horMask | verMask);
1548 if ( testTableFlags( Tbl_hScrollBar ) )
1549 coverCornerSquare( TRUE );
1550 if ( autoUpdate() )
1551 sbDirty = sbDirty | verMask;
1552 } else {
1553 tFlags &= ~Tbl_vScrollBar;
1554 if ( !vScrollBar )
1555 return;
1556 coverCornerSquare( FALSE );
1557 bool hideScrollBar = autoUpdate() && vScrollBar->isVisible();
1558 if ( hideScrollBar )
1559 vScrollBar->hide();
1560 if ( update )
1561 updateScrollBars( horMask );
1562 else
1563 sbDirty = sbDirty | horMask;
1564 if ( hideScrollBar && isVisible() )
1565 repaint( vScrollBar->x(), vScrollBar->y(),
1566 vScrollBar->width(), height() - vScrollBar->y() );
1568 if ( update )
1569 updateFrameSize();
1575 int QtTableView::findRawRow( int yPos, int *cellMaxY, int *cellMinY,
1576 bool goOutsideView ) const
1578 int r = -1;
1579 if ( nRows == 0 )
1580 return r;
1581 if ( goOutsideView || yPos >= minViewY() && yPos <= maxViewY() ) {
1582 if ( yPos < minViewY() ) {
1583 #if defined(QT_CHECK_RANGE)
1584 qWarning( "QtTableView::findRawRow: (%s) internal error: "
1585 "yPos < minViewY() && goOutsideView "
1586 "not supported. (%d,%d)",
1587 name( "unnamed" ), yPos, yOffs );
1588 #endif
1589 return -1;
1591 if ( cellH ) { // uniform cell height
1592 r = (yPos - minViewY() + yCellDelta)/cellH; // cell offs from top
1593 if ( cellMaxY )
1594 *cellMaxY = (r + 1)*cellH + minViewY() - yCellDelta - 1;
1595 if ( cellMinY )
1596 *cellMinY = r*cellH + minViewY() - yCellDelta;
1597 r += yCellOffs; // absolute cell index
1598 } else { // variable cell height
1599 QtTableView *tw = (QtTableView *)this;
1600 r = yCellOffs;
1601 int h = minViewY() - yCellDelta; //##arnt3
1602 int oldH = h;
1603 Q_ASSERT( r < nRows );
1604 while ( r < nRows ) {
1605 oldH = h;
1606 h += tw->cellHeight( r ); // Start of next cell
1607 if ( yPos < h )
1608 break;
1609 r++;
1611 if ( cellMaxY )
1612 *cellMaxY = h - 1;
1613 if ( cellMinY )
1614 *cellMinY = oldH;
1617 return r;
1622 int QtTableView::findRawCol( int xPos, int *cellMaxX, int *cellMinX ,
1623 bool goOutsideView ) const
1625 int c = -1;
1626 if ( nCols == 0 )
1627 return c;
1628 if ( goOutsideView || xPos >= minViewX() && xPos <= maxViewX() ) {
1629 if ( xPos < minViewX() ) {
1630 #if defined(QT_CHECK_RANGE)
1631 qWarning( "QtTableView::findRawCol: (%s) internal error: "
1632 "xPos < minViewX() && goOutsideView "
1633 "not supported. (%d,%d)",
1634 name( "unnamed" ), xPos, xOffs );
1635 #endif
1636 return -1;
1638 if ( cellW ) { // uniform cell width
1639 c = (xPos - minViewX() + xCellDelta)/cellW; //cell offs from left
1640 if ( cellMaxX )
1641 *cellMaxX = (c + 1)*cellW + minViewX() - xCellDelta - 1;
1642 if ( cellMinX )
1643 *cellMinX = c*cellW + minViewX() - xCellDelta;
1644 c += xCellOffs; // absolute cell index
1645 } else { // variable cell width
1646 QtTableView *tw = (QtTableView *)this;
1647 c = xCellOffs;
1648 int w = minViewX() - xCellDelta; //##arnt3
1649 int oldW = w;
1650 Q_ASSERT( c < nCols );
1651 while ( c < nCols ) {
1652 oldW = w;
1653 w += tw->cellWidth( c ); // Start of next cell
1654 if ( xPos < w )
1655 break;
1656 c++;
1658 if ( cellMaxX )
1659 *cellMaxX = w - 1;
1660 if ( cellMinX )
1661 *cellMinX = oldW;
1664 return c;
1669 Returns the index of the row at position \a yPos, where \a yPos is in
1670 \e widget coordinates. Returns -1 if \a yPos is outside the valid
1671 range.
1673 \sa findCol(), rowYPos()
1676 int QtTableView::findRow( int yPos ) const
1678 int cellMaxY;
1679 int row = findRawRow( yPos, &cellMaxY );
1680 if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() )
1681 row = - 1; // cell cut by bottom margin
1682 if ( row >= nRows )
1683 row = -1;
1684 return row;
1689 Returns the index of the column at position \a xPos, where \a xPos is
1690 in \e widget coordinates. Returns -1 if \a xPos is outside the valid
1691 range.
1693 \sa findRow(), colXPos()
1696 int QtTableView::findCol( int xPos ) const
1698 int cellMaxX;
1699 int col = findRawCol( xPos, &cellMaxX );
1700 if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() )
1701 col = - 1; // cell cut by right margin
1702 if ( col >= nCols )
1703 col = -1;
1704 return col;
1709 Computes the position in the widget of row \a row.
1711 Returns TRUE and stores the result in \a *yPos (in \e widget
1712 coordinates) if the row is visible. Returns FALSE and does not modify
1713 \a *yPos if \a row is invisible or invalid.
1715 \sa colXPos(), findRow()
1718 bool QtTableView::rowYPos( int row, int *yPos ) const
1720 int y;
1721 if ( row >= yCellOffs ) {
1722 if ( cellH ) {
1723 int lastVisible = lastRowVisible();
1724 if ( row > lastVisible || lastVisible == -1 )
1725 return FALSE;
1726 y = (row - yCellOffs)*cellH + minViewY() - yCellDelta;
1727 } else {
1728 //##arnt3
1729 y = minViewY() - yCellDelta; // y of leftmost cell in view
1730 int r = yCellOffs;
1731 QtTableView *tw = (QtTableView *)this;
1732 int maxY = maxViewY();
1733 while ( r < row && y <= maxY )
1734 y += tw->cellHeight( r++ );
1735 if ( y > maxY )
1736 return FALSE;
1739 } else {
1740 return FALSE;
1742 if ( yPos )
1743 *yPos = y;
1744 return TRUE;
1749 Computes the position in the widget of column \a col.
1751 Returns TRUE and stores the result in \a *xPos (in \e widget
1752 coordinates) if the column is visible. Returns FALSE and does not
1753 modify \a *xPos if \a col is invisible or invalid.
1755 \sa rowYPos(), findCol()
1758 bool QtTableView::colXPos( int col, int *xPos ) const
1760 int x;
1761 if ( col >= xCellOffs ) {
1762 if ( cellW ) {
1763 int lastVisible = lastColVisible();
1764 if ( col > lastVisible || lastVisible == -1 )
1765 return FALSE;
1766 x = (col - xCellOffs)*cellW + minViewX() - xCellDelta;
1767 } else {
1768 //##arnt3
1769 x = minViewX() - xCellDelta; // x of uppermost cell in view
1770 int c = xCellOffs;
1771 QtTableView *tw = (QtTableView *)this;
1772 int maxX = maxViewX();
1773 while ( c < col && x <= maxX )
1774 x += tw->cellWidth( c++ );
1775 if ( x > maxX )
1776 return FALSE;
1778 } else {
1779 return FALSE;
1781 if ( xPos )
1782 *xPos = x;
1783 return TRUE;
1788 Moves the visible area of the table right by \a xPixels and
1789 down by \a yPixels pixels. Both may be negative.
1791 \warning You might find that QScrollView offers a higher-level of
1792 functionality than using QtTableView and this function.
1794 This function is \e not the same as QWidget::scroll(); in particular,
1795 the signs of \a xPixels and \a yPixels have the reverse semantics.
1797 \sa setXOffset(), setYOffset(), setOffset(), setTopCell(),
1798 setLeftCell()
1801 void QtTableView::scroll( int xPixels, int yPixels )
1803 QWidget::scroll( -xPixels, -yPixels, contentsRect() );
1808 Returns the leftmost pixel of the table view in \e view
1809 coordinates. This excludes the frame and any header.
1811 \sa maxViewY(), viewWidth(), contentsRect()
1814 int QtTableView::minViewX() const
1816 return frameWidth();
1821 Returns the top pixel of the table view in \e view
1822 coordinates. This excludes the frame and any header.
1824 \sa maxViewX(), viewHeight(), contentsRect()
1827 int QtTableView::minViewY() const
1829 return frameWidth();
1834 Returns the rightmost pixel of the table view in \e view
1835 coordinates. This excludes the frame and any scroll bar, but
1836 includes blank pixels to the right of the visible table data.
1838 \sa maxViewY(), viewWidth(), contentsRect()
1841 int QtTableView::maxViewX() const
1843 return width() - 1 - frameWidth()
1844 - (tFlags & Tbl_vScrollBar ? VSBEXT
1845 : 0);
1850 Returns the bottom pixel of the table view in \e view
1851 coordinates. This excludes the frame and any scroll bar, but
1852 includes blank pixels below the visible table data.
1854 \sa maxViewX(), viewHeight(), contentsRect()
1857 int QtTableView::maxViewY() const
1859 return height() - 1 - frameWidth()
1860 - (tFlags & Tbl_hScrollBar ? HSBEXT
1861 : 0);
1866 Returns the width of the table view, as such, in \e view
1867 coordinates. This does not include any header, scroll bar or frame,
1868 but it does include background pixels to the right of the table data.
1870 \sa minViewX() maxViewX(), viewHeight(), contentsRect() viewRect()
1873 int QtTableView::viewWidth() const
1875 return maxViewX() - minViewX() + 1;
1880 Returns the height of the table view, as such, in \e view
1881 coordinates. This does not include any header, scroll bar or frame,
1882 but it does include background pixels below the table data.
1884 \sa minViewY() maxViewY() viewWidth() contentsRect() viewRect()
1887 int QtTableView::viewHeight() const
1889 return maxViewY() - minViewY() + 1;
1893 void QtTableView::doAutoScrollBars()
1895 int viewW = width() - frameWidth() - minViewX();
1896 int viewH = height() - frameWidth() - minViewY();
1897 bool vScrollOn = testTableFlags(Tbl_vScrollBar);
1898 bool hScrollOn = testTableFlags(Tbl_hScrollBar);
1899 int w = 0;
1900 int h = 0;
1901 int i;
1903 if ( testTableFlags(Tbl_autoHScrollBar) ) {
1904 if ( cellW ) {
1905 w = cellW*nCols;
1906 } else {
1907 i = 0;
1908 while ( i < nCols && w <= viewW )
1909 w += cellWidth( i++ );
1911 if ( w > viewW )
1912 hScrollOn = TRUE;
1913 else
1914 hScrollOn = FALSE;
1917 if ( testTableFlags(Tbl_autoVScrollBar) ) {
1918 if ( cellH ) {
1919 h = cellH*nRows;
1920 } else {
1921 i = 0;
1922 while ( i < nRows && h <= viewH )
1923 h += cellHeight( i++ );
1926 if ( h > viewH )
1927 vScrollOn = TRUE;
1928 else
1929 vScrollOn = FALSE;
1932 if ( testTableFlags(Tbl_autoHScrollBar) && vScrollOn && !hScrollOn )
1933 if ( w > viewW - VSBEXT )
1934 hScrollOn = TRUE;
1936 if ( testTableFlags(Tbl_autoVScrollBar) && hScrollOn && !vScrollOn )
1937 if ( h > viewH - HSBEXT )
1938 vScrollOn = TRUE;
1940 setHorScrollBar( hScrollOn, FALSE );
1941 setVerScrollBar( vScrollOn, FALSE );
1942 updateFrameSize();
1947 \fn void QtTableView::updateScrollBars()
1949 Updates the scroll bars' contents and presence to match the table's
1950 state. Generally, you should not need to call this.
1952 \sa setTableFlags()
1956 Updates the scroll bars' contents and presence to match the table's
1957 state \c or \a f.
1959 \sa setTableFlags()
1962 void QtTableView::updateScrollBars( uint f )
1964 sbDirty = sbDirty | f;
1965 if ( inSbUpdate )
1966 return;
1967 inSbUpdate = TRUE;
1969 if ( testTableFlags(Tbl_autoHScrollBar) && (sbDirty & horRange) ||
1970 testTableFlags(Tbl_autoVScrollBar) && (sbDirty & verRange) )
1971 // if range change and auto
1972 doAutoScrollBars(); // turn scroll bars on/off if needed
1974 if ( !autoUpdate() ) {
1975 inSbUpdate = FALSE;
1976 return;
1978 if ( yOffset() > 0 && testTableFlags( Tbl_autoVScrollBar ) &&
1979 !testTableFlags( Tbl_vScrollBar ) ) {
1980 setYOffset( 0 );
1982 if ( xOffset() > 0 && testTableFlags( Tbl_autoHScrollBar ) &&
1983 !testTableFlags( Tbl_hScrollBar ) ) {
1984 setXOffset( 0 );
1986 if ( !isVisible() ) {
1987 inSbUpdate = FALSE;
1988 return;
1991 if ( testTableFlags(Tbl_hScrollBar) && (sbDirty & horMask) != 0 ) {
1992 if ( sbDirty & horGeometry )
1993 hScrollBar->setGeometry( 0,height() - HSBEXT,
1994 viewWidth() + frameWidth()*2,
1995 HSBEXT);
1997 if ( sbDirty & horSteps ) {
1998 if ( cellW )
1999 hScrollBar->setSteps( QMIN(cellW,viewWidth()/2), viewWidth() );
2000 else
2001 hScrollBar->setSteps( 16, viewWidth() );
2004 if ( sbDirty & horRange )
2005 hScrollBar->setRange( 0, maxXOffset() );
2007 if ( sbDirty & horValue )
2008 hScrollBar->setValue( xOffs );
2010 // show scrollbar only when it has a sane geometry
2011 if ( !hScrollBar->isVisible() )
2012 hScrollBar->show();
2015 if ( testTableFlags(Tbl_vScrollBar) && (sbDirty & verMask) != 0 ) {
2016 if ( sbDirty & verGeometry )
2017 vScrollBar->setGeometry( width() - VSBEXT, 0,
2018 VSBEXT,
2019 viewHeight() + frameWidth()*2 );
2021 if ( sbDirty & verSteps ) {
2022 if ( cellH )
2023 vScrollBar->setSteps( QMIN(cellH,viewHeight()/2), viewHeight() );
2024 else
2025 vScrollBar->setSteps( 16, viewHeight() ); // fttb! ###
2028 if ( sbDirty & verRange )
2029 vScrollBar->setRange( 0, maxYOffset() );
2031 if ( sbDirty & verValue )
2032 vScrollBar->setValue( yOffs );
2034 // show scrollbar only when it has a sane geometry
2035 if ( !vScrollBar->isVisible() )
2036 vScrollBar->show();
2038 if ( coveringCornerSquare &&
2039 ( (sbDirty & verGeometry ) || (sbDirty & horGeometry)) )
2040 cornerSquare->move( maxViewX() + frameWidth() + 1,
2041 maxViewY() + frameWidth() + 1 );
2043 sbDirty = 0;
2044 inSbUpdate = FALSE;
2048 void QtTableView::updateFrameSize()
2050 int rw = width() - ( testTableFlags(Tbl_vScrollBar) ?
2051 VSBEXT : 0 );
2052 int rh = height() - ( testTableFlags(Tbl_hScrollBar) ?
2053 HSBEXT : 0 );
2054 if ( rw < 0 )
2055 rw = 0;
2056 if ( rh < 0 )
2057 rh = 0;
2059 if ( autoUpdate() ) {
2060 int fh = frameRect().height();
2061 int fw = frameRect().width();
2062 setFrameRect( QRect(0,0,rw,rh) );
2064 if ( rw != fw )
2065 update( QMIN(fw,rw) - frameWidth() - 2, 0, frameWidth()+4, rh );
2066 if ( rh != fh )
2067 update( 0, QMIN(fh,rh) - frameWidth() - 2, rw, frameWidth()+4 );
2073 Returns the maximum horizontal offset within the table of the
2074 view's left edge in \e table coordinates.
2076 This is used mainly to set the horizontal scroll bar's range.
2078 \sa maxColOffset(), maxYOffset(), totalWidth()
2081 int QtTableView::maxXOffset()
2083 int tw = totalWidth();
2084 int maxOffs;
2085 if ( testTableFlags(Tbl_scrollLastHCell) ) {
2086 if ( nCols != 1)
2087 maxOffs = tw - ( cellW ? cellW : cellWidth( nCols - 1 ) );
2088 else
2089 maxOffs = tw - viewWidth();
2090 } else {
2091 if ( testTableFlags(Tbl_snapToHGrid) ) {
2092 if ( cellW ) {
2093 maxOffs = tw - (viewWidth()/cellW)*cellW;
2094 } else {
2095 int goal = tw - viewWidth();
2096 int pos = tw;
2097 int nextCol = nCols - 1;
2098 int nextCellWidth = cellWidth( nextCol );
2099 while( nextCol > 0 && pos > goal + nextCellWidth ) {
2100 pos -= nextCellWidth;
2101 nextCellWidth = cellWidth( --nextCol );
2103 if ( goal + nextCellWidth == pos )
2104 maxOffs = goal;
2105 else if ( goal < pos )
2106 maxOffs = pos;
2107 else
2108 maxOffs = 0;
2110 } else {
2111 maxOffs = tw - viewWidth();
2114 return maxOffs > 0 ? maxOffs : 0;
2119 Returns the maximum vertical offset within the table of the
2120 view's top edge in \e table coordinates.
2122 This is used mainly to set the vertical scroll bar's range.
2124 \sa maxRowOffset(), maxXOffset(), totalHeight()
2127 int QtTableView::maxYOffset()
2129 int th = totalHeight();
2130 int maxOffs;
2131 if ( testTableFlags(Tbl_scrollLastVCell) ) {
2132 if ( nRows != 1)
2133 maxOffs = th - ( cellH ? cellH : cellHeight( nRows - 1 ) );
2134 else
2135 maxOffs = th - viewHeight();
2136 } else {
2137 if ( testTableFlags(Tbl_snapToVGrid) ) {
2138 if ( cellH ) {
2139 maxOffs = th - (viewHeight()/cellH)*cellH;
2140 } else {
2141 int goal = th - viewHeight();
2142 int pos = th;
2143 int nextRow = nRows - 1;
2144 int nextCellHeight = cellHeight( nextRow );
2145 while( nextRow > 0 && pos > goal + nextCellHeight ) {
2146 pos -= nextCellHeight;
2147 nextCellHeight = cellHeight( --nextRow );
2149 if ( goal + nextCellHeight == pos )
2150 maxOffs = goal;
2151 else if ( goal < pos )
2152 maxOffs = pos;
2153 else
2154 maxOffs = 0;
2156 } else {
2157 maxOffs = th - viewHeight();
2160 return maxOffs > 0 ? maxOffs : 0;
2165 Returns the index of the last column, which may be at the left edge
2166 of the view.
2168 Depending on the \link setTableFlags() Tbl_scrollLastHCell\endlink flag,
2169 this may or may not be the last column.
2171 \sa maxXOffset(), maxRowOffset()
2174 int QtTableView::maxColOffset()
2176 int mx = maxXOffset();
2177 if ( cellW )
2178 return mx/cellW;
2179 else {
2180 int xcd=0, col=0;
2181 while ( col < nCols && mx > (xcd=cellWidth(col)) ) {
2182 mx -= xcd;
2183 col++;
2185 return col;
2191 Returns the index of the last row, which may be at the top edge of
2192 the view.
2194 Depending on the \link setTableFlags() Tbl_scrollLastVCell\endlink flag,
2195 this may or may not be the last row.
2197 \sa maxYOffset(), maxColOffset()
2200 int QtTableView::maxRowOffset()
2202 int my = maxYOffset();
2203 if ( cellH )
2204 return my/cellH;
2205 else {
2206 int ycd=0, row=0;
2207 while ( row < nRows && my > (ycd=cellHeight(row)) ) {
2208 my -= ycd;
2209 row++;
2211 return row;
2216 void QtTableView::showOrHideScrollBars()
2218 if ( !autoUpdate() )
2219 return;
2220 if ( vScrollBar ) {
2221 if ( testTableFlags(Tbl_vScrollBar) ) {
2222 if ( !vScrollBar->isVisible() )
2223 sbDirty = sbDirty | verMask;
2224 } else {
2225 if ( vScrollBar->isVisible() )
2226 vScrollBar->hide();
2229 if ( hScrollBar ) {
2230 if ( testTableFlags(Tbl_hScrollBar) ) {
2231 if ( !hScrollBar->isVisible() )
2232 sbDirty = sbDirty | horMask;
2233 } else {
2234 if ( hScrollBar->isVisible() )
2235 hScrollBar->hide();
2238 if ( cornerSquare ) {
2239 if ( testTableFlags(Tbl_hScrollBar) &&
2240 testTableFlags(Tbl_vScrollBar) ) {
2241 if ( !cornerSquare->isVisible() )
2242 cornerSquare->show();
2243 } else {
2244 if ( cornerSquare->isVisible() )
2245 cornerSquare->hide();
2252 Updates the scroll bars and internal state.
2254 Call this function when the table view's total size is changed;
2255 typically because the result of cellHeight() or cellWidth() have changed.
2257 This function does not repaint the widget.
2260 void QtTableView::updateTableSize()
2262 bool updateOn = autoUpdate();
2263 setAutoUpdate( FALSE );
2264 int xofs = xOffset();
2265 xOffs++; //so that setOffset will not return immediately
2266 setOffset(xofs,yOffset(),FALSE); //to calculate internal state correctly
2267 setAutoUpdate(updateOn);
2269 updateScrollBars( horSteps | horRange |
2270 verSteps | verRange );
2271 showOrHideScrollBars();
2275 #endif
2276 #endif