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