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
QCornerSquare(QWidget * parent,const char * name)48 QCornerSquare::QCornerSquare( QWidget *parent, const char *name )
49 : QWidget( parent, name )
50 {
51 }
52
paintEvent(QPaintEvent *)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
QtTableView(QWidget * parent,const char * name,WFlags f)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
~QtTableView()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
setBackgroundColor(const QColor & c)186 void QtTableView::setBackgroundColor( const QColor &c )
187 {
188 QWidget::setBackgroundColor( c );
189 }
190
191 /*!\reimp
192 */
193
setPalette(const QPalette & p)194 void QtTableView::setPalette( const QPalette &p )
195 {
196 QWidget::setPalette( p );
197 }
198
199 /*!\reimp
200 */
201
show()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
repaint(int x,int y,int w,int h,bool erase)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
setNumRows(int rows)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
setNumCols(int cols)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
setTopCell(int row)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
setLeftCell(int col)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
setTopLeftCell(int row,int col)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
setXOffset(int x)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
setYOffset(int y)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
setOffset(int x,int y,bool updateScrBars)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
cellWidth(int)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
setCellWidth(int cellWidth)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
cellHeight(int)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
setCellHeight(int cellHeight)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
totalWidth()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
totalHeight()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
setTableFlags(uint f)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
clearTableFlags(uint f)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
setAutoUpdate(bool enable)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
updateCell(int row,int col,bool erase)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
viewRect() const985 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
lastRowVisible() const1001 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
lastColVisible() const1028 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
rowIsVisible(int row) const1050 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
colIsVisible(int col) const1060 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
coverCornerSquare(bool enable)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
snapToGrid(bool horizontal,bool vertical)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
horSbValue(int val)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
horSbSliding(int val)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
horSbSlidingDone()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
verSbValue(int val)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
verSbSliding(int val)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
verSbSlidingDone()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
setupPainter(QPainter *)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
paintEvent(QPaintEvent * e)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 */
resizeEvent(QResizeEvent *)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
updateView()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
verticalScrollBar() const1438 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
horizontalScrollBar() const1469 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
setHorScrollBar(bool on,bool update)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
setVerScrollBar(bool on,bool update)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
findRawRow(int yPos,int * cellMaxY,int * cellMinY,bool goOutsideView) const1574 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
findRawCol(int xPos,int * cellMaxX,int * cellMinX,bool goOutsideView) const1621 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
findRow(int yPos) const1675 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
findCol(int xPos) const1695 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
rowYPos(int row,int * yPos) const1717 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
colXPos(int col,int * xPos) const1757 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
scroll(int xPixels,int yPixels)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
minViewX() const1813 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
minViewY() const1826 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
maxViewX() const1840 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
maxViewY() const1856 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
viewWidth() const1872 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
viewHeight() const1886 int QtTableView::viewHeight() const
1887 {
1888 return maxViewY() - minViewY() + 1;
1889 }
1890
1891
doAutoScrollBars()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
updateScrollBars(uint f)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
updateFrameSize()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
maxXOffset()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
maxYOffset()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
maxColOffset()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
maxRowOffset()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
showOrHideScrollBars()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
updateTableSize()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
2276