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