~ubuntu-branches/ubuntu/warty/qps/warty

« back to all changes in this revision

Viewing changes to qttableview.C

  • Committer: Bazaar Package Importer
  • Author(s): Hanno Wagner
  • Date: 2004-03-15 23:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20040315231122-ydwd98o300gq0coq
Tags: 1.9.7.0-3
* Port to QT 3 (this time for real), with apologies to ro@suse.
* Update copyright file.
* Use default C++ compiler.
* Thanks for the Help from Florian Weimar

Show diffs side-by-side

added added

removed removed

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