OSDN Git Service

Initial Import
[nethackexpress/trunk.git] / win / Qt / qttableview.cpp
1 /**********************************************************************
2 ** $Id: qttableview.cpp,v 1.2 2002/03/09 03:13:15 jwalz Exp $
3 **
4 ** Implementation of QtTableView class
5 **
6 ** Created : 941115
7 **
8 ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
9 **
10 ** This file contains a class moved out of the Qt GUI Toolkit API. It
11 ** may be used, distributed and modified without limitation.
12 **
13 **********************************************************************/
14
15 #include "qttableview.h"
16 #if QT_VERSION >= 300
17 #ifndef QT_NO_QTTABLEVIEW
18 #include <qscrollbar.h>
19 #include <qpainter.h>
20 #include <qdrawutil.h>
21 #include <limits.h>
22
23 enum ScrollBarDirtyFlags {
24     verGeometry   = 0x01,
25     verSteps      = 0x02,
26     verRange      = 0x04,
27     verValue      = 0x08,
28     horGeometry   = 0x10,
29     horSteps      = 0x20,
30     horRange      = 0x40,
31     horValue      = 0x80,
32     verMask       = 0x0F,
33     horMask       = 0xF0
34 };
35
36
37 #define HSBEXT horizontalScrollBar()->sizeHint().height()
38 #define VSBEXT verticalScrollBar()->sizeHint().width()
39
40
41 class QCornerSquare : public QWidget            // internal class
42 {
43 public:
44     QCornerSquare( QWidget *, const char* = 0 );
45     void paintEvent( QPaintEvent * );
46 };
47
48 QCornerSquare::QCornerSquare( QWidget *parent, const char *name )
49         : QWidget( parent, name )
50 {
51 }
52
53 void QCornerSquare::paintEvent( QPaintEvent * )
54 {
55 }
56
57
58 // NOT REVISED
59 /*!
60   \class QtTableView qttableview.h
61   \brief The QtTableView class provides an abstract base for tables.
62
63   \obsolete
64
65   A table view consists of a number of abstract cells organized in rows
66   and columns, and a visible part called a view. The cells are identified
67   with a row index and a column index. The top-left cell is in row 0,
68   column 0.
69
70   The behavior of the widget can be finely tuned using
71   setTableFlags(); a typical subclass will consist of little more than a
72   call to setTableFlags(), some table content manipulation and an
73   implementation of paintCell().  Subclasses that need cells with
74   variable width or height must reimplement cellHeight() and/or
75   cellWidth(). Use updateTableSize() to tell QtTableView when the
76   width or height has changed.
77
78   When you read this documentation, it is important to understand the
79   distinctions among the four pixel coordinate systems involved.
80
81   \list 1
82   \i The \e cell coordinates.  (0,0) is the top-left corner of a cell.
83   Cell coordinates are used by functions such as paintCell().
84
85   \i The \e table coordinates.  (0,0) is the top-left corner of the cell at
86   row 0 and column 0. These coordinates are absolute; that is, they are
87   independent of what part of the table is visible at the moment. They are
88   used by functions such as setXOffset() or maxYOffset().
89
90   \i The \e widget coordinates. (0,0) is the top-left corner of the widget,
91   \e including the frame.  They are used by functions such as repaint().
92
93   \i The \e view coordinates.  (0,0) is the top-left corner of the view, \e
94   excluding the frame.  This is the least-used coordinate system; it is used by
95   functions such as viewWidth().  \endlist
96
97   It is rather unfortunate that we have to use four different
98   coordinate systems, but there was no alternative to provide a flexible and
99   powerful base class.
100
101   Note: The row,column indices are always given in that order,
102   i.e., first the vertical (row), then the horizontal (column). This is
103   the opposite order of all pixel operations, which take first the
104   horizontal (x) and then the vertical (y).
105
106   <img src=qtablevw-m.png> <img src=qtablevw-w.png>
107
108   \warning the functions setNumRows(), setNumCols(), setCellHeight(),
109   setCellWidth(), setTableFlags() and clearTableFlags() may cause
110   virtual functions such as cellWidth() and cellHeight() to be called,
111   even if autoUpdate() is FALSE.  This may cause errors if relevant
112   state variables are not initialized.
113
114   \warning Experience has shown that use of this widget tends to cause
115   more bugs than expected and our analysis indicates that the widget's
116   very flexibility is the problem.  If QScrollView or QListBox can
117   easily be made to do the job you need, we recommend subclassing
118   those widgets rather than QtTableView. In addition, QScrollView makes
119   it easy to have child widgets inside tables, which QtTableView
120   doesn't support at all.
121
122   \sa QScrollView
123   \link guibooks.html#fowler GUI Design Handbook: Table\endlink
124 */
125
126
127 /*!
128   Constructs a table view.  The \a parent, \a name and \f arguments
129   are passed to the QFrame constructor.
130
131   The \link setTableFlags() table flags\endlink are all cleared (set to 0).
132   Set \c Tbl_autoVScrollBar or \c Tbl_autoHScrollBar to get automatic scroll
133   bars and \c Tbl_clipCellPainting to get safe clipping.
134
135   The \link setCellHeight() cell height\endlink and \link setCellWidth()
136   cell width\endlink are set to 0.
137
138   Frame line shapes (QFrame::HLink and QFrame::VLine) are disallowed;
139   see QFrame::setFrameStyle().
140
141   Note that the \a f argument is \e not \link setTableFlags() table
142   flags \endlink but rather \link QWidget::QWidget() widget
143   flags. \endlink
144
145 */
146
147 QtTableView::QtTableView( QWidget *parent, const char *name, WFlags f )
148     : QFrame( parent, name, f )
149 {
150     nRows                = nCols      = 0;      // zero rows/cols
151     xCellOffs            = yCellOffs  = 0;      // zero offset
152     xCellDelta           = yCellDelta = 0;      // zero cell offset
153     xOffs                = yOffs      = 0;      // zero total pixel offset
154     cellH                = cellW      = 0;      // user defined cell size
155     tFlags               = 0;
156     vScrollBar           = hScrollBar = 0;      // no scroll bars
157     cornerSquare         = 0;
158     sbDirty              = 0;
159     eraseInPaint         = FALSE;
160     verSliding           = FALSE;
161     verSnappingOff       = FALSE;
162     horSliding           = FALSE;
163     horSnappingOff       = FALSE;
164     coveringCornerSquare = FALSE;
165     inSbUpdate           = FALSE;
166 }
167
168 /*!
169   Destroys the table view.
170 */
171
172 QtTableView::~QtTableView()
173 {
174     delete vScrollBar;
175     delete hScrollBar;
176     delete cornerSquare;
177 }
178
179
180 /*!
181   \internal
182   Reimplements QWidget::setBackgroundColor() for binary compatibility.
183   \sa setPalette()
184 */
185
186 void QtTableView::setBackgroundColor( const QColor &c )
187 {
188     QWidget::setBackgroundColor( c );
189 }
190
191 /*!\reimp
192 */
193
194 void QtTableView::setPalette( const QPalette &p )
195 {
196     QWidget::setPalette( p );
197 }
198
199 /*!\reimp
200 */
201
202 void QtTableView::show()
203 {
204     showOrHideScrollBars();
205     QWidget::show();
206 }
207
208
209 /*!
210   \overload void QtTableView::repaint( bool erase )
211   Repaints the entire view.
212 */
213
214 /*!
215   Repaints the table view directly by calling paintEvent() directly
216   unless updates are disabled.
217
218   Erases the view area \a (x,y,w,h) if \a erase is TRUE. Parameters \a
219   (x,y) are in \e widget coordinates.
220
221   If \a w is negative, it is replaced with <code>width() - x</code>.
222   If \a h is negative, it is replaced with <code>height() - y</code>.
223
224   Doing a repaint() usually is faster than doing an update(), but
225   calling update() many times in a row will generate a single paint
226   event.
227
228   At present, QtTableView is the only widget that reimplements \link
229   QWidget::repaint() repaint()\endlink.  It does this because by
230   clearing and then repainting one cell at at time, it can make the
231   screen flicker less than it would otherwise.  */
232
233 void QtTableView::repaint( int x, int y, int w, int h, bool erase )
234 {
235     if ( !isVisible() || testWState(WState_BlockUpdates) )
236         return;
237     if ( w < 0 )
238         w = width()  - x;
239     if ( h < 0 )
240         h = height() - y;
241     QRect r( x, y, w, h );
242     if ( r.isEmpty() )
243         return; // nothing to do
244     QPaintEvent e( r );
245     if ( erase && backgroundMode() != NoBackground )
246         eraseInPaint = TRUE;                    // erase when painting
247     paintEvent( &e );
248     eraseInPaint = FALSE;
249 }
250
251 /*!
252   \overload void QtTableView::repaint( const QRect &r, bool erase )
253   Replaints rectangle \a r. If \a erase is TRUE draws the background
254   using the palette's background.
255 */
256
257
258 /*!
259   \fn int QtTableView::numRows() const
260   Returns the number of rows in the table.
261   \sa numCols(), setNumRows()
262 */
263
264 /*!
265   Sets the number of rows of the table to \a rows (must be non-negative).
266   Does not change topCell().
267
268   The table repaints itself automatically if autoUpdate() is set.
269
270   \sa numCols(), setNumCols(), numRows()
271 */
272
273 void QtTableView::setNumRows( int rows )
274 {
275     if ( rows < 0 ) {
276 #if defined(QT_CHECK_RANGE)
277         qWarning( "QtTableView::setNumRows: (%s) Negative argument %d.",
278                  name( "unnamed" ), rows );
279 #endif
280         return;
281     }
282     if ( nRows == rows )
283         return;
284
285     if ( autoUpdate() && isVisible() ) {
286         int oldLastVisible = lastRowVisible();
287         int oldTopCell = topCell();
288         nRows = rows;
289         if ( autoUpdate() && isVisible() &&
290              ( oldLastVisible != lastRowVisible() || oldTopCell != topCell() ) )
291                 repaint( oldTopCell != topCell() );
292     } else {
293         // Be more careful - if destructing, bad things might happen.
294         nRows = rows;
295     }
296     updateScrollBars( verRange );
297     updateFrameSize();
298 }
299
300 /*!
301   \fn int QtTableView::numCols() const
302   Returns the number of columns in the table.
303   \sa numRows(), setNumCols()
304 */
305
306 /*!
307   Sets the number of columns of the table to \a cols (must be non-negative).
308   Does not change leftCell().
309
310   The table repaints itself automatically if autoUpdate() is set.
311
312   \sa numCols(), numRows(), setNumRows()
313 */
314
315 void QtTableView::setNumCols( int cols )
316 {
317     if ( cols < 0 ) {
318 #if defined(QT_CHECK_RANGE)
319         qWarning( "QtTableView::setNumCols: (%s) Negative argument %d.",
320                  name( "unnamed" ), cols );
321 #endif
322         return;
323     }
324     if ( nCols == cols )
325         return;
326     int oldCols = nCols;
327     nCols = cols;
328     if ( autoUpdate() && isVisible() ) {
329         int maxCol = lastColVisible();
330         if ( maxCol >= oldCols || maxCol >= nCols )
331             repaint();
332     }
333     updateScrollBars( horRange );
334     updateFrameSize();
335 }
336
337
338 /*!
339   \fn int QtTableView::topCell() const
340   Returns the index of the first row in the table that is visible in
341   the view.  The index of the first row is 0.
342   \sa leftCell(), setTopCell()
343 */
344
345 /*!
346   Scrolls the table so that \a row becomes the top row.
347   The index of the very first row is 0.
348   \sa setYOffset(), setTopLeftCell(), setLeftCell()
349 */
350
351 void QtTableView::setTopCell( int row )
352 {
353     setTopLeftCell( row, -1 );
354     return;
355 }
356
357 /*!
358   \fn int QtTableView::leftCell() const
359   Returns the index of the first column in the table that is visible in
360   the view.  The index of the very leftmost column is 0.
361   \sa topCell(), setLeftCell()
362 */
363
364 /*!
365   Scrolls the table so that \a col becomes the leftmost
366   column.  The index of the leftmost column is 0.
367   \sa setXOffset(), setTopLeftCell(), setTopCell()
368 */
369
370 void QtTableView::setLeftCell( int col )
371 {
372     setTopLeftCell( -1, col );
373     return;
374 }
375
376 /*!
377   Scrolls the table so that the cell at row \a row and colum \a
378   col becomes the top-left cell in the view.  The cell at the extreme
379   top left of the table is at position (0,0).
380   \sa setLeftCell(), setTopCell(), setOffset()
381 */
382
383 void QtTableView::setTopLeftCell( int row, int col )
384 {
385     int newX = xOffs;
386     int newY = yOffs;
387
388     if ( col >= 0 ) {
389         if ( cellW ) {
390             newX = col*cellW;
391             if ( newX > maxXOffset() )
392                 newX = maxXOffset();
393         } else {
394             newX = 0;
395             while ( col )
396                 newX += cellWidth( --col );   // optimize using current! ###
397         }
398     }
399     if ( row >= 0 ) {
400         if ( cellH ) {
401             newY = row*cellH;
402             if ( newY > maxYOffset() )
403                 newY = maxYOffset();
404         } else {
405             newY = 0;
406             while ( row )
407                 newY += cellHeight( --row );   // optimize using current! ###
408         }
409     }
410     setOffset( newX, newY );
411 }
412
413
414 /*!
415   \fn int QtTableView::xOffset() const
416
417   Returns the x coordinate in \e table coordinates of the pixel that is
418   currently on the left edge of the view.
419
420   \sa setXOffset(), yOffset(), leftCell() */
421
422 /*!
423   Scrolls the table so that \a x becomes the leftmost pixel in the view.
424   The \a x parameter is in \e table coordinates.
425
426   The interaction with \link setTableFlags() Tbl_snapToHGrid
427   \endlink is tricky.
428
429   \sa xOffset(), setYOffset(), setOffset(), setLeftCell()
430 */
431
432 void QtTableView::setXOffset( int x )
433 {
434     setOffset( x, yOffset() );
435 }
436
437 /*!
438   \fn int QtTableView::yOffset() const
439
440   Returns the y coordinate in \e table coordinates of the pixel that is
441   currently on the top edge of the view.
442
443   \sa setYOffset(), xOffset(), topCell()
444 */
445
446
447 /*!
448   Scrolls the table so that \a y becomes the top pixel in the view.
449   The \a y parameter is in \e table coordinates.
450
451   The interaction with \link setTableFlags() Tbl_snapToVGrid
452   \endlink is tricky.
453
454   \sa yOffset(), setXOffset(), setOffset(), setTopCell()
455 */
456
457 void QtTableView::setYOffset( int y )
458 {
459     setOffset( xOffset(), y );
460 }
461
462 /*!
463   Scrolls the table so that \a (x,y) becomes the top-left pixel
464   in the view. Parameters \a (x,y) are in \e table coordinates.
465
466   The interaction with \link setTableFlags() Tbl_snapTo*Grid \endlink
467   is tricky.  If \a updateScrBars is TRUE, the scroll bars are
468   updated.
469
470   \sa xOffset(), yOffset(), setXOffset(), setYOffset(), setTopLeftCell()
471 */
472
473 void QtTableView::setOffset( int x, int y, bool updateScrBars )
474 {
475     if ( (!testTableFlags(Tbl_snapToHGrid) || xCellDelta == 0) &&
476          (!testTableFlags(Tbl_snapToVGrid) || yCellDelta == 0) &&
477          (x == xOffs && y == yOffs) )
478         return;
479
480     if ( x < 0 )
481         x = 0;
482     if ( y < 0 )
483         y = 0;
484
485     if ( cellW ) {
486         if ( x > maxXOffset() )
487             x = maxXOffset();
488         xCellOffs = x / cellW;
489         if ( !testTableFlags(Tbl_snapToHGrid) ) {
490             xCellDelta  = (short)(x % cellW);
491         } else {
492             x           = xCellOffs*cellW;
493             xCellDelta  = 0;
494         }
495     } else {
496         int xn=0, xcd=0, col = 0;
497         while ( col < nCols-1 && x >= xn+(xcd=cellWidth(col)) ) {
498             xn += xcd;
499             col++;
500         }
501         xCellOffs = col;
502         if ( testTableFlags(Tbl_snapToHGrid) ) {
503             xCellDelta = 0;
504             x = xn;
505         } else {
506             xCellDelta = (short)(x-xn);
507         }
508     }
509     if ( cellH ) {
510         if ( y > maxYOffset() )
511             y = maxYOffset();
512         yCellOffs = y / cellH;
513         if ( !testTableFlags(Tbl_snapToVGrid) ) {
514             yCellDelta  = (short)(y % cellH);
515         } else {
516             y           = yCellOffs*cellH;
517             yCellDelta  = 0;
518         }
519     } else {
520         int yn=0, yrd=0, row=0;
521         while ( row < nRows-1 && y >= yn+(yrd=cellHeight(row)) ) {
522             yn += yrd;
523             row++;
524         }
525         yCellOffs = row;
526         if ( testTableFlags(Tbl_snapToVGrid) ) {
527             yCellDelta = 0;
528             y = yn;
529         } else {
530             yCellDelta = (short)(y-yn);
531         }
532     }
533     int dx = (x - xOffs);
534     int dy = (y - yOffs);
535     xOffs = x;
536     yOffs = y;
537     if ( autoUpdate() && isVisible() )
538         scroll( dx, dy );
539     if ( updateScrBars )
540         updateScrollBars( verValue | horValue );
541 }
542
543
544 /*!
545   \overload int QtTableView::cellWidth() const
546
547   Returns the column width in pixels.   Returns 0 if the columns have
548   variable widths.
549
550   \sa setCellWidth(), cellHeight()
551 */
552
553 /*!
554   Returns the width of column \a col in pixels.
555
556   This function is virtual and must be reimplemented by subclasses that
557   have variable cell widths. Note that if the total table width
558   changes, updateTableSize() must be called.
559
560   \sa setCellWidth(), cellHeight(), totalWidth(), updateTableSize()
561 */
562
563 int QtTableView::cellWidth( int )
564 {
565     return cellW;
566 }
567
568
569 /*!
570   Sets the width in pixels of the table cells to \a cellWidth.
571
572   Setting it to 0 means that the column width is variable.  When
573   set to 0 (this is the default) QtTableView calls the virtual function
574   cellWidth() to get the width.
575
576   \sa cellWidth(), setCellHeight(), totalWidth(), numCols()
577 */
578
579 void QtTableView::setCellWidth( int cellWidth )
580 {
581     if ( cellW == cellWidth )
582         return;
583 #if defined(QT_CHECK_RANGE)
584     if ( cellWidth < 0 || cellWidth > SHRT_MAX ) {
585         qWarning( "QtTableView::setCellWidth: (%s) Argument out of range (%d)",
586                  name( "unnamed" ), cellWidth );
587         return;
588     }
589 #endif
590     cellW = (short)cellWidth;
591
592     updateScrollBars( horSteps | horRange );
593     if ( autoUpdate() && isVisible() )
594         repaint();
595
596 }
597
598 /*!
599   \overload int QtTableView::cellHeight() const
600
601   Returns the row height, in pixels.  Returns 0 if the rows have
602   variable heights.
603
604   \sa setCellHeight(), cellWidth()
605 */
606
607
608 /*!
609   Returns the height of row \a row in pixels.
610
611   This function is virtual and must be reimplemented by subclasses that
612   have variable cell heights.  Note that if the total table height
613   changes, updateTableSize() must be called.
614
615   \sa setCellHeight(), cellWidth(), totalHeight()
616 */
617
618 int QtTableView::cellHeight( int )
619 {
620     return cellH;
621 }
622
623 /*!
624   Sets the height in pixels of the table cells to \a cellHeight.
625
626   Setting it to 0 means that the row height is variable.  When set
627   to 0 (this is the default), QtTableView calls the virtual function
628   cellHeight() to get the height.
629
630   \sa cellHeight(), setCellWidth(), totalHeight(), numRows()
631 */
632
633 void QtTableView::setCellHeight( int cellHeight )
634 {
635     if ( cellH == cellHeight )
636         return;
637 #if defined(QT_CHECK_RANGE)
638     if ( cellHeight < 0 || cellHeight > SHRT_MAX ) {
639         qWarning( "QtTableView::setCellHeight: (%s) Argument out of range (%d)",
640                  name( "unnamed" ), cellHeight );
641         return;
642     }
643 #endif
644     cellH = (short)cellHeight;
645     if ( autoUpdate() && isVisible() )
646         repaint();
647     updateScrollBars( verSteps | verRange );
648 }
649
650
651 /*!
652   Returns the total width of the table in pixels.
653
654   This function is virtual and should be reimplemented by subclasses that
655   have variable cell widths and a non-trivial cellWidth() function, or a
656   large number of columns in the table.
657
658   The default implementation may be slow for very wide tables.
659
660   \sa cellWidth(), totalHeight() */
661
662 int QtTableView::totalWidth()
663 {
664     if ( cellW ) {
665         return cellW*nCols;
666     } else {
667         int tw = 0;
668         for( int i = 0 ; i < nCols ; i++ )
669             tw += cellWidth( i );
670         return tw;
671     }
672 }
673
674 /*!
675   Returns the total height of the table in pixels.
676
677   This function is virtual and should be reimplemented by subclasses that
678   have variable cell heights and a non-trivial cellHeight() function, or a
679   large number of rows in the table.
680
681   The default implementation may be slow for very tall tables.
682
683   \sa cellHeight(), totalWidth()
684 */
685
686 int QtTableView::totalHeight()
687 {
688     if ( cellH ) {
689         return cellH*nRows;
690     } else {
691         int th = 0;
692         for( int i = 0 ; i < nRows ; i++ )
693             th += cellHeight( i );
694         return th;
695     }
696 }
697
698
699 /*!
700   \fn uint QtTableView::tableFlags() const
701
702   Returns the union of the table flags that are currently set.
703
704   \sa setTableFlags(), clearTableFlags(), testTableFlags()
705 */
706
707 /*!
708   \fn bool QtTableView::testTableFlags( uint f ) const
709
710   Returns TRUE if any of the table flags in \a f are currently set,
711   otherwise FALSE.
712
713   \sa setTableFlags(), clearTableFlags(), tableFlags()
714 */
715
716 /*!
717   Sets the table flags to \a f.
718
719   If a flag setting changes the appearance of the table, the table is
720   repainted if - and only if - autoUpdate() is TRUE.
721
722   The table flags are mostly single bits, though there are some multibit
723   flags for convenience. Here is a complete list:
724
725   <dl compact>
726   <dt> Tbl_vScrollBar <dd> - The table has a vertical scroll bar.
727   <dt> Tbl_hScrollBar <dd> - The table has a horizontal scroll bar.
728   <dt> Tbl_autoVScrollBar <dd> - The table has a vertical scroll bar if
729   - and only if - the table is taller than the view.
730   <dt> Tbl_autoHScrollBar <dd> The table has a horizontal scroll bar if
731   - and only if - the table is wider than the view.
732   <dt> Tbl_autoScrollBars <dd> - The union of the previous two flags.
733   <dt> Tbl_clipCellPainting <dd> - The table uses QPainter::setClipRect() to
734   make sure that paintCell() will not draw outside the cell
735   boundaries.
736   <dt> Tbl_cutCellsV <dd> - The table will never show part of a
737   cell at the bottom of the table; if there is not space for all of
738   a cell, the space is left blank.
739   <dt> Tbl_cutCellsH <dd> - The table will never show part of a
740   cell at the right side of the table; if there is not space for all of
741   a cell, the space is left blank.
742   <dt> Tbl_cutCells <dd> - The union of the previous two flags.
743   <dt> Tbl_scrollLastHCell <dd> - When the user scrolls horizontally,
744   let him/her scroll the last cell left until it is at the left
745   edge of the view.  If this flag is not set, the user can only scroll
746   to the point where the last cell is completely visible.
747   <dt> Tbl_scrollLastVCell <dd> - When the user scrolls vertically, let
748   him/her scroll the last cell up until it is at the top edge of
749   the view.  If this flag is not set, the user can only scroll to the
750   point where the last cell is completely visible.
751   <dt> Tbl_scrollLastCell <dd> - The union of the previous two flags.
752   <dt> Tbl_smoothHScrolling <dd> - The table scrolls as smoothly as
753   possible when the user scrolls horizontally. When this flag is not
754   set, scrolling is done one cell at a time.
755   <dt> Tbl_smoothVScrolling <dd> - The table scrolls as smoothly as
756   possible when scrolling vertically. When this flag is not set,
757   scrolling is done one cell at a time.
758   <dt> Tbl_smoothScrolling <dd> - The union of the previous two flags.
759   <dt> Tbl_snapToHGrid <dd> - Except when the user is actually scrolling,
760   the leftmost column shown snaps to the leftmost edge of the view.
761   <dt> Tbl_snapToVGrid <dd> - Except when the user is actually
762   scrolling, the top row snaps to the top edge of the view.
763   <dt> Tbl_snapToGrid <dd> - The union of the previous two flags.
764   </dl>
765
766   You can specify more than one flag at a time using bitwise OR.
767
768   Example:
769   \code
770     setTableFlags( Tbl_smoothScrolling | Tbl_autoScrollBars );
771   \endcode
772
773   \warning The cutCells options (\c Tbl_cutCells, \c Tbl_cutCellsH and
774   Tbl_cutCellsV) may cause painting problems when scrollbars are
775   enabled. Do not combine cutCells and scrollbars.
776
777
778   \sa clearTableFlags(), testTableFlags(), tableFlags()
779 */
780
781 void QtTableView::setTableFlags( uint f )
782 {
783     f = (f ^ tFlags) & f;                       // clear flags already set
784     tFlags |= f;
785
786     bool updateOn = autoUpdate();
787     setAutoUpdate( FALSE );
788
789     uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
790
791     if ( f & Tbl_vScrollBar ) {
792         setVerScrollBar( TRUE );
793     }
794     if ( f & Tbl_hScrollBar ) {
795         setHorScrollBar( TRUE );
796     }
797     if ( f & Tbl_autoVScrollBar ) {
798         updateScrollBars( verRange );
799     }
800     if ( f & Tbl_autoHScrollBar ) {
801         updateScrollBars( horRange );
802     }
803     if ( f & Tbl_scrollLastHCell ) {
804         updateScrollBars( horRange );
805     }
806     if ( f & Tbl_scrollLastVCell ) {
807         updateScrollBars( verRange );
808     }
809     if ( f & Tbl_snapToHGrid ) {
810         updateScrollBars( horRange );
811     }
812     if ( f & Tbl_snapToVGrid ) {
813         updateScrollBars( verRange );
814     }
815     if ( f & Tbl_snapToGrid ) {                 // Note: checks for 2 flags
816         if ( (f & Tbl_snapToHGrid) != 0 && xCellDelta != 0 || //have to scroll?
817              (f & Tbl_snapToVGrid) != 0 && yCellDelta != 0 ) {
818             snapToGrid( (f & Tbl_snapToHGrid) != 0,     // do snapping
819                         (f & Tbl_snapToVGrid) != 0 );
820             repaintMask |= Tbl_snapToGrid;      // repaint table
821         }
822     }
823
824     if ( updateOn ) {
825         setAutoUpdate( TRUE );
826         updateScrollBars();
827         if ( isVisible() && (f & repaintMask) )
828             repaint();
829     }
830
831 }
832
833 /*!
834   Clears the \link setTableFlags() table flags\endlink that are set
835   in \a f.
836
837   Example (clears a single flag):
838   \code
839     clearTableFlags( Tbl_snapToGrid );
840   \endcode
841
842   The default argument clears all flags.
843
844   \sa setTableFlags(), testTableFlags(), tableFlags()
845 */
846
847 void QtTableView::clearTableFlags( uint f )
848 {
849     f = (f ^ ~tFlags) & f;              // clear flags that are already 0
850     tFlags &= ~f;
851
852     bool updateOn = autoUpdate();
853     setAutoUpdate( FALSE );
854
855     uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
856
857     if ( f & Tbl_vScrollBar ) {
858         setVerScrollBar( FALSE );
859     }
860     if ( f & Tbl_hScrollBar ) {
861         setHorScrollBar( FALSE );
862     }
863     if ( f & Tbl_scrollLastHCell ) {
864         int maxX = maxXOffset();
865         if ( xOffs > maxX ) {
866             setOffset( maxX, yOffs );
867             repaintMask |= Tbl_scrollLastHCell;
868         }
869         updateScrollBars( horRange );
870     }
871     if ( f & Tbl_scrollLastVCell ) {
872         int maxY = maxYOffset();
873         if ( yOffs > maxY ) {
874             setOffset( xOffs, maxY );
875             repaintMask |= Tbl_scrollLastVCell;
876         }
877         updateScrollBars( verRange );
878     }
879     if ( f & Tbl_smoothScrolling ) {          // Note: checks for 2 flags
880         if ((f & Tbl_smoothHScrolling) != 0 && xCellDelta != 0 ||//must scroll?
881             (f & Tbl_smoothVScrolling) != 0 && yCellDelta != 0 ) {
882             snapToGrid( (f & Tbl_smoothHScrolling) != 0,      // do snapping
883                         (f & Tbl_smoothVScrolling) != 0 );
884             repaintMask |= Tbl_smoothScrolling;              // repaint table
885         }
886     }
887     if ( f & Tbl_snapToHGrid ) {
888         updateScrollBars( horRange );
889     }
890     if ( f & Tbl_snapToVGrid ) {
891         updateScrollBars( verRange );
892     }
893     if ( updateOn ) {
894         setAutoUpdate( TRUE );
895         updateScrollBars();          // returns immediately if nothing to do
896         if ( isVisible() && (f & repaintMask) )
897             repaint();
898     }
899
900 }
901
902
903 /*!
904   \fn bool QtTableView::autoUpdate() const
905
906   Returns TRUE if the view updates itself automatically whenever it
907   is changed in some way.
908
909   \sa setAutoUpdate()
910 */
911
912 /*!
913   Sets the auto-update option of the table view to \a enable.
914
915   If \a enable is TRUE (this is the default), the view updates itself
916   automatically whenever it has changed in some way (for example, when a
917   \link setTableFlags() flag\endlink is changed).
918
919   If \a enable is FALSE, the view does NOT repaint itself or update
920   its internal state variables when it is changed.  This can be
921   useful to avoid flicker during large changes and is singularly
922   useless otherwise. Disable auto-update, do the changes, re-enable
923   auto-update and call repaint().
924
925   \warning Do not leave the view in this state for a long time
926   (i.e., between events). If, for example, the user interacts with the
927   view when auto-update is off, strange things can happen.
928
929   Setting auto-update to TRUE does not repaint the view; you must call
930   repaint() to do this.
931
932   \sa autoUpdate(), repaint()
933 */
934
935 void QtTableView::setAutoUpdate( bool enable )
936 {
937     if ( isUpdatesEnabled() == enable )
938         return;
939     setUpdatesEnabled( enable );
940     if ( enable ) {
941         showOrHideScrollBars();
942         updateScrollBars();
943     }
944 }
945
946
947 /*!
948   Repaints the cell at row \a row, column \a col if it is inside the view.
949
950   If \a erase is TRUE, the relevant part of the view is cleared to the
951   background color/pixmap before the contents are repainted.
952
953   \sa isVisible()
954 */
955
956 void QtTableView::updateCell( int row, int col, bool erase )
957 {
958     int xPos, yPos;
959     if ( !colXPos( col, &xPos ) )
960         return;
961     if ( !rowYPos( row, &yPos ) )
962         return;
963     QRect uR = QRect( xPos, yPos,
964                       cellW ? cellW : cellWidth(col),
965                       cellH ? cellH : cellHeight(row) );
966     repaint( uR.intersect(viewRect()), erase );
967 }
968
969
970 /*!
971   \fn QRect QtTableView::cellUpdateRect() const
972
973   This function should be called only from the paintCell() function in
974   subclasses. It returns the portion of a cell that actually needs to be
975   updated in \e cell coordinates. This is useful only for non-trivial
976   paintCell().
977
978 */
979
980 /*!
981   Returns the rectangle that is the actual table, excluding any
982   frame, in \e widget coordinates.
983 */
984
985 QRect QtTableView::viewRect() const
986 {
987     return QRect( frameWidth(), frameWidth(), viewWidth(), viewHeight() );
988 }
989
990
991 /*!
992   Returns the index of the last (bottom) row in the view.
993   The index of the first row is 0.
994
995   If no rows are visible it returns -1.  This can happen if the
996   view is too small for the first row and Tbl_cutCellsV is set.
997
998   \sa lastColVisible()
999 */
1000
1001 int QtTableView::lastRowVisible() const
1002 {
1003     int cellMaxY;
1004     int row = findRawRow( maxViewY(), &cellMaxY );
1005     if ( row == -1 || row >= nRows ) {          // maxViewY() past end?
1006         row = nRows - 1;                        // yes: return last row
1007     } else {
1008         if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() ) {
1009             if ( row == yCellOffs )             // cut by right margin?
1010                 return -1;                      // yes, nothing in the view
1011             else
1012                row = row - 1;                   // cut by margin, one back
1013         }
1014     }
1015     return row;
1016 }
1017
1018 /*!
1019   Returns the index of the last (right) column in the view.
1020   The index of the first column is 0.
1021
1022   If no columns are visible it returns -1.  This can happen if the
1023   view is too narrow for the first column and Tbl_cutCellsH is set.
1024
1025   \sa lastRowVisible()
1026 */
1027
1028 int QtTableView::lastColVisible() const
1029 {
1030     int cellMaxX;
1031     int col = findRawCol( maxViewX(), &cellMaxX );
1032     if ( col == -1 || col >= nCols ) {          // maxViewX() past end?
1033         col = nCols - 1;                        // yes: return last col
1034     } else {
1035         if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() ) {
1036             if ( col == xCellOffs )             // cut by bottom margin?
1037                 return -1;                      // yes, nothing in the view
1038             else
1039                col = col - 1;                   // cell by margin, one back
1040         }
1041     }
1042     return col;
1043 }
1044
1045 /*!
1046   Returns TRUE if \a row is at least partially visible.
1047   \sa colIsVisible()
1048 */
1049
1050 bool QtTableView::rowIsVisible( int row ) const
1051 {
1052     return rowYPos( row, 0 );
1053 }
1054
1055 /*!
1056   Returns TRUE if \a col is at least partially visible.
1057   \sa rowIsVisible()
1058 */
1059
1060 bool QtTableView::colIsVisible( int col ) const
1061 {
1062     return colXPos( col, 0 );
1063 }
1064
1065
1066 /*!
1067   \internal
1068   Called when both scroll bars are active at the same time. Covers the
1069   bottom left corner between the two scroll bars with an empty widget.
1070 */
1071
1072 void QtTableView::coverCornerSquare( bool enable )
1073 {
1074     coveringCornerSquare = enable;
1075     if ( !cornerSquare && enable ) {
1076         cornerSquare = new QCornerSquare( this );
1077         Q_CHECK_PTR( cornerSquare );
1078         cornerSquare->setGeometry( maxViewX() + frameWidth() + 1,
1079                                    maxViewY() + frameWidth() + 1,
1080                                    VSBEXT,
1081                                  HSBEXT);
1082     }
1083     if ( autoUpdate() && cornerSquare ) {
1084         if ( enable )
1085             cornerSquare->show();
1086         else
1087             cornerSquare->hide();
1088     }
1089 }
1090
1091
1092 /*!
1093   \internal
1094   Scroll the view to a position such that:
1095
1096   If \a horizontal is TRUE, the leftmost column shown fits snugly
1097   with the left edge of the view.
1098
1099   If \a vertical is TRUE, the top row shown fits snugly with the top
1100   of the view.
1101
1102   You can achieve the same effect automatically by setting any of the
1103   \link setTableFlags() Tbl_snapTo*Grid \endlink table flags.
1104 */
1105
1106 void QtTableView::snapToGrid( bool horizontal, bool vertical )
1107 {
1108     int newXCell = -1;
1109     int newYCell = -1;
1110     if ( horizontal && xCellDelta != 0 ) {
1111         int w = cellW ? cellW : cellWidth( xCellOffs );
1112         if ( xCellDelta >= w/2 )
1113             newXCell = xCellOffs + 1;
1114         else
1115             newXCell = xCellOffs;
1116     }
1117     if ( vertical && yCellDelta != 0 ) {
1118         int h = cellH ? cellH : cellHeight( yCellOffs );
1119         if ( yCellDelta >= h/2 )
1120             newYCell = yCellOffs + 1;
1121         else
1122             newYCell = yCellOffs;
1123     }
1124     setTopLeftCell( newYCell, newXCell );  //row,column
1125 }
1126
1127 /*!
1128   \internal
1129   This internal slot is connected to the horizontal scroll bar's
1130   QScrollBar::valueChanged() signal.
1131
1132   Moves the table horizontally to offset \a val without updating the
1133   scroll bar.
1134 */
1135
1136 void QtTableView::horSbValue( int val )
1137 {
1138     if ( horSliding ) {
1139         horSliding = FALSE;
1140         if ( horSnappingOff ) {
1141             horSnappingOff = FALSE;
1142             tFlags |= Tbl_snapToHGrid;
1143         }
1144     }
1145     setOffset( val, yOffs, FALSE );
1146 }
1147
1148 /*!
1149   \internal
1150   This internal slot is connected to the horizontal scroll bar's
1151   QScrollBar::sliderMoved() signal.
1152
1153   Scrolls the table smoothly horizontally even if \c Tbl_snapToHGrid is set.
1154 */
1155
1156 void QtTableView::horSbSliding( int val )
1157 {
1158     if ( testTableFlags(Tbl_snapToHGrid) &&
1159          testTableFlags(Tbl_smoothHScrolling) ) {
1160         tFlags &= ~Tbl_snapToHGrid;     // turn off snapping while sliding
1161         setOffset( val, yOffs, FALSE );
1162         tFlags |= Tbl_snapToHGrid;      // turn on snapping again
1163     } else {
1164         setOffset( val, yOffs, FALSE );
1165     }
1166 }
1167
1168 /*!
1169   \internal
1170   This internal slot is connected to the horizontal scroll bar's
1171   QScrollBar::sliderReleased() signal.
1172 */
1173
1174 void QtTableView::horSbSlidingDone( )
1175 {
1176     if ( testTableFlags(Tbl_snapToHGrid) &&
1177          testTableFlags(Tbl_smoothHScrolling) )
1178         snapToGrid( TRUE, FALSE );
1179 }
1180
1181 /*!
1182   \internal
1183   This internal slot is connected to the vertical scroll bar's
1184   QScrollBar::valueChanged() signal.
1185
1186   Moves the table vertically to offset \a val without updating the
1187   scroll bar.
1188 */
1189
1190 void QtTableView::verSbValue( int val )
1191 {
1192     if ( verSliding ) {
1193         verSliding = FALSE;
1194         if ( verSnappingOff ) {
1195             verSnappingOff = FALSE;
1196             tFlags |= Tbl_snapToVGrid;
1197         }
1198     }
1199     setOffset( xOffs, val, FALSE );
1200 }
1201
1202 /*!
1203   \internal
1204   This internal slot is connected to the vertical scroll bar's
1205   QScrollBar::sliderMoved() signal.
1206
1207   Scrolls the table smoothly vertically even if \c Tbl_snapToVGrid is set.
1208 */
1209
1210 void QtTableView::verSbSliding( int val )
1211 {
1212     if ( testTableFlags(Tbl_snapToVGrid) &&
1213          testTableFlags(Tbl_smoothVScrolling) ) {
1214         tFlags &= ~Tbl_snapToVGrid;     // turn off snapping while sliding
1215         setOffset( xOffs, val, FALSE );
1216         tFlags |= Tbl_snapToVGrid;      // turn on snapping again
1217     } else {
1218         setOffset( xOffs, val, FALSE );
1219     }
1220 }
1221
1222 /*!
1223   \internal
1224   This internal slot is connected to the vertical scroll bar's
1225   QScrollBar::sliderReleased() signal.
1226 */
1227
1228 void QtTableView::verSbSlidingDone( )
1229 {
1230     if ( testTableFlags(Tbl_snapToVGrid) &&
1231          testTableFlags(Tbl_smoothVScrolling) )
1232         snapToGrid( FALSE, TRUE );
1233 }
1234
1235
1236 /*!
1237   This virtual function is called before painting of table cells
1238   is started. It can be reimplemented by subclasses that want to
1239   to set up the painter in a special way and that do not want to
1240   do so for each cell.
1241 */
1242
1243 void QtTableView::setupPainter( QPainter * )
1244 {
1245 }
1246
1247 /*!
1248   \fn void QtTableView::paintCell( QPainter *p, int row, int col )
1249
1250   This pure virtual function is called to paint the single cell at \a
1251   (row,col) using \a p, which is open when paintCell() is called and
1252   must remain open.
1253
1254   The coordinate system is \link QPainter::translate() translated \endlink
1255   so that the origin is at the top-left corner of the cell to be
1256   painted, i.e. \e cell coordinates.  Do not scale or shear the coordinate
1257   system (or if you do, restore the transformation matrix before you
1258   return).
1259
1260   The painter is not clipped by default and for maximum efficiency. For safety,
1261   call setTableFlags(Tbl_clipCellPainting) to enable clipping.
1262
1263   \sa paintEvent(), setTableFlags() */
1264
1265
1266 /*!
1267   Handles paint events, \a e, for the table view.
1268
1269   Calls paintCell() for the cells that needs to be repainted.
1270 */
1271
1272 void QtTableView::paintEvent( QPaintEvent *e )
1273 {
1274     QRect updateR = e->rect();                  // update rectangle
1275     if ( sbDirty ) {
1276         bool e = eraseInPaint;
1277         updateScrollBars();
1278         eraseInPaint = e;
1279     }
1280
1281     QPainter paint( this );
1282
1283     if ( !contentsRect().contains( updateR, TRUE  ) ) {// update frame ?
1284         drawFrame( &paint );
1285         if ( updateR.left() < frameWidth() )            //###
1286             updateR.setLeft( frameWidth() );
1287         if ( updateR.top() < frameWidth() )
1288             updateR.setTop( frameWidth() );
1289     }
1290
1291     int maxWX = maxViewX();
1292     int maxWY = maxViewY();
1293     if ( updateR.right() > maxWX )
1294         updateR.setRight( maxWX );
1295     if ( updateR.bottom() > maxWY )
1296         updateR.setBottom( maxWY );
1297
1298     setupPainter( &paint );                     // prepare for painting table
1299
1300     int firstRow = findRow( updateR.y() );
1301     int firstCol = findCol( updateR.x() );
1302     int  xStart, yStart;
1303     if ( !colXPos( firstCol, &xStart ) || !rowYPos( firstRow, &yStart ) ) {
1304         paint.eraseRect( updateR ); // erase area outside cells but in view
1305         return;
1306     }
1307     int   maxX  = updateR.right();
1308     int   maxY  = updateR.bottom();
1309     int   row   = firstRow;
1310     int   col;
1311     int   yPos  = yStart;
1312     int   xPos = maxX+1; // in case the while() is empty
1313     int   nextX;
1314     int   nextY;
1315     QRect winR = viewRect();
1316     QRect cellR;
1317     QRect cellUR;
1318 #ifndef QT_NO_TRANSFORMATIONS
1319     QWMatrix matrix;
1320 #endif
1321
1322     while ( yPos <= maxY && row < nRows ) {
1323         nextY = yPos + (cellH ? cellH : cellHeight( row ));
1324         if ( testTableFlags( Tbl_cutCellsV ) && nextY > ( maxWY + 1 ) )
1325             break;
1326         col  = firstCol;
1327         xPos = xStart;
1328         while ( xPos <= maxX && col < nCols ) {
1329             nextX = xPos + (cellW ? cellW : cellWidth( col ));
1330             if ( testTableFlags( Tbl_cutCellsH ) && nextX > ( maxWX + 1 ) )
1331                 break;
1332
1333             cellR.setRect( xPos, yPos, cellW ? cellW : cellWidth(col),
1334                                        cellH ? cellH : cellHeight(row) );
1335             cellUR = cellR.intersect( updateR );
1336             if ( cellUR.isValid() ) {
1337                 cellUpdateR = cellUR;
1338                 cellUpdateR.moveBy( -xPos, -yPos ); // cell coordinates
1339                 if ( eraseInPaint )
1340                     paint.eraseRect( cellUR );
1341
1342 #ifndef QT_NO_TRANSFORMATIONS
1343                 matrix.translate( xPos, yPos );
1344                 paint.setWorldMatrix( matrix );
1345                 if ( testTableFlags(Tbl_clipCellPainting) ||
1346                      frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1347                     paint.setClipRect( cellUR );
1348                     paintCell( &paint, row, col );
1349                     paint.setClipping( FALSE );
1350                 } else {
1351                     paintCell( &paint, row, col );
1352                 }
1353                 matrix.reset();
1354                 paint.setWorldMatrix( matrix );
1355 #else
1356                 paint.translate( xPos, yPos );
1357                 if ( testTableFlags(Tbl_clipCellPainting) ||
1358                      frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
1359                     paint.setClipRect( cellUR );
1360                     paintCell( &paint, row, col );
1361                     paint.setClipping( FALSE );
1362                 } else {
1363                     paintCell( &paint, row, col );
1364                 }
1365                 paint.translate( -xPos, -yPos );
1366 #endif
1367             }
1368             col++;
1369             xPos = nextX;
1370         }
1371         row++;
1372         yPos = nextY;
1373     }
1374
1375     // while painting we have to erase any areas in the view that
1376     // are not covered by cells but are covered by the paint event
1377     // rectangle these must be erased. We know that xPos is the last
1378     // x pixel updated + 1 and that yPos is the last y pixel updated + 1.
1379
1380     // Note that this needs to be done regardless whether we do
1381     // eraseInPaint or not. Reason: a subclass may implement
1382     // flicker-freeness and encourage the use of repaint(FALSE).
1383     // The subclass, however, cannot draw all pixels, just those
1384     // inside the cells. So QtTableView is reponsible for all pixels
1385     // outside the cells.
1386
1387     QRect viewR = viewRect();
1388     const QColorGroup g = colorGroup();
1389
1390     if ( xPos <= maxX ) {
1391         QRect r = viewR;
1392         r.setLeft( xPos );
1393         r.setBottom( yPos<maxY?yPos:maxY );
1394         if ( inherits( "QMultiLineEdit" ) )
1395             paint.fillRect( r.intersect( updateR ), g.base() );
1396         else
1397             paint.eraseRect( r.intersect( updateR ) );
1398     }
1399     if ( yPos <= maxY ) {
1400         QRect r = viewR;
1401         r.setTop( yPos );
1402         if ( inherits( "QMultiLineEdit" ) )
1403             paint.fillRect( r.intersect( updateR ), g.base() );
1404         else
1405             paint.eraseRect( r.intersect( updateR ) );
1406     }
1407 }
1408
1409 /*!\reimp
1410 */
1411 void QtTableView::resizeEvent( QResizeEvent * )
1412 {
1413     updateScrollBars( horValue | verValue | horSteps | horGeometry | horRange |
1414                       verSteps | verGeometry | verRange );
1415     showOrHideScrollBars();
1416     updateFrameSize();
1417     int maxX = QMIN( xOffs, maxXOffset() );                     // ### can be slow
1418     int maxY = QMIN( yOffs, maxYOffset() );
1419     setOffset( maxX, maxY );
1420 }
1421
1422
1423 /*!
1424   Redraws all visible cells in the table view.
1425 */
1426
1427 void QtTableView::updateView()
1428 {
1429     repaint( viewRect() );
1430 }
1431
1432 /*!
1433   Returns a pointer to the vertical scroll bar mainly so you can
1434   connect() to its signals.  Note that the scroll bar works in pixel
1435   values; use findRow() to translate to cell numbers.
1436 */
1437
1438 QScrollBar *QtTableView::verticalScrollBar() const
1439 {
1440     QtTableView *that = (QtTableView*)this; // semantic const
1441     if ( !vScrollBar ) {
1442         QScrollBar *sb = new QScrollBar( QScrollBar::Vertical, that );
1443 #ifndef QT_NO_CURSOR
1444         sb->setCursor( arrowCursor );
1445 #endif
1446         sb->resize( sb->sizeHint() ); // height is irrelevant
1447         Q_CHECK_PTR(sb);
1448         sb->setTracking( FALSE );
1449         sb->setFocusPolicy( NoFocus );
1450         connect( sb, SIGNAL(valueChanged(int)),
1451                  SLOT(verSbValue(int)));
1452         connect( sb, SIGNAL(sliderMoved(int)),
1453                  SLOT(verSbSliding(int)));
1454         connect( sb, SIGNAL(sliderReleased()),
1455                  SLOT(verSbSlidingDone()));
1456         sb->hide();
1457         that->vScrollBar = sb;
1458         return sb;
1459     }
1460     return vScrollBar;
1461 }
1462
1463 /*!
1464   Returns a pointer to the horizontal scroll bar mainly so you can
1465   connect() to its signals. Note that the scroll bar works in pixel
1466   values; use findCol() to translate to cell numbers.
1467 */
1468
1469 QScrollBar *QtTableView::horizontalScrollBar() const
1470 {
1471     QtTableView *that = (QtTableView*)this; // semantic const
1472     if ( !hScrollBar ) {
1473         QScrollBar *sb = new QScrollBar( QScrollBar::Horizontal, that );
1474 #ifndef QT_NO_CURSOR
1475         sb->setCursor( arrowCursor );
1476 #endif
1477         sb->resize( sb->sizeHint() ); // width is irrelevant
1478         sb->setFocusPolicy( NoFocus );
1479         Q_CHECK_PTR(sb);
1480         sb->setTracking( FALSE );
1481         connect( sb, SIGNAL(valueChanged(int)),
1482                  SLOT(horSbValue(int)));
1483         connect( sb, SIGNAL(sliderMoved(int)),
1484                  SLOT(horSbSliding(int)));
1485         connect( sb, SIGNAL(sliderReleased()),
1486                  SLOT(horSbSlidingDone()));
1487         sb->hide();
1488         that->hScrollBar = sb;
1489         return sb;
1490     }
1491     return hScrollBar;
1492 }
1493
1494 /*!
1495   Enables or disables the horizontal scroll bar, as required by
1496   setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1497 */
1498
1499 void QtTableView::setHorScrollBar( bool on, bool update )
1500 {
1501     if ( on ) {
1502         tFlags |= Tbl_hScrollBar;
1503         horizontalScrollBar(); // created
1504         if ( update )
1505             updateScrollBars( horMask | verMask );
1506         else
1507             sbDirty = sbDirty | (horMask | verMask);
1508         if ( testTableFlags( Tbl_vScrollBar ) )
1509             coverCornerSquare( TRUE );
1510         if ( autoUpdate() )
1511             sbDirty = sbDirty | horMask;
1512     } else {
1513         tFlags &= ~Tbl_hScrollBar;
1514         if ( !hScrollBar )
1515             return;
1516         coverCornerSquare( FALSE );
1517         bool hideScrollBar = autoUpdate() && hScrollBar->isVisible();
1518         if ( hideScrollBar )
1519             hScrollBar->hide();
1520         if ( update )
1521             updateScrollBars( verMask );
1522         else
1523             sbDirty = sbDirty | verMask;
1524         if ( hideScrollBar && isVisible() )
1525             repaint( hScrollBar->x(), hScrollBar->y(),
1526                      width() - hScrollBar->x(), hScrollBar->height() );
1527     }
1528     if ( update )
1529         updateFrameSize();
1530 }
1531
1532
1533 /*!
1534   Enables or disables the vertical scroll bar, as required by
1535   setAutoUpdate() and the \link setTableFlags() table flags\endlink.
1536 */
1537
1538 void QtTableView::setVerScrollBar( bool on, bool update )
1539 {
1540     if ( on ) {
1541         tFlags |= Tbl_vScrollBar;
1542         verticalScrollBar(); // created
1543         if ( update )
1544             updateScrollBars( verMask | horMask );
1545         else
1546             sbDirty = sbDirty | (horMask | verMask);
1547         if ( testTableFlags( Tbl_hScrollBar ) )
1548             coverCornerSquare( TRUE );
1549         if ( autoUpdate() )
1550             sbDirty = sbDirty | verMask;
1551     } else {
1552         tFlags &= ~Tbl_vScrollBar;
1553         if ( !vScrollBar )
1554             return;
1555         coverCornerSquare( FALSE );
1556         bool hideScrollBar = autoUpdate() && vScrollBar->isVisible();
1557         if ( hideScrollBar )
1558             vScrollBar->hide();
1559         if ( update )
1560             updateScrollBars( horMask );
1561         else
1562             sbDirty = sbDirty | horMask;
1563         if ( hideScrollBar && isVisible() )
1564             repaint( vScrollBar->x(), vScrollBar->y(),
1565                      vScrollBar->width(), height() - vScrollBar->y() );
1566     }
1567     if ( update )
1568         updateFrameSize();
1569 }
1570
1571
1572
1573
1574 int QtTableView::findRawRow( int yPos, int *cellMaxY, int *cellMinY,
1575                             bool goOutsideView ) const
1576 {
1577     int r = -1;
1578     if ( nRows == 0 )
1579         return r;
1580     if ( goOutsideView || yPos >= minViewY() && yPos <= maxViewY() ) {
1581         if ( yPos < minViewY() ) {
1582 #if defined(QT_CHECK_RANGE)
1583             qWarning( "QtTableView::findRawRow: (%s) internal error: "
1584                      "yPos < minViewY() && goOutsideView "
1585                      "not supported. (%d,%d)",
1586                      name( "unnamed" ), yPos, yOffs );
1587 #endif
1588             return -1;
1589         }
1590         if ( cellH ) {                               // uniform cell height
1591             r = (yPos - minViewY() + yCellDelta)/cellH; // cell offs from top
1592             if ( cellMaxY )
1593                 *cellMaxY = (r + 1)*cellH + minViewY() - yCellDelta - 1;
1594             if ( cellMinY )
1595                 *cellMinY = r*cellH + minViewY() - yCellDelta;
1596             r += yCellOffs;                          // absolute cell index
1597         } else {                                     // variable cell height
1598             QtTableView *tw = (QtTableView *)this;
1599             r        = yCellOffs;
1600             int h    = minViewY() - yCellDelta; //##arnt3
1601             int oldH = h;
1602             Q_ASSERT( r < nRows );
1603             while ( r < nRows ) {
1604                 oldH = h;
1605                 h += tw->cellHeight( r );            // Start of next cell
1606                 if ( yPos < h )
1607                     break;
1608                 r++;
1609             }
1610             if ( cellMaxY )
1611                 *cellMaxY = h - 1;
1612             if ( cellMinY )
1613                 *cellMinY = oldH;
1614         }
1615     }
1616     return r;
1617
1618 }
1619
1620
1621 int QtTableView::findRawCol( int xPos, int *cellMaxX, int *cellMinX ,
1622                             bool goOutsideView ) const
1623 {
1624     int c = -1;
1625     if ( nCols == 0 )
1626         return c;
1627     if ( goOutsideView || xPos >= minViewX() && xPos <= maxViewX() ) {
1628         if ( xPos < minViewX() ) {
1629 #if defined(QT_CHECK_RANGE)
1630             qWarning( "QtTableView::findRawCol: (%s) internal error: "
1631                      "xPos < minViewX() && goOutsideView "
1632                      "not supported. (%d,%d)",
1633                      name( "unnamed" ), xPos, xOffs );
1634 #endif
1635             return -1;
1636         }
1637         if ( cellW ) {                          // uniform cell width
1638             c = (xPos - minViewX() + xCellDelta)/cellW; //cell offs from left
1639             if ( cellMaxX )
1640                 *cellMaxX = (c + 1)*cellW + minViewX() - xCellDelta - 1;
1641             if ( cellMinX )
1642                 *cellMinX = c*cellW + minViewX() - xCellDelta;
1643             c += xCellOffs;                     // absolute cell index
1644         } else {                                // variable cell width
1645             QtTableView *tw = (QtTableView *)this;
1646             c        = xCellOffs;
1647             int w    = minViewX() - xCellDelta; //##arnt3
1648             int oldW = w;
1649             Q_ASSERT( c < nCols );
1650             while ( c < nCols ) {
1651                 oldW = w;
1652                 w += tw->cellWidth( c );        // Start of next cell
1653                 if ( xPos < w )
1654                     break;
1655                 c++;
1656             }
1657             if ( cellMaxX )
1658                 *cellMaxX = w - 1;
1659             if ( cellMinX )
1660                 *cellMinX = oldW;
1661         }
1662     }
1663     return c;
1664 }
1665
1666
1667 /*!
1668   Returns the index of the row at position \a yPos, where \a yPos is in
1669   \e widget coordinates.  Returns -1 if \a yPos is outside the valid
1670   range.
1671
1672   \sa findCol(), rowYPos()
1673 */
1674
1675 int QtTableView::findRow( int yPos ) const
1676 {
1677     int cellMaxY;
1678     int row = findRawRow( yPos, &cellMaxY );
1679     if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() )
1680         row = - 1;                              //  cell cut by bottom margin
1681     if ( row >= nRows )
1682         row = -1;
1683     return row;
1684 }
1685
1686
1687 /*!
1688   Returns the index of the column at position \a xPos, where \a xPos is
1689   in \e widget coordinates.  Returns -1 if \a xPos is outside the valid
1690   range.
1691
1692   \sa findRow(), colXPos()
1693 */
1694
1695 int QtTableView::findCol( int xPos ) const
1696 {
1697     int cellMaxX;
1698     int col = findRawCol( xPos, &cellMaxX );
1699     if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() )
1700         col = - 1;                              //  cell cut by right margin
1701     if ( col >= nCols )
1702         col = -1;
1703     return col;
1704 }
1705
1706
1707 /*!
1708   Computes the position in the widget of row \a row.
1709
1710   Returns TRUE and stores the result in \a *yPos (in \e widget
1711   coordinates) if the row is visible.  Returns FALSE and does not modify
1712   \a *yPos if \a row is invisible or invalid.
1713
1714   \sa colXPos(), findRow()
1715 */
1716
1717 bool QtTableView::rowYPos( int row, int *yPos ) const
1718 {
1719     int y;
1720     if ( row >= yCellOffs ) {
1721         if ( cellH ) {
1722             int lastVisible = lastRowVisible();
1723             if ( row > lastVisible || lastVisible == -1 )
1724                 return FALSE;
1725             y = (row - yCellOffs)*cellH + minViewY() - yCellDelta;
1726         } else {
1727             //##arnt3
1728             y = minViewY() - yCellDelta;        // y of leftmost cell in view
1729             int r = yCellOffs;
1730             QtTableView *tw = (QtTableView *)this;
1731             int maxY = maxViewY();
1732             while ( r < row && y <= maxY )
1733                 y += tw->cellHeight( r++ );
1734             if ( y > maxY )
1735                 return FALSE;
1736
1737         }
1738     } else {
1739         return FALSE;
1740     }
1741     if ( yPos )
1742         *yPos = y;
1743     return TRUE;
1744 }
1745
1746
1747 /*!
1748   Computes the position in the widget of column \a col.
1749
1750   Returns TRUE and stores the result in \a *xPos (in \e widget
1751   coordinates) if the column is visible.  Returns FALSE and does not
1752   modify \a *xPos if \a col is invisible or invalid.
1753
1754   \sa rowYPos(), findCol()
1755 */
1756
1757 bool QtTableView::colXPos( int col, int *xPos ) const
1758 {
1759     int x;
1760     if ( col >= xCellOffs ) {
1761         if ( cellW ) {
1762             int lastVisible = lastColVisible();
1763             if ( col > lastVisible || lastVisible == -1 )
1764                 return FALSE;
1765             x = (col - xCellOffs)*cellW + minViewX() - xCellDelta;
1766         } else {
1767             //##arnt3
1768             x = minViewX() - xCellDelta;        // x of uppermost cell in view
1769             int c = xCellOffs;
1770             QtTableView *tw = (QtTableView *)this;
1771             int maxX = maxViewX();
1772             while ( c < col && x <= maxX )
1773                 x += tw->cellWidth( c++ );
1774             if ( x > maxX )
1775                 return FALSE;
1776         }
1777     } else {
1778         return FALSE;
1779     }
1780     if ( xPos )
1781         *xPos = x;
1782     return TRUE;
1783 }
1784
1785
1786 /*!
1787   Moves the visible area of the table right by \a xPixels and
1788   down by \a yPixels pixels.  Both may be negative.
1789
1790   \warning You might find that QScrollView offers a higher-level of
1791         functionality than using QtTableView and this function.
1792
1793   This function is \e not the same as QWidget::scroll(); in particular,
1794   the signs of \a xPixels and \a yPixels have the reverse semantics.
1795
1796   \sa setXOffset(), setYOffset(), setOffset(), setTopCell(),
1797   setLeftCell()
1798 */
1799
1800 void QtTableView::scroll( int xPixels, int yPixels )
1801 {
1802     QWidget::scroll( -xPixels, -yPixels, contentsRect() );
1803 }
1804
1805
1806 /*!
1807   Returns the leftmost pixel of the table view in \e view
1808   coordinates.  This excludes the frame and any header.
1809
1810   \sa maxViewY(), viewWidth(), contentsRect()
1811 */
1812
1813 int QtTableView::minViewX() const
1814 {
1815     return frameWidth();
1816 }
1817
1818
1819 /*!
1820   Returns the top pixel of the table view in \e view
1821   coordinates.  This excludes the frame and any header.
1822
1823   \sa maxViewX(), viewHeight(), contentsRect()
1824 */
1825
1826 int QtTableView::minViewY() const
1827 {
1828     return frameWidth();
1829 }
1830
1831
1832 /*!
1833   Returns the rightmost pixel of the table view in \e view
1834   coordinates.  This excludes the frame and any scroll bar, but
1835   includes blank pixels to the right of the visible table data.
1836
1837   \sa maxViewY(), viewWidth(), contentsRect()
1838 */
1839
1840 int QtTableView::maxViewX() const
1841 {
1842     return width() - 1 - frameWidth()
1843         - (tFlags & Tbl_vScrollBar ? VSBEXT
1844            : 0);
1845 }
1846
1847
1848 /*!
1849   Returns the bottom pixel of the table view in \e view
1850   coordinates.  This excludes the frame and any scroll bar, but
1851   includes blank pixels below the visible table data.
1852
1853   \sa maxViewX(), viewHeight(), contentsRect()
1854 */
1855
1856 int QtTableView::maxViewY() const
1857 {
1858     return height() - 1 - frameWidth()
1859         - (tFlags & Tbl_hScrollBar ? HSBEXT
1860            : 0);
1861 }
1862
1863
1864 /*!
1865   Returns the width of the table view, as such, in \e view
1866   coordinates.  This does not include any header, scroll bar or frame,
1867   but it does include background pixels to the right of the table data.
1868
1869   \sa minViewX() maxViewX(), viewHeight(), contentsRect() viewRect()
1870 */
1871
1872 int QtTableView::viewWidth() const
1873 {
1874     return maxViewX() - minViewX() + 1;
1875 }
1876
1877
1878 /*!
1879   Returns the height of the table view, as such, in \e view
1880   coordinates.  This does not include any header, scroll bar or frame,
1881   but it does include background pixels below the table data.
1882
1883   \sa minViewY() maxViewY() viewWidth() contentsRect() viewRect()
1884 */
1885
1886 int QtTableView::viewHeight() const
1887 {
1888     return maxViewY() - minViewY() + 1;
1889 }
1890
1891
1892 void QtTableView::doAutoScrollBars()
1893 {
1894     int viewW = width()  - frameWidth() - minViewX();
1895     int viewH = height() - frameWidth() - minViewY();
1896     bool vScrollOn = testTableFlags(Tbl_vScrollBar);
1897     bool hScrollOn = testTableFlags(Tbl_hScrollBar);
1898     int w = 0;
1899     int h = 0;
1900     int i;
1901
1902     if ( testTableFlags(Tbl_autoHScrollBar) ) {
1903         if ( cellW ) {
1904             w = cellW*nCols;
1905         } else {
1906             i = 0;
1907             while ( i < nCols && w <= viewW )
1908                 w += cellWidth( i++ );
1909         }
1910         if ( w > viewW )
1911             hScrollOn = TRUE;
1912         else
1913             hScrollOn = FALSE;
1914     }
1915
1916     if ( testTableFlags(Tbl_autoVScrollBar) ) {
1917         if ( cellH ) {
1918             h = cellH*nRows;
1919         } else {
1920             i = 0;
1921             while ( i < nRows && h <= viewH )
1922                 h += cellHeight( i++ );
1923         }
1924
1925         if ( h > viewH )
1926             vScrollOn = TRUE;
1927         else
1928             vScrollOn = FALSE;
1929     }
1930
1931     if ( testTableFlags(Tbl_autoHScrollBar) && vScrollOn && !hScrollOn )
1932         if ( w > viewW - VSBEXT )
1933             hScrollOn = TRUE;
1934
1935     if ( testTableFlags(Tbl_autoVScrollBar) && hScrollOn && !vScrollOn )
1936         if ( h > viewH - HSBEXT )
1937             vScrollOn = TRUE;
1938
1939     setHorScrollBar( hScrollOn, FALSE );
1940     setVerScrollBar( vScrollOn, FALSE );
1941     updateFrameSize();
1942 }
1943
1944
1945 /*!
1946   \fn void QtTableView::updateScrollBars()
1947
1948   Updates the scroll bars' contents and presence to match the table's
1949   state.  Generally, you should not need to call this.
1950
1951   \sa setTableFlags()
1952 */
1953
1954 /*!
1955   Updates the scroll bars' contents and presence to match the table's
1956   state \c or \a f.
1957
1958   \sa setTableFlags()
1959 */
1960
1961 void QtTableView::updateScrollBars( uint f )
1962 {
1963     sbDirty = sbDirty | f;
1964     if ( inSbUpdate )
1965         return;
1966     inSbUpdate = TRUE;
1967
1968     if ( testTableFlags(Tbl_autoHScrollBar) && (sbDirty & horRange) ||
1969          testTableFlags(Tbl_autoVScrollBar) && (sbDirty & verRange) )
1970                                         // if range change and auto
1971         doAutoScrollBars();             // turn scroll bars on/off if needed
1972
1973     if ( !autoUpdate() ) {
1974         inSbUpdate = FALSE;
1975         return;
1976     }
1977     if ( yOffset() > 0 && testTableFlags( Tbl_autoVScrollBar ) &&
1978          !testTableFlags( Tbl_vScrollBar ) ) {
1979         setYOffset( 0 );
1980     }
1981     if ( xOffset() > 0 && testTableFlags( Tbl_autoHScrollBar ) &&
1982          !testTableFlags( Tbl_hScrollBar ) ) {
1983         setXOffset( 0 );
1984     }
1985     if ( !isVisible() ) {
1986         inSbUpdate = FALSE;
1987         return;
1988     }
1989
1990     if ( testTableFlags(Tbl_hScrollBar) && (sbDirty & horMask) != 0 ) {
1991         if ( sbDirty & horGeometry )
1992             hScrollBar->setGeometry( 0,height() - HSBEXT,
1993                                      viewWidth() + frameWidth()*2,
1994                                    HSBEXT);
1995
1996         if ( sbDirty & horSteps ) {
1997             if ( cellW )
1998                 hScrollBar->setSteps( QMIN(cellW,viewWidth()/2), viewWidth() );
1999             else
2000                 hScrollBar->setSteps( 16, viewWidth() );
2001         }
2002
2003         if ( sbDirty & horRange )
2004             hScrollBar->setRange( 0, maxXOffset() );
2005
2006         if ( sbDirty & horValue )
2007             hScrollBar->setValue( xOffs );
2008
2009                         // show scrollbar only when it has a sane geometry
2010         if ( !hScrollBar->isVisible() )
2011             hScrollBar->show();
2012     }
2013
2014     if ( testTableFlags(Tbl_vScrollBar) && (sbDirty & verMask) != 0 ) {
2015         if ( sbDirty & verGeometry )
2016             vScrollBar->setGeometry( width() - VSBEXT, 0,
2017                                      VSBEXT,
2018                                      viewHeight() + frameWidth()*2 );
2019
2020         if ( sbDirty & verSteps ) {
2021             if ( cellH )
2022                 vScrollBar->setSteps( QMIN(cellH,viewHeight()/2), viewHeight() );
2023             else
2024                 vScrollBar->setSteps( 16, viewHeight() );  // fttb! ###
2025         }
2026
2027         if ( sbDirty & verRange )
2028             vScrollBar->setRange( 0, maxYOffset() );
2029
2030         if ( sbDirty & verValue )
2031             vScrollBar->setValue( yOffs );
2032
2033                         // show scrollbar only when it has a sane geometry
2034         if ( !vScrollBar->isVisible() )
2035             vScrollBar->show();
2036     }
2037     if ( coveringCornerSquare &&
2038          ( (sbDirty & verGeometry ) || (sbDirty & horGeometry)) )
2039         cornerSquare->move( maxViewX() + frameWidth() + 1,
2040                             maxViewY() + frameWidth() + 1 );
2041
2042     sbDirty = 0;
2043     inSbUpdate = FALSE;
2044 }
2045
2046
2047 void QtTableView::updateFrameSize()
2048 {
2049     int rw = width()  - ( testTableFlags(Tbl_vScrollBar) ?
2050                           VSBEXT : 0 );
2051     int rh = height() - ( testTableFlags(Tbl_hScrollBar) ?
2052                           HSBEXT : 0 );
2053     if ( rw < 0 )
2054         rw = 0;
2055     if ( rh < 0 )
2056         rh = 0;
2057
2058     if ( autoUpdate() ) {
2059         int fh = frameRect().height();
2060         int fw = frameRect().width();
2061         setFrameRect( QRect(0,0,rw,rh) );
2062
2063         if ( rw != fw )
2064             update( QMIN(fw,rw) - frameWidth() - 2, 0, frameWidth()+4, rh );
2065         if ( rh != fh )
2066             update( 0, QMIN(fh,rh) - frameWidth() - 2, rw, frameWidth()+4 );
2067     }
2068 }
2069
2070
2071 /*!
2072   Returns the maximum horizontal offset within the table of the
2073   view's left edge in \e table coordinates.
2074
2075   This is used mainly to set the horizontal scroll bar's range.
2076
2077   \sa maxColOffset(), maxYOffset(), totalWidth()
2078 */
2079
2080 int QtTableView::maxXOffset()
2081 {
2082     int tw = totalWidth();
2083     int maxOffs;
2084     if ( testTableFlags(Tbl_scrollLastHCell) ) {
2085         if ( nCols != 1)
2086             maxOffs =  tw - ( cellW ? cellW : cellWidth( nCols - 1 ) );
2087         else
2088             maxOffs = tw - viewWidth();
2089     } else {
2090         if ( testTableFlags(Tbl_snapToHGrid) ) {
2091             if ( cellW ) {
2092                 maxOffs =  tw - (viewWidth()/cellW)*cellW;
2093             } else {
2094                 int goal = tw - viewWidth();
2095                 int pos = tw;
2096                 int nextCol = nCols - 1;
2097                 int nextCellWidth = cellWidth( nextCol );
2098                 while( nextCol > 0 && pos > goal + nextCellWidth ) {
2099                     pos -= nextCellWidth;
2100                     nextCellWidth = cellWidth( --nextCol );
2101                 }
2102                 if ( goal + nextCellWidth == pos )
2103                     maxOffs = goal;
2104                  else if ( goal < pos )
2105                    maxOffs = pos;
2106                  else
2107                    maxOffs = 0;
2108             }
2109         } else {
2110             maxOffs = tw - viewWidth();
2111         }
2112     }
2113     return maxOffs > 0 ? maxOffs : 0;
2114 }
2115
2116
2117 /*!
2118   Returns the maximum vertical offset within the table of the
2119   view's top edge in \e table coordinates.
2120
2121   This is used mainly to set the vertical scroll bar's range.
2122
2123   \sa maxRowOffset(), maxXOffset(), totalHeight()
2124 */
2125
2126 int QtTableView::maxYOffset()
2127 {
2128     int th = totalHeight();
2129     int maxOffs;
2130     if ( testTableFlags(Tbl_scrollLastVCell) ) {
2131         if ( nRows != 1)
2132             maxOffs =  th - ( cellH ? cellH : cellHeight( nRows - 1 ) );
2133         else
2134             maxOffs = th - viewHeight();
2135     } else {
2136         if ( testTableFlags(Tbl_snapToVGrid) ) {
2137             if ( cellH ) {
2138                 maxOffs =  th - (viewHeight()/cellH)*cellH;
2139             } else {
2140                 int goal = th - viewHeight();
2141                 int pos = th;
2142                 int nextRow = nRows - 1;
2143                 int nextCellHeight = cellHeight( nextRow );
2144                 while( nextRow > 0 && pos > goal + nextCellHeight ) {
2145                     pos -= nextCellHeight;
2146                     nextCellHeight = cellHeight( --nextRow );
2147                 }
2148                 if ( goal + nextCellHeight == pos )
2149                     maxOffs = goal;
2150                  else if ( goal < pos )
2151                    maxOffs = pos;
2152                  else
2153                    maxOffs = 0;
2154             }
2155         } else {
2156             maxOffs = th - viewHeight();
2157         }
2158     }
2159     return maxOffs > 0 ? maxOffs : 0;
2160 }
2161
2162
2163 /*!
2164   Returns the index of the last column, which may be at the left edge
2165   of the view.
2166
2167   Depending on the \link setTableFlags() Tbl_scrollLastHCell\endlink flag,
2168   this may or may not be the last column.
2169
2170   \sa maxXOffset(), maxRowOffset()
2171 */
2172
2173 int QtTableView::maxColOffset()
2174 {
2175     int mx = maxXOffset();
2176     if ( cellW )
2177         return mx/cellW;
2178     else {
2179         int xcd=0, col=0;
2180         while ( col < nCols && mx > (xcd=cellWidth(col)) ) {
2181             mx -= xcd;
2182             col++;
2183         }
2184         return col;
2185     }
2186 }
2187
2188
2189 /*!
2190   Returns the index of the last row, which may be at the top edge of
2191   the view.
2192
2193   Depending on the \link setTableFlags() Tbl_scrollLastVCell\endlink flag,
2194   this may or may not be the last row.
2195
2196   \sa maxYOffset(), maxColOffset()
2197 */
2198
2199 int QtTableView::maxRowOffset()
2200 {
2201     int my = maxYOffset();
2202     if ( cellH )
2203         return my/cellH;
2204     else {
2205         int ycd=0, row=0;
2206         while ( row < nRows && my > (ycd=cellHeight(row)) ) {
2207             my -= ycd;
2208             row++;
2209         }
2210         return row;
2211     }
2212 }
2213
2214
2215 void QtTableView::showOrHideScrollBars()
2216 {
2217     if ( !autoUpdate() )
2218         return;
2219     if ( vScrollBar ) {
2220         if ( testTableFlags(Tbl_vScrollBar) ) {
2221             if ( !vScrollBar->isVisible() )
2222                 sbDirty = sbDirty | verMask;
2223         } else {
2224             if ( vScrollBar->isVisible() )
2225                vScrollBar->hide();
2226         }
2227     }
2228     if ( hScrollBar ) {
2229         if ( testTableFlags(Tbl_hScrollBar) ) {
2230             if ( !hScrollBar->isVisible() )
2231                 sbDirty = sbDirty | horMask;
2232         } else {
2233             if ( hScrollBar->isVisible() )
2234                 hScrollBar->hide();
2235         }
2236     }
2237     if ( cornerSquare ) {
2238         if ( testTableFlags(Tbl_hScrollBar) &&
2239              testTableFlags(Tbl_vScrollBar) ) {
2240             if ( !cornerSquare->isVisible() )
2241                 cornerSquare->show();
2242         } else {
2243             if ( cornerSquare->isVisible() )
2244                 cornerSquare->hide();
2245         }
2246     }
2247 }
2248
2249
2250 /*!
2251   Updates the scroll bars and internal state.
2252
2253   Call this function when the table view's total size is changed;
2254   typically because the result of cellHeight() or cellWidth() have changed.
2255
2256   This function does not repaint the widget.
2257 */
2258
2259 void QtTableView::updateTableSize()
2260 {
2261     bool updateOn = autoUpdate();
2262     setAutoUpdate( FALSE );
2263     int xofs = xOffset();
2264     xOffs++; //so that setOffset will not return immediately
2265     setOffset(xofs,yOffset(),FALSE); //to calculate internal state correctly
2266     setAutoUpdate(updateOn);
2267
2268     updateScrollBars( horSteps |  horRange |
2269                       verSteps |  verRange );
2270     showOrHideScrollBars();
2271 }
2272
2273
2274 #endif
2275 #endif