1 /**********************************************************************
2 ** $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.4 $ $NHDT-Date: 1524684508 2018/04/25 19:28:28 $
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.
10 **
11 ** This file contains a class moved out of the Qt GUI Toolkit API. It
12 ** may be used, distributed and modified without limitation.
13 **
14 **********************************************************************/
15 
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>
23 
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
35 };
36 
37 
38 #define HSBEXT horizontalScrollBar()->sizeHint().height()
39 #define VSBEXT verticalScrollBar()->sizeHint().width()
40 
41 
42 class QCornerSquare : public QWidget		// internal class
43 {
44 public:
45     QCornerSquare( QWidget *, const char* = 0 );
46     void paintEvent( QPaintEvent * );
47 };
48 
QCornerSquare(QWidget * parent,const char * name)49 QCornerSquare::QCornerSquare( QWidget *parent, const char *name )
50 	: QWidget( parent, name )
51 {
52 }
53 
paintEvent(QPaintEvent *)54 void QCornerSquare::paintEvent( QPaintEvent * )
55 {
56 }
57 
58 
59 // NOT REVISED
60 /*!
61   \class QtTableView qttableview.h
62   \brief The QtTableView class provides an abstract base for tables.
63 
64   \obsolete
65 
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.
70 
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.
78 
79   When you read this documentation, it is important to understand the
80   distinctions among the four pixel coordinate systems involved.
81 
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().
85 
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().
90 
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().
93 
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
97 
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.
101 
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).
106 
107   <img src=qtablevw-m.png> <img src=qtablevw-w.png>
108 
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.
114 
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.
122 
123   \sa QScrollView
124   \link guibooks.html#fowler GUI Design Handbook: Table\endlink
125 */
126 
127 
128 /*!
129   Constructs a table view.  The \a parent, \a name and \f arguments
130   are passed to the QFrame constructor.
131 
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.
135 
136   The \link setCellHeight() cell height\endlink and \link setCellWidth()
137   cell width\endlink are set to 0.
138 
139   Frame line shapes (QFrame::HLink and QFrame::VLine) are disallowed;
140   see QFrame::setFrameStyle().
141 
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
145 
146 */
147 
QtTableView(QWidget * parent,const char * name,WFlags f)148 QtTableView::QtTableView( QWidget *parent, const char *name, WFlags f )
149     : QFrame( parent, name, f )
150 {
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;
167 }
168 
169 /*!
170   Destroys the table view.
171 */
172 
~QtTableView()173 QtTableView::~QtTableView()
174 {
175     delete vScrollBar;
176     delete hScrollBar;
177     delete cornerSquare;
178 }
179 
180 
181 /*!
182   \internal
183   Reimplements QWidget::setBackgroundColor() for binary compatibility.
184   \sa setPalette()
185 */
186 
setBackgroundColor(const QColor & c)187 void QtTableView::setBackgroundColor( const QColor &c )
188 {
189     QWidget::setBackgroundColor( c );
190 }
191 
192 /*!\reimp
193 */
194 
setPalette(const QPalette & p)195 void QtTableView::setPalette( const QPalette &p )
196 {
197     QWidget::setPalette( p );
198 }
199 
200 /*!\reimp
201 */
202 
show()203 void QtTableView::show()
204 {
205     showOrHideScrollBars();
206     QWidget::show();
207 }
208 
209 
210 /*!
211   \overload void QtTableView::repaint( bool erase )
212   Repaints the entire view.
213 */
214 
215 /*!
216   Repaints the table view directly by calling paintEvent() directly
217   unless updates are disabled.
218 
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.
221 
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>.
224 
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.
228 
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.  */
233 
repaint(int x,int y,int w,int h,bool erase)234 void QtTableView::repaint( int x, int y, int w, int h, bool erase )
235 {
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;
250 }
251 
252 /*!
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.
256 */
257 
258 
259 /*!
260   \fn int QtTableView::numRows() const
261   Returns the number of rows in the table.
262   \sa numCols(), setNumRows()
263 */
264 
265 /*!
266   Sets the number of rows of the table to \a rows (must be non-negative).
267   Does not change topCell().
268 
269   The table repaints itself automatically if autoUpdate() is set.
270 
271   \sa numCols(), setNumCols(), numRows()
272 */
273 
setNumRows(int rows)274 void QtTableView::setNumRows( int rows )
275 {
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;
282     }
283     if ( nRows == rows )
284 	return;
285 
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;
296     }
297     updateScrollBars( verRange );
298     updateFrameSize();
299 }
300 
301 /*!
302   \fn int QtTableView::numCols() const
303   Returns the number of columns in the table.
304   \sa numRows(), setNumCols()
305 */
306 
307 /*!
308   Sets the number of columns of the table to \a cols (must be non-negative).
309   Does not change leftCell().
310 
311   The table repaints itself automatically if autoUpdate() is set.
312 
313   \sa numCols(), numRows(), setNumRows()
314 */
315 
setNumCols(int cols)316 void QtTableView::setNumCols( int cols )
317 {
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;
324     }
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();
333     }
334     updateScrollBars( horRange );
335     updateFrameSize();
336 }
337 
338 
339 /*!
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()
344 */
345 
346 /*!
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()
350 */
351 
setTopCell(int row)352 void QtTableView::setTopCell( int row )
353 {
354     setTopLeftCell( row, -1 );
355     return;
356 }
357 
358 /*!
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()
363 */
364 
365 /*!
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()
369 */
370 
setLeftCell(int col)371 void QtTableView::setLeftCell( int col )
372 {
373     setTopLeftCell( -1, col );
374     return;
375 }
376 
377 /*!
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()
382 */
383 
setTopLeftCell(int row,int col)384 void QtTableView::setTopLeftCell( int row, int col )
385 {
386     int newX = xOffs;
387     int newY = yOffs;
388 
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! ###
398 	}
399     }
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! ###
409 	}
410     }
411     setOffset( newX, newY );
412 }
413 
414 
415 /*!
416   \fn int QtTableView::xOffset() const
417 
418   Returns the x coordinate in \e table coordinates of the pixel that is
419   currently on the left edge of the view.
420 
421   \sa setXOffset(), yOffset(), leftCell() */
422 
423 /*!
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.
426 
427   The interaction with \link setTableFlags() Tbl_snapToHGrid
428   \endlink is tricky.
429 
430   \sa xOffset(), setYOffset(), setOffset(), setLeftCell()
431 */
432 
setXOffset(int x)433 void QtTableView::setXOffset( int x )
434 {
435     setOffset( x, yOffset() );
436 }
437 
438 /*!
439   \fn int QtTableView::yOffset() const
440 
441   Returns the y coordinate in \e table coordinates of the pixel that is
442   currently on the top edge of the view.
443 
444   \sa setYOffset(), xOffset(), topCell()
445 */
446 
447 
448 /*!
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.
451 
452   The interaction with \link setTableFlags() Tbl_snapToVGrid
453   \endlink is tricky.
454 
455   \sa yOffset(), setXOffset(), setOffset(), setTopCell()
456 */
457 
setYOffset(int y)458 void QtTableView::setYOffset( int y )
459 {
460     setOffset( xOffset(), y );
461 }
462 
463 /*!
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.
466 
467   The interaction with \link setTableFlags() Tbl_snapTo*Grid \endlink
468   is tricky.  If \a updateScrBars is TRUE, the scroll bars are
469   updated.
470 
471   \sa xOffset(), yOffset(), setXOffset(), setYOffset(), setTopLeftCell()
472 */
473 
setOffset(int x,int y,bool updateScrBars)474 void QtTableView::setOffset( int x, int y, bool updateScrBars )
475 {
476     if ( (!testTableFlags(Tbl_snapToHGrid) || xCellDelta == 0) &&
477 	 (!testTableFlags(Tbl_snapToVGrid) || yCellDelta == 0) &&
478 	 (x == xOffs && y == yOffs) )
479 	return;
480 
481     if ( x < 0 )
482 	x = 0;
483     if ( y < 0 )
484 	y = 0;
485 
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;
495 	}
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++;
501 	}
502 	xCellOffs = col;
503 	if ( testTableFlags(Tbl_snapToHGrid) ) {
504 	    xCellDelta = 0;
505 	    x = xn;
506 	} else {
507 	    xCellDelta = (short)(x-xn);
508 	}
509     }
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;
519 	}
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++;
525 	}
526 	yCellOffs = row;
527 	if ( testTableFlags(Tbl_snapToVGrid) ) {
528 	    yCellDelta = 0;
529 	    y = yn;
530 	} else {
531 	    yCellDelta = (short)(y-yn);
532 	}
533     }
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 );
542 }
543 
544 
545 /*!
546   \overload int QtTableView::cellWidth() const
547 
548   Returns the column width in pixels.	Returns 0 if the columns have
549   variable widths.
550 
551   \sa setCellWidth(), cellHeight()
552 */
553 
554 /*!
555   Returns the width of column \a col in pixels.
556 
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.
560 
561   \sa setCellWidth(), cellHeight(), totalWidth(), updateTableSize()
562 */
563 
cellWidth(int)564 int QtTableView::cellWidth( int )
565 {
566     return cellW;
567 }
568 
569 
570 /*!
571   Sets the width in pixels of the table cells to \a cellWidth.
572 
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.
576 
577   \sa cellWidth(), setCellHeight(), totalWidth(), numCols()
578 */
579 
setCellWidth(int cellWidth)580 void QtTableView::setCellWidth( int cellWidth )
581 {
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;
589     }
590 #endif
591     cellW = (short)cellWidth;
592 
593     updateScrollBars( horSteps | horRange );
594     if ( autoUpdate() && isVisible() )
595 	repaint();
596 
597 }
598 
599 /*!
600   \overload int QtTableView::cellHeight() const
601 
602   Returns the row height, in pixels.  Returns 0 if the rows have
603   variable heights.
604 
605   \sa setCellHeight(), cellWidth()
606 */
607 
608 
609 /*!
610   Returns the height of row \a row in pixels.
611 
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.
615 
616   \sa setCellHeight(), cellWidth(), totalHeight()
617 */
618 
cellHeight(int)619 int QtTableView::cellHeight( int )
620 {
621     return cellH;
622 }
623 
624 /*!
625   Sets the height in pixels of the table cells to \a cellHeight.
626 
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.
630 
631   \sa cellHeight(), setCellWidth(), totalHeight(), numRows()
632 */
633 
setCellHeight(int cellHeight)634 void QtTableView::setCellHeight( int cellHeight )
635 {
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;
643     }
644 #endif
645     cellH = (short)cellHeight;
646     if ( autoUpdate() && isVisible() )
647 	repaint();
648     updateScrollBars( verSteps | verRange );
649 }
650 
651 
652 /*!
653   Returns the total width of the table in pixels.
654 
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.
658 
659   The default implementation may be slow for very wide tables.
660 
661   \sa cellWidth(), totalHeight() */
662 
totalWidth()663 int QtTableView::totalWidth()
664 {
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;
672     }
673 }
674 
675 /*!
676   Returns the total height of the table in pixels.
677 
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.
681 
682   The default implementation may be slow for very tall tables.
683 
684   \sa cellHeight(), totalWidth()
685 */
686 
totalHeight()687 int QtTableView::totalHeight()
688 {
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;
696     }
697 }
698 
699 
700 /*!
701   \fn uint QtTableView::tableFlags() const
702 
703   Returns the union of the table flags that are currently set.
704 
705   \sa setTableFlags(), clearTableFlags(), testTableFlags()
706 */
707 
708 /*!
709   \fn bool QtTableView::testTableFlags( uint f ) const
710 
711   Returns TRUE if any of the table flags in \a f are currently set,
712   otherwise FALSE.
713 
714   \sa setTableFlags(), clearTableFlags(), tableFlags()
715 */
716 
717 /*!
718   Sets the table flags to \a f.
719 
720   If a flag setting changes the appearance of the table, the table is
721   repainted if - and only if - autoUpdate() is TRUE.
722 
723   The table flags are mostly single bits, though there are some multibit
724   flags for convenience. Here is a complete list:
725 
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>
766 
767   You can specify more than one flag at a time using bitwise OR.
768 
769   Example:
770   \code
771     setTableFlags( Tbl_smoothScrolling | Tbl_autoScrollBars );
772   \endcode
773 
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.
777 
778 
779   \sa clearTableFlags(), testTableFlags(), tableFlags()
780 */
781 
setTableFlags(uint f)782 void QtTableView::setTableFlags( uint f )
783 {
784     f = (f ^ tFlags) & f;			// clear flags already set
785     tFlags |= f;
786 
787     bool updateOn = autoUpdate();
788     setAutoUpdate( FALSE );
789 
790     uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
791 
792     if ( f & Tbl_vScrollBar ) {
793 	setVerScrollBar( TRUE );
794     }
795     if ( f & Tbl_hScrollBar ) {
796 	setHorScrollBar( TRUE );
797     }
798     if ( f & Tbl_autoVScrollBar ) {
799 	updateScrollBars( verRange );
800     }
801     if ( f & Tbl_autoHScrollBar ) {
802 	updateScrollBars( horRange );
803     }
804     if ( f & Tbl_scrollLastHCell ) {
805 	updateScrollBars( horRange );
806     }
807     if ( f & Tbl_scrollLastVCell ) {
808 	updateScrollBars( verRange );
809     }
810     if ( f & Tbl_snapToHGrid ) {
811 	updateScrollBars( horRange );
812     }
813     if ( f & Tbl_snapToVGrid ) {
814 	updateScrollBars( verRange );
815     }
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
822 	}
823     }
824 
825     if ( updateOn ) {
826 	setAutoUpdate( TRUE );
827 	updateScrollBars();
828 	if ( isVisible() && (f & repaintMask) )
829 	    repaint();
830     }
831 
832 }
833 
834 /*!
835   Clears the \link setTableFlags() table flags\endlink that are set
836   in \a f.
837 
838   Example (clears a single flag):
839   \code
840     clearTableFlags( Tbl_snapToGrid );
841   \endcode
842 
843   The default argument clears all flags.
844 
845   \sa setTableFlags(), testTableFlags(), tableFlags()
846 */
847 
clearTableFlags(uint f)848 void QtTableView::clearTableFlags( uint f )
849 {
850     f = (f ^ ~tFlags) & f;		// clear flags that are already 0
851     tFlags &= ~f;
852 
853     bool updateOn = autoUpdate();
854     setAutoUpdate( FALSE );
855 
856     uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
857 
858     if ( f & Tbl_vScrollBar ) {
859 	setVerScrollBar( FALSE );
860     }
861     if ( f & Tbl_hScrollBar ) {
862 	setHorScrollBar( FALSE );
863     }
864     if ( f & Tbl_scrollLastHCell ) {
865 	int maxX = maxXOffset();
866 	if ( xOffs > maxX ) {
867 	    setOffset( maxX, yOffs );
868 	    repaintMask |= Tbl_scrollLastHCell;
869 	}
870 	updateScrollBars( horRange );
871     }
872     if ( f & Tbl_scrollLastVCell ) {
873 	int maxY = maxYOffset();
874 	if ( yOffs > maxY ) {
875 	    setOffset( xOffs, maxY );
876 	    repaintMask |= Tbl_scrollLastVCell;
877 	}
878 	updateScrollBars( verRange );
879     }
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
886 	}
887     }
888     if ( f & Tbl_snapToHGrid ) {
889 	updateScrollBars( horRange );
890     }
891     if ( f & Tbl_snapToVGrid ) {
892 	updateScrollBars( verRange );
893     }
894     if ( updateOn ) {
895 	setAutoUpdate( TRUE );
896 	updateScrollBars();	     // returns immediately if nothing to do
897 	if ( isVisible() && (f & repaintMask) )
898 	    repaint();
899     }
900 
901 }
902 
903 
904 /*!
905   \fn bool QtTableView::autoUpdate() const
906 
907   Returns TRUE if the view updates itself automatically whenever it
908   is changed in some way.
909 
910   \sa setAutoUpdate()
911 */
912 
913 /*!
914   Sets the auto-update option of the table view to \a enable.
915 
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).
919 
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().
925 
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.
929 
930   Setting auto-update to TRUE does not repaint the view; you must call
931   repaint() to do this.
932 
933   \sa autoUpdate(), repaint()
934 */
935 
setAutoUpdate(bool enable)936 void QtTableView::setAutoUpdate( bool enable )
937 {
938     if ( isUpdatesEnabled() == enable )
939 	return;
940     setUpdatesEnabled( enable );
941     if ( enable ) {
942 	showOrHideScrollBars();
943 	updateScrollBars();
944     }
945 }
946 
947 
948 /*!
949   Repaints the cell at row \a row, column \a col if it is inside the view.
950 
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.
953 
954   \sa isVisible()
955 */
956 
updateCell(int row,int col,bool erase)957 void QtTableView::updateCell( int row, int col, bool erase )
958 {
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 );
968 }
969 
970 
971 /*!
972   \fn QRect QtTableView::cellUpdateRect() const
973 
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().
978 
979 */
980 
981 /*!
982   Returns the rectangle that is the actual table, excluding any
983   frame, in \e widget coordinates.
984 */
985 
viewRect() const986 QRect QtTableView::viewRect() const
987 {
988     return QRect( frameWidth(), frameWidth(), viewWidth(), viewHeight() );
989 }
990 
991 
992 /*!
993   Returns the index of the last (bottom) row in the view.
994   The index of the first row is 0.
995 
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.
998 
999   \sa lastColVisible()
1000 */
1001 
lastRowVisible() const1002 int QtTableView::lastRowVisible() const
1003 {
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
1014 	}
1015     }
1016     return row;
1017 }
1018 
1019 /*!
1020   Returns the index of the last (right) column in the view.
1021   The index of the first column is 0.
1022 
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.
1025 
1026   \sa lastRowVisible()
1027 */
1028 
lastColVisible() const1029 int QtTableView::lastColVisible() const
1030 {
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
1041 	}
1042     }
1043     return col;
1044 }
1045 
1046 /*!
1047   Returns TRUE if \a row is at least partially visible.
1048   \sa colIsVisible()
1049 */
1050 
rowIsVisible(int row) const1051 bool QtTableView::rowIsVisible( int row ) const
1052 {
1053     return rowYPos( row, 0 );
1054 }
1055 
1056 /*!
1057   Returns TRUE if \a col is at least partially visible.
1058   \sa rowIsVisible()
1059 */
1060 
colIsVisible(int col) const1061 bool QtTableView::colIsVisible( int col ) const
1062 {
1063     return colXPos( col, 0 );
1064 }
1065 
1066 
1067 /*!
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.
1071 */
1072 
coverCornerSquare(bool enable)1073 void QtTableView::coverCornerSquare( bool enable )
1074 {
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);
1083     }
1084     if ( autoUpdate() && cornerSquare ) {
1085 	if ( enable )
1086 	    cornerSquare->show();
1087 	else
1088 	    cornerSquare->hide();
1089     }
1090 }
1091 
1092 
1093 /*!
1094   \internal
1095   Scroll the view to a position such that:
1096 
1097   If \a horizontal is TRUE, the leftmost column shown fits snugly
1098   with the left edge of the view.
1099 
1100   If \a vertical is TRUE, the top row shown fits snugly with the top
1101   of the view.
1102 
1103   You can achieve the same effect automatically by setting any of the
1104   \link setTableFlags() Tbl_snapTo*Grid \endlink table flags.
1105 */
1106 
snapToGrid(bool horizontal,bool vertical)1107 void QtTableView::snapToGrid( bool horizontal, bool vertical )
1108 {
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;
1117     }
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;
1124     }
1125     setTopLeftCell( newYCell, newXCell );  //row,column
1126 }
1127 
1128 /*!
1129   \internal
1130   This internal slot is connected to the horizontal scroll bar's
1131   QScrollBar::valueChanged() signal.
1132 
1133   Moves the table horizontally to offset \a val without updating the
1134   scroll bar.
1135 */
1136 
horSbValue(int val)1137 void QtTableView::horSbValue( int val )
1138 {
1139     if ( horSliding ) {
1140 	horSliding = FALSE;
1141 	if ( horSnappingOff ) {
1142 	    horSnappingOff = FALSE;
1143 	    tFlags |= Tbl_snapToHGrid;
1144 	}
1145     }
1146     setOffset( val, yOffs, FALSE );
1147 }
1148 
1149 /*!
1150   \internal
1151   This internal slot is connected to the horizontal scroll bar's
1152   QScrollBar::sliderMoved() signal.
1153 
1154   Scrolls the table smoothly horizontally even if \c Tbl_snapToHGrid is set.
1155 */
1156 
horSbSliding(int val)1157 void QtTableView::horSbSliding( int val )
1158 {
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 );
1166     }
1167 }
1168 
1169 /*!
1170   \internal
1171   This internal slot is connected to the horizontal scroll bar's
1172   QScrollBar::sliderReleased() signal.
1173 */
1174 
horSbSlidingDone()1175 void QtTableView::horSbSlidingDone( )
1176 {
1177     if ( testTableFlags(Tbl_snapToHGrid) &&
1178 	 testTableFlags(Tbl_smoothHScrolling) )
1179 	snapToGrid( TRUE, FALSE );
1180 }
1181 
1182 /*!
1183   \internal
1184   This internal slot is connected to the vertical scroll bar's
1185   QScrollBar::valueChanged() signal.
1186 
1187   Moves the table vertically to offset \a val without updating the
1188   scroll bar.
1189 */
1190 
verSbValue(int val)1191 void QtTableView::verSbValue( int val )
1192 {
1193     if ( verSliding ) {
1194 	verSliding = FALSE;
1195 	if ( verSnappingOff ) {
1196 	    verSnappingOff = FALSE;
1197 	    tFlags |= Tbl_snapToVGrid;
1198 	}
1199     }
1200     setOffset( xOffs, val, FALSE );
1201 }
1202 
1203 /*!
1204   \internal
1205   This internal slot is connected to the vertical scroll bar's
1206   QScrollBar::sliderMoved() signal.
1207 
1208   Scrolls the table smoothly vertically even if \c Tbl_snapToVGrid is set.
1209 */
1210 
verSbSliding(int val)1211 void QtTableView::verSbSliding( int val )
1212 {
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 );
1220     }
1221 }
1222 
1223 /*!
1224   \internal
1225   This internal slot is connected to the vertical scroll bar's
1226   QScrollBar::sliderReleased() signal.
1227 */
1228 
verSbSlidingDone()1229 void QtTableView::verSbSlidingDone( )
1230 {
1231     if ( testTableFlags(Tbl_snapToVGrid) &&
1232 	 testTableFlags(Tbl_smoothVScrolling) )
1233 	snapToGrid( FALSE, TRUE );
1234 }
1235 
1236 
1237 /*!
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.
1242 */
1243 
setupPainter(QPainter *)1244 void QtTableView::setupPainter( QPainter * )
1245 {
1246 }
1247 
1248 /*!
1249   \fn void QtTableView::paintCell( QPainter *p, int row, int col )
1250 
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.
1254 
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).
1260 
1261   The painter is not clipped by default and for maximum efficiency. For safety,
1262   call setTableFlags(Tbl_clipCellPainting) to enable clipping.
1263 
1264   \sa paintEvent(), setTableFlags() */
1265 
1266 
1267 /*!
1268   Handles paint events, \a e, for the table view.
1269 
1270   Calls paintCell() for the cells that needs to be repainted.
1271 */
1272 
paintEvent(QPaintEvent * e)1273 void QtTableView::paintEvent( QPaintEvent *e )
1274 {
1275     QRect updateR = e->rect();			// update rectangle
1276     if ( sbDirty ) {
1277 	bool e = eraseInPaint;
1278 	updateScrollBars();
1279 	eraseInPaint = e;
1280     }
1281 
1282     QPainter paint( this );
1283 
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() );
1290     }
1291 
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 );
1298 
1299     setupPainter( &paint );			// prepare for painting table
1300 
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;
1307     }
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
1322 
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;
1333 
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 );
1342 
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 );
1353 		}
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 );
1365 		}
1366 		paint.translate( -xPos, -yPos );
1367 #endif
1368 	    }
1369 	    col++;
1370 	    xPos = nextX;
1371 	}
1372 	row++;
1373 	yPos = nextY;
1374     }
1375 
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.
1380 
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.
1387 
1388     QRect viewR = viewRect();
1389     const QColorGroup g = colorGroup();
1390 
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 ) );
1399     }
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 ) );
1407     }
1408 }
1409 
1410 /*!\reimp
1411 */
resizeEvent(QResizeEvent *)1412 void QtTableView::resizeEvent( QResizeEvent * )
1413 {
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 );
1421 }
1422 
1423 
1424 /*!
1425   Redraws all visible cells in the table view.
1426 */
1427 
updateView()1428 void QtTableView::updateView()
1429 {
1430     repaint( viewRect() );
1431 }
1432 
1433 /*!
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.
1437 */
1438 
verticalScrollBar() const1439 QScrollBar *QtTableView::verticalScrollBar() const
1440 {
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;
1460     }
1461     return vScrollBar;
1462 }
1463 
1464 /*!
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.
1468 */
1469 
horizontalScrollBar() const1470 QScrollBar *QtTableView::horizontalScrollBar() const
1471 {
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;
1491     }
1492     return hScrollBar;
1493 }
1494 
1495 /*!
1496   Enables or disables the horizontal scroll bar, as required by
1497   setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1498 */
1499 
setHorScrollBar(bool on,bool update)1500 void QtTableView::setHorScrollBar( bool on, bool update )
1501 {
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() );
1528     }
1529     if ( update )
1530 	updateFrameSize();
1531 }
1532 
1533 
1534 /*!
1535   Enables or disables the vertical scroll bar, as required by
1536   setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1537 */
1538 
setVerScrollBar(bool on,bool update)1539 void QtTableView::setVerScrollBar( bool on, bool update )
1540 {
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() );
1567     }
1568     if ( update )
1569 	updateFrameSize();
1570 }
1571 
1572 
1573 
1574 
findRawRow(int yPos,int * cellMaxY,int * cellMinY,bool goOutsideView) const1575 int QtTableView::findRawRow( int yPos, int *cellMaxY, int *cellMinY,
1576 			    bool goOutsideView ) const
1577 {
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;
1590 	}
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++;
1610 	    }
1611 	    if ( cellMaxY )
1612 		*cellMaxY = h - 1;
1613 	    if ( cellMinY )
1614 		*cellMinY = oldH;
1615 	}
1616     }
1617     return r;
1618 
1619 }
1620 
1621 
findRawCol(int xPos,int * cellMaxX,int * cellMinX,bool goOutsideView) const1622 int QtTableView::findRawCol( int xPos, int *cellMaxX, int *cellMinX ,
1623 			    bool goOutsideView ) const
1624 {
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;
1637 	}
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++;
1657 	    }
1658 	    if ( cellMaxX )
1659 		*cellMaxX = w - 1;
1660 	    if ( cellMinX )
1661 		*cellMinX = oldW;
1662 	}
1663     }
1664     return c;
1665 }
1666 
1667 
1668 /*!
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.
1672 
1673   \sa findCol(), rowYPos()
1674 */
1675 
findRow(int yPos) const1676 int QtTableView::findRow( int yPos ) const
1677 {
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;
1685 }
1686 
1687 
1688 /*!
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.
1692 
1693   \sa findRow(), colXPos()
1694 */
1695 
findCol(int xPos) const1696 int QtTableView::findCol( int xPos ) const
1697 {
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;
1705 }
1706 
1707 
1708 /*!
1709   Computes the position in the widget of row \a row.
1710 
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.
1714 
1715   \sa colXPos(), findRow()
1716 */
1717 
rowYPos(int row,int * yPos) const1718 bool QtTableView::rowYPos( int row, int *yPos ) const
1719 {
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;
1737 
1738 	}
1739     } else {
1740 	return FALSE;
1741     }
1742     if ( yPos )
1743 	*yPos = y;
1744     return TRUE;
1745 }
1746 
1747 
1748 /*!
1749   Computes the position in the widget of column \a col.
1750 
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.
1754 
1755   \sa rowYPos(), findCol()
1756 */
1757 
colXPos(int col,int * xPos) const1758 bool QtTableView::colXPos( int col, int *xPos ) const
1759 {
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;
1777 	}
1778     } else {
1779 	return FALSE;
1780     }
1781     if ( xPos )
1782 	*xPos = x;
1783     return TRUE;
1784 }
1785 
1786 
1787 /*!
1788   Moves the visible area of the table right by \a xPixels and
1789   down by \a yPixels pixels.  Both may be negative.
1790 
1791   \warning You might find that QScrollView offers a higher-level of
1792 	functionality than using QtTableView and this function.
1793 
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.
1796 
1797   \sa setXOffset(), setYOffset(), setOffset(), setTopCell(),
1798   setLeftCell()
1799 */
1800 
scroll(int xPixels,int yPixels)1801 void QtTableView::scroll( int xPixels, int yPixels )
1802 {
1803     QWidget::scroll( -xPixels, -yPixels, contentsRect() );
1804 }
1805 
1806 
1807 /*!
1808   Returns the leftmost pixel of the table view in \e view
1809   coordinates.	This excludes the frame and any header.
1810 
1811   \sa maxViewY(), viewWidth(), contentsRect()
1812 */
1813 
minViewX() const1814 int QtTableView::minViewX() const
1815 {
1816     return frameWidth();
1817 }
1818 
1819 
1820 /*!
1821   Returns the top pixel of the table view in \e view
1822   coordinates.	This excludes the frame and any header.
1823 
1824   \sa maxViewX(), viewHeight(), contentsRect()
1825 */
1826 
minViewY() const1827 int QtTableView::minViewY() const
1828 {
1829     return frameWidth();
1830 }
1831 
1832 
1833 /*!
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.
1837 
1838   \sa maxViewY(), viewWidth(), contentsRect()
1839 */
1840 
maxViewX() const1841 int QtTableView::maxViewX() const
1842 {
1843     return width() - 1 - frameWidth()
1844         - (tFlags & Tbl_vScrollBar ? VSBEXT
1845            : 0);
1846 }
1847 
1848 
1849 /*!
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.
1853 
1854   \sa maxViewX(), viewHeight(), contentsRect()
1855 */
1856 
maxViewY() const1857 int QtTableView::maxViewY() const
1858 {
1859     return height() - 1 - frameWidth()
1860         - (tFlags & Tbl_hScrollBar ? HSBEXT
1861            : 0);
1862 }
1863 
1864 
1865 /*!
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.
1869 
1870   \sa minViewX() maxViewX(), viewHeight(), contentsRect() viewRect()
1871 */
1872 
viewWidth() const1873 int QtTableView::viewWidth() const
1874 {
1875     return maxViewX() - minViewX() + 1;
1876 }
1877 
1878 
1879 /*!
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.
1883 
1884   \sa minViewY() maxViewY() viewWidth() contentsRect() viewRect()
1885 */
1886 
viewHeight() const1887 int QtTableView::viewHeight() const
1888 {
1889     return maxViewY() - minViewY() + 1;
1890 }
1891 
1892 
doAutoScrollBars()1893 void QtTableView::doAutoScrollBars()
1894 {
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;
1902 
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++ );
1910 	}
1911 	if ( w > viewW )
1912 	    hScrollOn = TRUE;
1913 	else
1914 	    hScrollOn = FALSE;
1915     }
1916 
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++ );
1924 	}
1925 
1926 	if ( h > viewH )
1927 	    vScrollOn = TRUE;
1928 	else
1929 	    vScrollOn = FALSE;
1930     }
1931 
1932     if ( testTableFlags(Tbl_autoHScrollBar) && vScrollOn && !hScrollOn )
1933 	if ( w > viewW - VSBEXT )
1934 	    hScrollOn = TRUE;
1935 
1936     if ( testTableFlags(Tbl_autoVScrollBar) && hScrollOn && !vScrollOn )
1937 	if ( h > viewH - HSBEXT )
1938 	    vScrollOn = TRUE;
1939 
1940     setHorScrollBar( hScrollOn, FALSE );
1941     setVerScrollBar( vScrollOn, FALSE );
1942     updateFrameSize();
1943 }
1944 
1945 
1946 /*!
1947   \fn void QtTableView::updateScrollBars()
1948 
1949   Updates the scroll bars' contents and presence to match the table's
1950   state.  Generally, you should not need to call this.
1951 
1952   \sa setTableFlags()
1953 */
1954 
1955 /*!
1956   Updates the scroll bars' contents and presence to match the table's
1957   state \c or \a f.
1958 
1959   \sa setTableFlags()
1960 */
1961 
updateScrollBars(uint f)1962 void QtTableView::updateScrollBars( uint f )
1963 {
1964     sbDirty = sbDirty | f;
1965     if ( inSbUpdate )
1966 	return;
1967     inSbUpdate = TRUE;
1968 
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
1973 
1974     if ( !autoUpdate() ) {
1975 	inSbUpdate = FALSE;
1976 	return;
1977     }
1978     if ( yOffset() > 0 && testTableFlags( Tbl_autoVScrollBar ) &&
1979 	 !testTableFlags( Tbl_vScrollBar ) ) {
1980 	setYOffset( 0 );
1981     }
1982     if ( xOffset() > 0 && testTableFlags( Tbl_autoHScrollBar ) &&
1983 	 !testTableFlags( Tbl_hScrollBar ) ) {
1984 	setXOffset( 0 );
1985     }
1986     if ( !isVisible() ) {
1987 	inSbUpdate = FALSE;
1988 	return;
1989     }
1990 
1991     if ( testTableFlags(Tbl_hScrollBar) && (sbDirty & horMask) != 0 ) {
1992 	if ( sbDirty & horGeometry )
1993 	    hScrollBar->setGeometry( 0,height() - HSBEXT,
1994                                      viewWidth() + frameWidth()*2,
1995                                    HSBEXT);
1996 
1997 	if ( sbDirty & horSteps ) {
1998 	    if ( cellW )
1999 		hScrollBar->setSteps( QMIN(cellW,viewWidth()/2), viewWidth() );
2000 	    else
2001 		hScrollBar->setSteps( 16, viewWidth() );
2002 	}
2003 
2004 	if ( sbDirty & horRange )
2005 	    hScrollBar->setRange( 0, maxXOffset() );
2006 
2007 	if ( sbDirty & horValue )
2008 	    hScrollBar->setValue( xOffs );
2009 
2010 			// show scrollbar only when it has a sane geometry
2011 	if ( !hScrollBar->isVisible() )
2012 	    hScrollBar->show();
2013     }
2014 
2015     if ( testTableFlags(Tbl_vScrollBar) && (sbDirty & verMask) != 0 ) {
2016 	if ( sbDirty & verGeometry )
2017 	    vScrollBar->setGeometry( width() - VSBEXT, 0,
2018                                      VSBEXT,
2019                                      viewHeight() + frameWidth()*2 );
2020 
2021 	if ( sbDirty & verSteps ) {
2022 	    if ( cellH )
2023 		vScrollBar->setSteps( QMIN(cellH,viewHeight()/2), viewHeight() );
2024 	    else
2025 		vScrollBar->setSteps( 16, viewHeight() );  // fttb! ###
2026 	}
2027 
2028 	if ( sbDirty & verRange )
2029 	    vScrollBar->setRange( 0, maxYOffset() );
2030 
2031 	if ( sbDirty & verValue )
2032 	    vScrollBar->setValue( yOffs );
2033 
2034 			// show scrollbar only when it has a sane geometry
2035 	if ( !vScrollBar->isVisible() )
2036 	    vScrollBar->show();
2037     }
2038     if ( coveringCornerSquare &&
2039 	 ( (sbDirty & verGeometry ) || (sbDirty & horGeometry)) )
2040 	cornerSquare->move( maxViewX() + frameWidth() + 1,
2041 			    maxViewY() + frameWidth() + 1 );
2042 
2043     sbDirty = 0;
2044     inSbUpdate = FALSE;
2045 }
2046 
2047 
updateFrameSize()2048 void QtTableView::updateFrameSize()
2049 {
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;
2058 
2059     if ( autoUpdate() ) {
2060         int fh = frameRect().height();
2061 	int fw = frameRect().width();
2062 	setFrameRect( QRect(0,0,rw,rh) );
2063 
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 );
2068     }
2069 }
2070 
2071 
2072 /*!
2073   Returns the maximum horizontal offset within the table of the
2074   view's left edge in \e table coordinates.
2075 
2076   This is used mainly to set the horizontal scroll bar's range.
2077 
2078   \sa maxColOffset(), maxYOffset(), totalWidth()
2079 */
2080 
maxXOffset()2081 int QtTableView::maxXOffset()
2082 {
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 );
2102 		}
2103 		if ( goal + nextCellWidth == pos )
2104 		    maxOffs = goal;
2105 		 else if ( goal < pos )
2106 		   maxOffs = pos;
2107 		 else
2108 		   maxOffs = 0;
2109 	    }
2110 	} else {
2111 	    maxOffs = tw - viewWidth();
2112 	}
2113     }
2114     return maxOffs > 0 ? maxOffs : 0;
2115 }
2116 
2117 
2118 /*!
2119   Returns the maximum vertical offset within the table of the
2120   view's top edge in \e table coordinates.
2121 
2122   This is used mainly to set the vertical scroll bar's range.
2123 
2124   \sa maxRowOffset(), maxXOffset(), totalHeight()
2125 */
2126 
maxYOffset()2127 int QtTableView::maxYOffset()
2128 {
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 );
2148 		}
2149 		if ( goal + nextCellHeight == pos )
2150 		    maxOffs = goal;
2151 		 else if ( goal < pos )
2152 		   maxOffs = pos;
2153 		 else
2154 		   maxOffs = 0;
2155 	    }
2156 	} else {
2157 	    maxOffs = th - viewHeight();
2158 	}
2159     }
2160     return maxOffs > 0 ? maxOffs : 0;
2161 }
2162 
2163 
2164 /*!
2165   Returns the index of the last column, which may be at the left edge
2166   of the view.
2167 
2168   Depending on the \link setTableFlags() Tbl_scrollLastHCell\endlink flag,
2169   this may or may not be the last column.
2170 
2171   \sa maxXOffset(), maxRowOffset()
2172 */
2173 
maxColOffset()2174 int QtTableView::maxColOffset()
2175 {
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++;
2184 	}
2185 	return col;
2186     }
2187 }
2188 
2189 
2190 /*!
2191   Returns the index of the last row, which may be at the top edge of
2192   the view.
2193 
2194   Depending on the \link setTableFlags() Tbl_scrollLastVCell\endlink flag,
2195   this may or may not be the last row.
2196 
2197   \sa maxYOffset(), maxColOffset()
2198 */
2199 
maxRowOffset()2200 int QtTableView::maxRowOffset()
2201 {
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++;
2210 	}
2211 	return row;
2212     }
2213 }
2214 
2215 
showOrHideScrollBars()2216 void QtTableView::showOrHideScrollBars()
2217 {
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();
2227 	}
2228     }
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();
2236 	}
2237     }
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();
2246 	}
2247     }
2248 }
2249 
2250 
2251 /*!
2252   Updates the scroll bars and internal state.
2253 
2254   Call this function when the table view's total size is changed;
2255   typically because the result of cellHeight() or cellWidth() have changed.
2256 
2257   This function does not repaint the widget.
2258 */
2259 
updateTableSize()2260 void QtTableView::updateTableSize()
2261 {
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);
2268 
2269     updateScrollBars( horSteps |  horRange |
2270 		      verSteps |  verRange );
2271     showOrHideScrollBars();
2272 }
2273 
2274 
2275 #endif
2276 #endif
2277