~ubuntu-branches/ubuntu/breezy/koffice/breezy

« back to all changes in this revision

Viewing changes to kchart/qttableview.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ben Burton
  • Date: 2004-05-09 11:33:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040509113300-vfrdadqsvjfuhn3b
Tags: 1:1.3.1-1
* New upstream bugfix release.
* Built against newer imagemagick (closes: #246623).
* Made koffice-libs/kformula recommend/depend on latex-xft-fonts, which
  provides mathematical fonts that the formula editor can use.  Also
  patched the kformula part to make these fonts the default.
* Changed kword menu hint from "WordProcessors" to "Word processors"
  (closes: #246209).
* Spellchecker configuration is now fixed (closes: #221256, #227568).

Show diffs side-by-side

added added

removed removed

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