~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/itemviews/qtableview.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the item views module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "qtableview.h"
 
30
#include <qheaderview.h>
 
31
#include <qitemdelegate.h>
 
32
#include <qapplication.h>
 
33
#include <qpainter.h>
 
34
#include <qstyle.h>
 
35
#include <qsize.h>
 
36
#include <qevent.h>
 
37
#include <qscrollbar.h>
 
38
#include <private/qtableview_p.h>
 
39
 
 
40
void QTableViewPrivate::init()
 
41
{
 
42
    Q_Q(QTableView);
 
43
 
 
44
    q->setEditTriggers(editTriggers|QAbstractItemView::AnyKeyPressed);
 
45
 
 
46
    QHeaderView *vertical = new QHeaderView(Qt::Vertical, q);
 
47
    vertical->setClickable(true);
 
48
    vertical->setHighlightSections(true);
 
49
    q->setVerticalHeader(vertical);
 
50
 
 
51
    QHeaderView *horizontal = new QHeaderView(Qt::Horizontal, q);
 
52
    horizontal->setClickable(true);
 
53
    horizontal->setHighlightSections(true);
 
54
    q->setHorizontalHeader(horizontal);
 
55
 
 
56
    tabKeyNavigation = true;
 
57
}
 
58
 
 
59
void QTableViewPrivate::updateVerticalScrollbar()
 
60
{
 
61
    Q_Q(QTableView);
 
62
 
 
63
    int height = viewport->height();
 
64
    int count = verticalHeader->count();
 
65
 
 
66
    // if we have no viewport or no rows, there is nothing to do
 
67
    if (height <= 0 || count <= 0) {
 
68
        q->verticalScrollBar()->setRange(0, 0);
 
69
        return;
 
70
    }
 
71
 
 
72
    // set the scroller range
 
73
    int y = height;
 
74
    while (y > 0 && count > 0)
 
75
        y -= verticalHeader->sectionSize(--count);
 
76
    int max = count * verticalStepsPerItem;
 
77
 
 
78
    // set page step size
 
79
    int visibleCount = verticalHeader->count() - count - 1;
 
80
    q->verticalScrollBar()->setPageStep(visibleCount * verticalStepsPerItem);
 
81
 
 
82
    if (y < 0) { // if the last item starts above the viewport, we have to backtrack
 
83
        int sectionSize = verticalHeader->sectionSize(count);
 
84
        if (sectionSize) // avoid division by zero
 
85
            max += ((-y * verticalStepsPerItem)/ sectionSize) + 1; // how many units to add
 
86
    }
 
87
 
 
88
    q->verticalScrollBar()->setRange(0, max);
 
89
}
 
90
 
 
91
void QTableViewPrivate::updateHorizontalScrollbar()
 
92
{
 
93
    Q_Q(QTableView);
 
94
 
 
95
    int width = viewport->width();
 
96
    int count = horizontalHeader->count();
 
97
 
 
98
    // if we have no viewport or no columns, there is nothing to do
 
99
    if (width <= 0 || count <= 0) {
 
100
        q->horizontalScrollBar()->setRange(0, 0);
 
101
        return;
 
102
    }
 
103
 
 
104
    // set the scroller range
 
105
    int x = width;
 
106
    while (x > 0 && count > 0)
 
107
        x -= horizontalHeader->sectionSize(--count);
 
108
    int max = count * horizontalStepsPerItem;
 
109
 
 
110
    // set page step size
 
111
    int visibleCount = horizontalHeader->count() - count - 1;
 
112
    q->horizontalScrollBar()->setPageStep(visibleCount * horizontalStepsPerItem);
 
113
 
 
114
    if (x < 0) { // if the last item starts left of the viewport, we have to backtrack
 
115
        int sectionSize = horizontalHeader->sectionSize(count);
 
116
        if (sectionSize) // avoid division by zero
 
117
            max += ((-x * horizontalStepsPerItem) / sectionSize) + 1;
 
118
    }
 
119
 
 
120
    q->horizontalScrollBar()->setRange(0, max);
 
121
}
 
122
 
 
123
/*!
 
124
    \class QTableView qtableview.h
 
125
 
 
126
    \brief The QTableView class provides a default model/view
 
127
    implementation of a table view.
 
128
 
 
129
    \ingroup model-view
 
130
    \mainclass
 
131
 
 
132
    A QTableView implements a table view that displays items from a
 
133
    model. This class is used to provide standard tables that were
 
134
    previously provided by the \c QTable class, but using the more
 
135
    flexible approach provided by Qt's model/view architecture.
 
136
 
 
137
    The QTableView class is one of the \l{Model/View Classes}
 
138
    and is part of Qt's \l{Model/View Programming}{model/view framework}.
 
139
 
 
140
    QTableView implements the interfaces defined by the
 
141
    QAbstractItemView class to allow it to display data provided by
 
142
    models derived from the QAbstractItemModel class.
 
143
 
 
144
    The table has a vertical header that can be obtained using the
 
145
    verticalHeader() function, and a horizontal header that is available
 
146
    through the horizontalHeader() function. Each of the rows in the
 
147
    table can be found by using rowHeight(); similarly, the width of
 
148
    columns can be found using columnWidth().
 
149
 
 
150
    Rows and columns can be hidden and shown with hideRow(), hideColumn(),
 
151
    showRow(), and showColumn(). They can be selected with selectRow()
 
152
    and selectColumn(). The table will show a grid depending on the
 
153
    \l showGrid property.
 
154
 
 
155
    For some specialized forms of tables it is useful to be able to
 
156
    convert between row and column indexes and widget coordinates.
 
157
    The rowAt() function provides the y-coordinate within the view of the
 
158
    specified row; the row index can be used to obtain a corresponding
 
159
    y-coordinate with rowViewportPosition(). The columnAt() and
 
160
    columnViewportPosition() functions provide the equivalent conversion
 
161
    operations between x-coordinates and column indexes.
 
162
 
 
163
    \sa \link model-view-programming.html Model/View Programming\endlink QAbstractItemModel QAbstractItemView
 
164
 
 
165
*/
 
166
 
 
167
/*!
 
168
    Constructs a table view with a \a parent to represent the data.
 
169
 
 
170
    \sa QAbstractItemModel
 
171
*/
 
172
 
 
173
QTableView::QTableView(QWidget *parent)
 
174
    : QAbstractItemView(*new QTableViewPrivate, parent)
 
175
{
 
176
    d_func()->init();
 
177
}
 
178
 
 
179
/*!
 
180
  \internal
 
181
*/
 
182
QTableView::QTableView(QTableViewPrivate &dd, QWidget *parent)
 
183
    : QAbstractItemView(dd, parent)
 
184
{
 
185
    d_func()->init();
 
186
}
 
187
 
 
188
/*!
 
189
  Destroys the table view.
 
190
*/
 
191
QTableView::~QTableView()
 
192
{
 
193
}
 
194
 
 
195
/*!
 
196
  \reimp
 
197
*/
 
198
void QTableView::setModel(QAbstractItemModel *model)
 
199
{
 
200
    Q_D(QTableView);
 
201
 
 
202
    if (d->selectionModel && d->model) // support row editing
 
203
        disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
 
204
                   d->model, SLOT(submit()));
 
205
 
 
206
    d->verticalHeader->setModel(model);
 
207
    d->horizontalHeader->setModel(model);
 
208
    QAbstractItemView::setModel(model);
 
209
}
 
210
 
 
211
/*!
 
212
  \reimp
 
213
*/
 
214
void QTableView::setRootIndex(const QModelIndex &index)
 
215
{
 
216
    Q_D(QTableView);
 
217
 
 
218
    d->verticalHeader->setRootIndex(index);
 
219
    d->horizontalHeader->setRootIndex(index);
 
220
    QAbstractItemView::setRootIndex(index);
 
221
}
 
222
 
 
223
/*!
 
224
  \reimp
 
225
*/
 
226
void QTableView::setSelectionModel(QItemSelectionModel *selectionModel)
 
227
{
 
228
    Q_D(QTableView);
 
229
 
 
230
    Q_ASSERT(selectionModel);
 
231
    if (d->model && d->selectionModel) // support row editing
 
232
        disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
 
233
                   d->model, SLOT(submit()));
 
234
 
 
235
    d->verticalHeader->setSelectionModel(selectionModel);
 
236
    d->horizontalHeader->setSelectionModel(selectionModel);
 
237
    QAbstractItemView::setSelectionModel(selectionModel);
 
238
 
 
239
    if (d->model && d->selectionModel) // support row editing
 
240
        connect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
 
241
                d->model, SLOT(submit()));
 
242
}
 
243
 
 
244
/*!
 
245
    Returns the table view's horizontal header.
 
246
 
 
247
    \sa setHorizontalHeader() verticalHeader()
 
248
*/
 
249
 
 
250
QHeaderView *QTableView::horizontalHeader() const
 
251
{
 
252
    return d_func()->horizontalHeader;
 
253
}
 
254
 
 
255
/*!
 
256
    Returns the table view's vertical header.
 
257
 
 
258
    \sa setVerticalHeader() horizontalHeader()
 
259
*/
 
260
QHeaderView *QTableView::verticalHeader() const
 
261
{
 
262
    return d_func()->verticalHeader;
 
263
}
 
264
 
 
265
/*!
 
266
    Sets the widget to use for the vertical header to \a header.
 
267
 
 
268
    \sa horizontalHeader() setVerticalHeader()
 
269
*/
 
270
void QTableView::setHorizontalHeader(QHeaderView *header)
 
271
{
 
272
    Q_D(QTableView);
 
273
 
 
274
    Q_ASSERT(header);
 
275
    delete d->horizontalHeader;
 
276
    d->horizontalHeader = header;
 
277
 
 
278
    connect(d->horizontalHeader,SIGNAL(sectionResized(int,int,int)),
 
279
            this, SLOT(columnResized(int,int,int)), Qt::QueuedConnection);
 
280
    connect(d->horizontalHeader, SIGNAL(sectionMoved(int,int,int)),
 
281
            this, SLOT(columnMoved(int,int,int)), Qt::QueuedConnection);
 
282
    connect(d->horizontalHeader, SIGNAL(sectionCountChanged(int,int)),
 
283
            this, SLOT(columnCountChanged(int,int)), Qt::QueuedConnection);
 
284
    connect(d->horizontalHeader, SIGNAL(sectionPressed(int)), this, SLOT(selectColumn(int)));
 
285
    connect(d->horizontalHeader, SIGNAL(sectionHandleDoubleClicked(int)),
 
286
            this, SLOT(resizeColumnToContents(int)));
 
287
    d->horizontalHeader->setFocusProxy(this);
 
288
}
 
289
 
 
290
/*!
 
291
    Sets the widget to use for the horizontal header to \a header.
 
292
 
 
293
    \sa verticalHeader() setHorizontalHeader()
 
294
*/
 
295
void QTableView::setVerticalHeader(QHeaderView *header)
 
296
{
 
297
    Q_D(QTableView);
 
298
 
 
299
    Q_ASSERT(header);
 
300
    delete d->verticalHeader;
 
301
    d->verticalHeader = header;
 
302
 
 
303
    connect(d->verticalHeader, SIGNAL(sectionResized(int,int,int)),
 
304
            this, SLOT(rowResized(int,int,int)), Qt::QueuedConnection);
 
305
    connect(d->verticalHeader, SIGNAL(sectionMoved(int,int,int)),
 
306
            this, SLOT(rowMoved(int,int,int)), Qt::QueuedConnection);
 
307
    connect(d->verticalHeader, SIGNAL(sectionCountChanged(int,int)),
 
308
            this, SLOT(rowCountChanged(int,int)), Qt::QueuedConnection);
 
309
    connect(d->verticalHeader, SIGNAL(sectionPressed(int)), this, SLOT(selectRow(int)));
 
310
    connect(d->verticalHeader, SIGNAL(sectionHandleDoubleClicked(int)),
 
311
            this, SLOT(resizeRowToContents(int)));
 
312
    d->verticalHeader->setFocusProxy(this);
 
313
}
 
314
 
 
315
/*!
 
316
    \internal
 
317
 
 
318
    Scroll the contents of the table view by \a(dx, dy).
 
319
*/
 
320
void QTableView::scrollContentsBy(int dx, int dy)
 
321
{
 
322
    Q_D(QTableView);
 
323
 
 
324
    if (dx) { // horizontal
 
325
        int value = horizontalScrollBar()->value();
 
326
        int section = d->horizontalHeader->logicalIndex(value / horizontalStepsPerItem());
 
327
        int steps = horizontalStepsPerItem();
 
328
        int left = (value % steps) * d->horizontalHeader->sectionSize(section);
 
329
        int offset = (left / steps) + d->horizontalHeader->sectionPosition(section);
 
330
        if (isRightToLeft())
 
331
            dx = offset - d->horizontalHeader->offset();
 
332
        else
 
333
            dx = d->horizontalHeader->offset() - offset;
 
334
        d->horizontalHeader->setOffset(offset);
 
335
    }
 
336
 
 
337
    if (dy) { // vertical
 
338
        int value = verticalScrollBar()->value();
 
339
        int section = d->verticalHeader->logicalIndex(value / verticalStepsPerItem());
 
340
        int steps = verticalStepsPerItem();
 
341
        int above = (value % steps) * d->verticalHeader->sectionSize(section);
 
342
        int offset = (above / steps) + d->verticalHeader->sectionPosition(section);
 
343
        dy = d->verticalHeader->offset() - offset;
 
344
        d->verticalHeader->setOffset(offset);
 
345
    }
 
346
 
 
347
    d->scrollContentsBy(dx, dy);
 
348
}
 
349
 
 
350
 
 
351
/*!
 
352
  \reimp
 
353
*/
 
354
QStyleOptionViewItem QTableView::viewOptions() const
 
355
{
 
356
    QStyleOptionViewItem option = QAbstractItemView::viewOptions();
 
357
    option.showDecorationSelected = true;
 
358
    return option;
 
359
}
 
360
 
 
361
/*!
 
362
    Paints the table on receipt of the given paint event \a e.
 
363
*/
 
364
void QTableView::paintEvent(QPaintEvent *e)
 
365
{
 
366
    Q_D(QTableView);
 
367
 
 
368
    // setup temp variables for the painting
 
369
 
 
370
    QStyleOptionViewItem option = viewOptions();
 
371
    const QPoint offset = d->scrollDelayOffset;
 
372
    const bool showGrid = d->showGrid;
 
373
    const int gridSize = showGrid ? 1 : 0;
 
374
    const int gridHint = style()->styleHint(QStyle::SH_Table_GridLineColor, &option, this);
 
375
    const QColor gridColor = static_cast<QRgb>(gridHint);
 
376
    const QPen gridPen = QPen(gridColor, 0, d->gridStyle);
 
377
    const QItemSelectionModel *sels = selectionModel();
 
378
    const QHeaderView *verticalHeader = d->verticalHeader;
 
379
    const QHeaderView *horizontalHeader = d->horizontalHeader;
 
380
    const QModelIndex current = currentIndex();
 
381
    const bool focus = (hasFocus() || d->viewport->hasFocus()) && current.isValid();
 
382
    const QStyle::State state = option.state;
 
383
    const bool alternate = d->alternatingColors;
 
384
 
 
385
    QPainter painter(d->viewport);
 
386
 
 
387
    // if there's nothing to do, clear the area and return
 
388
    if (d->horizontalHeader->count() == 0 || d->verticalHeader->count() == 0) {
 
389
        painter.fillRect(e->rect(), option.palette.brush(QPalette::Base));
 
390
        return;
 
391
    }
 
392
 
 
393
    QVector<QRect> rects = e->region().rects();
 
394
    for (int i = 0; i < rects.size(); ++i) {
 
395
 
 
396
        QRect area = rects.at(i);
 
397
        area.translate(offset);
 
398
 
 
399
        // get the horizontal start and end sections (visual indexes)
 
400
        int left = d->horizontalHeader->visualIndexAt(area.left());
 
401
        int right = d->horizontalHeader->visualIndexAt(area.right());
 
402
 
 
403
        if (isRightToLeft()) {
 
404
            left = (left == -1 ? model()->columnCount(rootIndex()) - 1 : left);
 
405
            right = (right == -1 ? 0 : right);
 
406
        } else {
 
407
            left = (left == -1 ? 0 : left);
 
408
            right = (right == -1 ? model()->columnCount(rootIndex()) - 1 : right);
 
409
        }
 
410
 
 
411
        int tmp = left;
 
412
        left = qMin(left, right);
 
413
        right = qMax(tmp, right);
 
414
 
 
415
        // get the vertical start and end sections (visual indexes)
 
416
        int top = d->verticalHeader->visualIndexAt(area.top());
 
417
        int bottom = d->verticalHeader->visualIndexAt(area.bottom());
 
418
 
 
419
        top = (top == -1 ? 0 : top);
 
420
        bottom = (bottom == -1 ? d->model->rowCount(rootIndex()) - 1 : bottom);
 
421
 
 
422
        tmp = top;
 
423
        top = qMin(top, bottom);
 
424
        bottom = qMax(tmp, bottom);
 
425
 
 
426
        // do the actual painting
 
427
 
 
428
        for (int v = top; v <= bottom; ++v) {
 
429
            int row = verticalHeader->logicalIndex(v);
 
430
            if (verticalHeader->isSectionHidden(row))
 
431
                continue;
 
432
            int rowp = rowViewportPosition(row) + offset.y();
 
433
            int rowh = rowHeight(row) - gridSize;
 
434
            for (int h = left; h <= right; ++h) {
 
435
                int col = horizontalHeader->logicalIndex(h);
 
436
                if (horizontalHeader->isSectionHidden(col))
 
437
                    continue;
 
438
                int colp = columnViewportPosition(col) + offset.x();
 
439
                int colw = columnWidth(col) - gridSize;
 
440
                QModelIndex index = model()->index(row, col, rootIndex());
 
441
                if (index.isValid()) {
 
442
                    option.rect = QRect(colp, rowp, colw, rowh);
 
443
                    option.state = state;
 
444
                    if (sels && sels->isSelected(index))
 
445
                        option.state |= QStyle::State_Selected;
 
446
                    QPalette::ColorGroup cg;
 
447
                    if ((model()->flags(index) & Qt::ItemIsEnabled) == 0) {
 
448
                        option.state &= ~QStyle::State_Enabled;
 
449
                        cg = QPalette::Disabled;
 
450
                    } else {
 
451
                        cg = QPalette::Normal;
 
452
                    }
 
453
                    if (focus && index == current)
 
454
                        option.state |= QStyle::State_HasFocus;
 
455
                    if (alternate && v & 1)
 
456
                        painter.fillRect(colp, rowp, colw, rowh,
 
457
                                         option.palette.brush(cg, QPalette::AlternateBase));
 
458
                    else
 
459
                        painter.fillRect(colp, rowp, colw, rowh,
 
460
                                         option.palette.brush(QPalette::Base));
 
461
                    itemDelegate()->paint(&painter, option, index);
 
462
                }
 
463
                if (v == top && showGrid) {
 
464
                    QPen old = painter.pen();
 
465
                    painter.setPen(gridPen);
 
466
                    painter.drawLine(colp + colw, area.top(), colp + colw, area.bottom()+1);
 
467
                    painter.setPen(old);
 
468
                }
 
469
            }
 
470
            if (showGrid) {
 
471
                QPen old = painter.pen();
 
472
                painter.setPen(gridPen);
 
473
                painter.drawLine(area.left(), rowp + rowh, area.right(), rowp + rowh);
 
474
                painter.setPen(old);
 
475
            }
 
476
        }
 
477
 
 
478
        int w = d->viewport->width();
 
479
        int h = d->viewport->height();
 
480
        int x = d->horizontalHeader->length();
 
481
        int y = d->verticalHeader->length();
 
482
        QRect b(0, y, w, h - y);
 
483
        if (y < h && area.intersects(b))
 
484
            painter.fillRect(b, option.palette.brush(QPalette::Base));
 
485
        if (isRightToLeft()) {
 
486
            QRect r(0, 0, w - x, h);
 
487
            if (x > 0 && area.intersects(r))
 
488
                painter.fillRect(r, option.palette.brush(QPalette::Base));
 
489
        } else {
 
490
            QRect l(x, 0, w - x, h);
 
491
            if (x < w && area.intersects(l))
 
492
                painter.fillRect(l, option.palette.brush(QPalette::Base));
 
493
        }
 
494
    }
 
495
}
 
496
 
 
497
/*!
 
498
    Returns the index position of the model item corresponding to the
 
499
    table item at position \a pos in contents coordinates.
 
500
*/
 
501
QModelIndex QTableView::indexAt(const QPoint &pos) const
 
502
{
 
503
    d_func()->executePostedLayout();
 
504
    int r = rowAt(pos.y());
 
505
    int c = columnAt(pos.x());
 
506
    if (r >= 0 && c >= 0)
 
507
        return model()->index(r, c, rootIndex());
 
508
    return QModelIndex();
 
509
}
 
510
 
 
511
/*!
 
512
    Returns the horizontal offset of the items in the table view.
 
513
 
 
514
    \sa verticalOffset()
 
515
*/
 
516
int QTableView::horizontalOffset() const
 
517
{
 
518
    return d_func()->horizontalHeader->offset();
 
519
}
 
520
 
 
521
/*!
 
522
    Returns the vertical offset of the items in the table view.
 
523
 
 
524
    \sa horizontalOffset()
 
525
*/
 
526
int QTableView::verticalOffset() const
 
527
{
 
528
    return d_func()->verticalHeader->offset();
 
529
}
 
530
 
 
531
/*!
 
532
    \fn QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
 
533
 
 
534
    Moves the cursor in accordance with the given \a cursorAction, using the
 
535
    information provided by the \a modifiers.
 
536
 
 
537
    \sa QAbstractItemView::CursorAction
 
538
*/
 
539
QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
 
540
{
 
541
    Q_D(QTableView);
 
542
 
 
543
    Q_UNUSED(modifiers);
 
544
 
 
545
    QModelIndex current = currentIndex();
 
546
    if (!current.isValid())
 
547
        return current;
 
548
    int visualRow = verticalHeader()->visualIndex(current.row());
 
549
    int visualColumn = horizontalHeader()->visualIndex(current.column());
 
550
    int verticalStep = 0;
 
551
    int horizontalStep = 0;
 
552
 
 
553
    int bottom = model()->rowCount(rootIndex()) - 1;
 
554
    int right = model()->columnCount(rootIndex()) - 1;
 
555
    switch (cursorAction) {
 
556
    case MoveUp:
 
557
        verticalStep = -1;
 
558
        visualRow += verticalStep;
 
559
        break;
 
560
    case MoveDown:
 
561
        verticalStep = 1;
 
562
        visualRow += verticalStep;
 
563
        break;
 
564
    case MovePrevious:
 
565
    case MoveLeft:
 
566
        horizontalStep = isRightToLeft() ? 1 : -1;
 
567
        visualColumn += horizontalStep;
 
568
        break;
 
569
    case MoveNext:
 
570
    case MoveRight:
 
571
        horizontalStep = isRightToLeft() ? -1 : 1;
 
572
        visualColumn += horizontalStep;
 
573
        break;
 
574
    case MoveHome:
 
575
        verticalStep = 1;
 
576
        visualRow = 0;
 
577
        break;
 
578
    case MoveEnd:
 
579
        verticalStep = -1;
 
580
        visualRow = bottom;
 
581
        break;
 
582
    case MovePageUp: {
 
583
        int newRow = rowAt(visualRect(current).top() - d->viewport->height());
 
584
        return model()->index(newRow <= bottom ? newRow : 0, current.column(), rootIndex());}
 
585
    case MovePageDown: {
 
586
        int newRow = rowAt(visualRect(current).bottom() + d->viewport->height());
 
587
        return model()->index(newRow >= 0 ? newRow : bottom, current.column(), rootIndex());}
 
588
    }
 
589
 
 
590
    while (verticalStep != 0
 
591
           && visualRow >= 0
 
592
           && visualRow <= bottom
 
593
           && verticalHeader()->isSectionHidden(verticalHeader()->logicalIndex(visualRow)))
 
594
        visualRow += verticalStep;
 
595
 
 
596
    while (horizontalStep != 0
 
597
           && visualColumn >= 0
 
598
           && visualColumn <= right
 
599
           && horizontalHeader()->isSectionHidden(horizontalHeader()->logicalIndex(visualColumn)))
 
600
        visualColumn += horizontalStep;
 
601
 
 
602
    int logicalRow = verticalHeader()->logicalIndex(visualRow);
 
603
    int logicalColumn = horizontalHeader()->logicalIndex(visualColumn);
 
604
    if (model()->hasIndex(logicalRow, logicalColumn, rootIndex()))
 
605
        return model()->index(logicalRow, logicalColumn, rootIndex());
 
606
    return QModelIndex();
 
607
}
 
608
 
 
609
/*!
 
610
    \fn void QTableView::setSelection(const QRect &rect,
 
611
    QItemSelectionModel::SelectionFlags flags)
 
612
 
 
613
    Selects the items within the given \a rect and in accordance with
 
614
    the specified selection \a flags.
 
615
*/
 
616
void QTableView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
 
617
{
 
618
    if (!selectionModel())
 
619
        return;
 
620
    QModelIndex tl = indexAt(QPoint(isRightToLeft() ? rect.right() : rect.left(), rect.top()));
 
621
    QModelIndex br = indexAt(QPoint(isRightToLeft() ? rect.left() : rect.right(), rect.bottom()));
 
622
    selectionModel()->select(QItemSelection(tl, br), command);
 
623
}
 
624
 
 
625
/*!
 
626
    \internal
 
627
 
 
628
    Returns the rectangle from the viewport of the items in the given
 
629
    \a selection.
 
630
*/
 
631
QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) const
 
632
{
 
633
    Q_D(const QTableView);
 
634
 
 
635
    if (selection.isEmpty())
 
636
        return QRegion();
 
637
 
 
638
    QRegion selectionRegion;
 
639
    bool verticalMoved = verticalHeader()->sectionsMoved();
 
640
    bool horizontalMoved = horizontalHeader()->sectionsMoved();
 
641
 
 
642
    if (verticalMoved && horizontalMoved) {
 
643
        for (int i = 0; i < selection.count(); ++i) {
 
644
            QItemSelectionRange range = selection.at(i);
 
645
            if (range.parent() != rootIndex() || !range.isValid())
 
646
                continue;
 
647
            for (int r = range.top(); r <= range.bottom(); ++r)
 
648
                for (int c = range.left(); c <= range.right(); ++c)
 
649
                    selectionRegion += QRegion(visualRect(d->model->index(r, c, rootIndex())));
 
650
        }
 
651
    } else if (horizontalMoved) {
 
652
        for (int i = 0; i < selection.count(); ++i) {
 
653
            QItemSelectionRange range = selection.at(i);
 
654
            if (range.parent() != rootIndex() || !range.isValid())
 
655
                continue;
 
656
            int top = rowViewportPosition(range.top());
 
657
            int bottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom());
 
658
            if (top > bottom)
 
659
                qSwap<int>(top, bottom);
 
660
            int height = bottom - top;
 
661
            for (int c = range.left(); c <= range.right(); ++c)
 
662
                selectionRegion += QRegion(QRect(columnViewportPosition(c), top,
 
663
                                                 columnWidth(c), height));
 
664
        }
 
665
    } else if (verticalMoved) {
 
666
        for (int i = 0; i < selection.count(); ++i) {
 
667
            QItemSelectionRange range = selection.at(i);
 
668
            if (range.parent() != rootIndex() || !range.isValid())
 
669
                continue;
 
670
            int left = columnViewportPosition(range.left());
 
671
            int right = columnViewportPosition(range.right()) + columnWidth(range.right());
 
672
            if (left > right)
 
673
                qSwap<int>(left, right);
 
674
            int width = right - left;
 
675
            for (int r = range.top(); r <= range.bottom(); ++r)
 
676
                selectionRegion += QRegion(QRect(left, rowViewportPosition(r),
 
677
                                                 width, rowHeight(r)));
 
678
        }
 
679
    } else { // nothing moved
 
680
        for (int i = 0; i < selection.count(); ++i) {
 
681
            QItemSelectionRange range = selection.at(i);
 
682
            if (range.parent() != rootIndex() || !range.isValid())
 
683
                continue;
 
684
            QRect tl = visualRect(range.topLeft());
 
685
            QRect br = visualRect(range.bottomRight());
 
686
            selectionRegion += QRegion(tl|br);
 
687
        }
 
688
    }
 
689
 
 
690
    return selectionRegion;
 
691
}
 
692
 
 
693
 
 
694
/*!
 
695
  \reimp
 
696
*/
 
697
QModelIndexList QTableView::selectedIndexes() const
 
698
{
 
699
    QModelIndexList viewSelected;
 
700
    QModelIndexList modelSelected;
 
701
    if (selectionModel())
 
702
        modelSelected = selectionModel()->selectedIndexes();
 
703
    for (int i=0; i<modelSelected.count(); ++i) {
 
704
        QModelIndex index = modelSelected.at(i);
 
705
        if (!isIndexHidden(index) && index.parent() == rootIndex())
 
706
            viewSelected.append(index);
 
707
    }
 
708
    return viewSelected;
 
709
}
 
710
 
 
711
 
 
712
/*!
 
713
    This slot is called whenever rows are added or deleted. The
 
714
    previous number of rows is specified by \a oldCount, and the new
 
715
    number of rows is specified by \a newCount.
 
716
*/
 
717
void QTableView::rowCountChanged(int, int)
 
718
{
 
719
    updateGeometries();
 
720
    d_func()->viewport->update();
 
721
}
 
722
 
 
723
/*!
 
724
    This slot is called whenever columns are added or deleted. The
 
725
    previous number of columns is specified by \a oldCount, and the new
 
726
    number of columns is specified by \a newCount.
 
727
*/
 
728
void QTableView::columnCountChanged(int, int)
 
729
{
 
730
    updateGeometries();
 
731
    d_func()->viewport->update();
 
732
}
 
733
 
 
734
/*!
 
735
    \internal
 
736
*/
 
737
void QTableView::updateGeometries()
 
738
{
 
739
    Q_D(QTableView);
 
740
 
 
741
    int width = d->verticalHeader->isVisible() ? d->verticalHeader->sizeHint().width() : 0;
 
742
    int height = d->horizontalHeader->isVisible() ? d->horizontalHeader->sizeHint().height() : 0;
 
743
    bool reverse = isRightToLeft();
 
744
    setViewportMargins(reverse ? 0 : width, height, reverse ? width : 0, 0);
 
745
 
 
746
    QRect vg = d->viewport->geometry();
 
747
 
 
748
    int verticalLeft = reverse ? vg.right() : (vg.left() - width);
 
749
    d->verticalHeader->setGeometry(verticalLeft, vg.top(), width, vg.height());
 
750
 
 
751
    int horizontalTop = vg.top() - height;
 
752
    d->horizontalHeader->setGeometry(vg.left(), horizontalTop, vg.width(), height);
 
753
 
 
754
    if (d->model) {
 
755
        d->updateVerticalScrollbar();
 
756
        d->updateHorizontalScrollbar();
 
757
    }
 
758
 
 
759
    QAbstractItemView::updateGeometries();
 
760
}
 
761
 
 
762
/*!
 
763
    Returns the size hint for the given \a row's height or -1 if there
 
764
    is no model.
 
765
 
 
766
    If you need to set the height of a given row to a fixed value, call
 
767
    QHeaderView::resizeSection() on the table's vertical header.
 
768
 
 
769
    If you reimplement this function in a subclass, note that the value you
 
770
    return is only used when resizeRowToContents() is called. In that case,
 
771
    if a larger row height is required by either the vertical header or
 
772
    the item delegate, that width will be used instead.
 
773
 
 
774
    \sa QWidget::sizeHint, verticalHeader()
 
775
*/
 
776
int QTableView::sizeHintForRow(int row) const
 
777
{
 
778
    Q_D(const QTableView);
 
779
 
 
780
 
 
781
    if (!model())
 
782
        return -1;
 
783
 
 
784
    int columnfirst = columnAt(0);
 
785
    int columnlast = columnAt(d->viewport->width());
 
786
    if (columnlast < 0)
 
787
        columnlast = d->horizontalHeader->count() - 1;
 
788
 
 
789
    QStyleOptionViewItem option = viewOptions();
 
790
 
 
791
    int hint = 0;
 
792
    QModelIndex index;
 
793
    for (int column = columnfirst; column <= columnlast; ++column) {
 
794
        index = d->model->index(row, column, rootIndex());
 
795
        hint = qMax(hint, itemDelegate()->sizeHint(option, index).height());
 
796
    }
 
797
    return d->showGrid ? hint + 1 : hint;
 
798
}
 
799
 
 
800
/*!
 
801
    Returns the size hint for the given \a column's width or -1 if
 
802
    there is no model.
 
803
 
 
804
    If you need to set the width of a given column to a fixed value, call
 
805
    QHeaderView::resizeSection() on the table's horizontal header.
 
806
 
 
807
    If you reimplement this function in a subclass, note that the value you
 
808
    return is only used when resizeColumnToContents() is called. In that case,
 
809
    if a larger column width is required by either the horizontal header or
 
810
    the item delegate, that width will be used instead.
 
811
 
 
812
    \sa QWidget::sizeHint, horizontalHeader()
 
813
*/
 
814
int QTableView::sizeHintForColumn(int column) const
 
815
{
 
816
    Q_D(const QTableView);
 
817
 
 
818
 
 
819
    if (!model())
 
820
        return -1;
 
821
 
 
822
    int rowfirst = rowAt(0);
 
823
    int rowlast = rowAt(d->viewport->height());
 
824
    if (rowlast < 0)
 
825
        rowlast = d->verticalHeader->count() - 1;
 
826
 
 
827
    QStyleOptionViewItem option = viewOptions();
 
828
 
 
829
    int hint = 0;
 
830
    QModelIndex index;
 
831
    for (int row = rowfirst; row <= rowlast; ++row) {
 
832
        index = d->model->index(row, column, rootIndex());
 
833
        hint = qMax(hint, itemDelegate()->sizeHint(option, index).width());
 
834
    }
 
835
    return d->showGrid ? hint + 1 : hint;
 
836
}
 
837
 
 
838
/*!
 
839
    Returns the y-coordinate in contents coordinates of the given \a
 
840
    row.
 
841
*/
 
842
int QTableView::rowViewportPosition(int row) const
 
843
{
 
844
    return d_func()->verticalHeader->sectionViewportPosition(row);
 
845
}
 
846
 
 
847
/*!
 
848
    Returns the height of the given \a row.
 
849
 
 
850
    \sa resizeRowToContents()
 
851
*/
 
852
int QTableView::rowHeight(int row) const
 
853
{
 
854
    return d_func()->verticalHeader->sectionSize(row);
 
855
}
 
856
 
 
857
/*!
 
858
    Returns the row in which the given y-coordinate, \a y, in contents
 
859
    coordinates is located.
 
860
*/
 
861
int QTableView::rowAt(int y) const
 
862
{
 
863
    return d_func()->verticalHeader->logicalIndexAt(y);
 
864
}
 
865
 
 
866
/*!
 
867
    Returns the x-coordinate in contents coordinates of the given \a
 
868
    column.
 
869
*/
 
870
int QTableView::columnViewportPosition(int column) const
 
871
{
 
872
    return d_func()->horizontalHeader->sectionViewportPosition(column);
 
873
}
 
874
 
 
875
/*!
 
876
    Returns the width of the given \a column.
 
877
 
 
878
    \sa resizeColumnToContents()
 
879
*/
 
880
int QTableView::columnWidth(int column) const
 
881
{
 
882
    return d_func()->horizontalHeader->sectionSize(column);
 
883
}
 
884
 
 
885
/*!
 
886
    Returns the column in which the given x-coordinate, \a x, in contents
 
887
    coordinates is located.
 
888
*/
 
889
int QTableView::columnAt(int x) const
 
890
{
 
891
    return d_func()->horizontalHeader->logicalIndexAt(x);
 
892
}
 
893
 
 
894
/*!
 
895
    Returns true if the given \a row is hidden; otherwise returns false.
 
896
*/
 
897
bool QTableView::isRowHidden(int row) const
 
898
{
 
899
    return d_func()->verticalHeader->isSectionHidden(row);
 
900
}
 
901
 
 
902
/*!
 
903
  If \a hide is true \a row will be hidden, otherwise it will be shown.
 
904
*/
 
905
void QTableView::setRowHidden(int row, bool hide)
 
906
{
 
907
    if (hide)
 
908
        hideRow(row);
 
909
    else
 
910
        showRow(row);
 
911
}
 
912
 
 
913
/*!
 
914
    Returns true if the given \a column is hidden; otherwise returns false.
 
915
*/
 
916
bool QTableView::isColumnHidden(int column) const
 
917
{
 
918
    return d_func()->horizontalHeader->isSectionHidden(column);
 
919
}
 
920
 
 
921
/*!
 
922
  If \a hide is true the given \a column will be hidden; otherwise it
 
923
  will be shown.
 
924
*/
 
925
void QTableView::setColumnHidden(int column, bool hide)
 
926
{
 
927
    if (hide)
 
928
        hideColumn(column);
 
929
    else
 
930
        showColumn(column);
 
931
}
 
932
 
 
933
/*!
 
934
    \property QTableView::showGrid
 
935
    \brief whether the grid is shown
 
936
 
 
937
    If this property is true a grid is drawn for the table; if the
 
938
    property is false, no grid is drawn. The default value is true.
 
939
*/
 
940
bool QTableView::showGrid() const
 
941
{
 
942
    return d_func()->showGrid;
 
943
}
 
944
 
 
945
void QTableView::setShowGrid(bool show)
 
946
{
 
947
    d_func()->showGrid = show;
 
948
}
 
949
 
 
950
/*!
 
951
  \property QTableView::gridStyle
 
952
  \brief  the pen style used to draw the grid.
 
953
 
 
954
  This property holds the style used when drawing the grid (see \l{showGrid}).
 
955
*/
 
956
Qt::PenStyle QTableView::gridStyle() const
 
957
{
 
958
    return d_func()->gridStyle;
 
959
}
 
960
 
 
961
void QTableView::setGridStyle(Qt::PenStyle style)
 
962
{
 
963
    d_func()->gridStyle = style;
 
964
}
 
965
 
 
966
/*!
 
967
    \internal
 
968
 
 
969
    Returns the rectangle on the viewport occupied by the given \a
 
970
    index.
 
971
*/
 
972
QRect QTableView::visualRect(const QModelIndex &index) const
 
973
{
 
974
    if (!index.isValid() || index.parent() != rootIndex())
 
975
        return QRect();
 
976
    d_func()->executePostedLayout();
 
977
    return QRect(columnViewportPosition(index.column()), rowViewportPosition(index.row()),
 
978
                 columnWidth(index.column()) - 1, rowHeight(index.row()) - 1);
 
979
}
 
980
 
 
981
/*!
 
982
    \internal
 
983
 
 
984
    Makes sure that the given \a item is visible in the table view,
 
985
    scrolling if necessary.
 
986
*/
 
987
void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint)
 
988
{
 
989
    Q_D(QTableView);
 
990
 
 
991
    // check if we really need to do anything
 
992
    if (index.parent() != rootIndex() || isIndexHidden(index))
 
993
        return;
 
994
 
 
995
    QRect area = d->viewport->rect();
 
996
    QRect rect = visualRect(index);
 
997
    if (hint == EnsureVisible && area.contains(rect)) {
 
998
        d->setDirtyRegion(rect);
 
999
        return;
 
1000
    }
 
1001
 
 
1002
    // vertical
 
1003
    int verticalSteps = verticalStepsPerItem();
 
1004
    bool above = (hint == EnsureVisible && rect.top() < area.top());
 
1005
    bool below = (hint == EnsureVisible && rect.bottom() > area.bottom());
 
1006
    if (hint == PositionAtTop || above) {
 
1007
        verticalScrollBar()->setValue(index.row() * verticalSteps);
 
1008
    } else if (hint == PositionAtBottom || below) {
 
1009
        int r = index.row();
 
1010
        int y = area.height();
 
1011
        while (y > 0 && r > 0)
 
1012
            y -= rowHeight(r--);
 
1013
        int h = rowHeight(r);
 
1014
        int a = (-y * verticalSteps) / (h ? h : 1);
 
1015
        verticalScrollBar()->setValue(++r * verticalSteps + a);
 
1016
    }
 
1017
 
 
1018
    // horizontal
 
1019
    int horizontalSteps = horizontalStepsPerItem();
 
1020
    bool leftOf = isRightToLeft()
 
1021
                  ? rect.right() > area.right()
 
1022
                  : rect.left() < area.left();
 
1023
    bool rightOf = isRightToLeft()
 
1024
                   ? rect.left() < area.left()
 
1025
                   : rect.right() > area.right();
 
1026
    if (leftOf) {
 
1027
        horizontalScrollBar()->setValue(index.column() * horizontalSteps);
 
1028
    } else if (rightOf) {
 
1029
        int c = index.column();
 
1030
        int x = area.width();
 
1031
        while (x > 0 && c > 0)
 
1032
            x -= columnWidth(c--);
 
1033
        int w = columnWidth(c);
 
1034
        int a = (-x * horizontalSteps) / (w ? w : 1);
 
1035
        horizontalScrollBar()->setValue(++c * horizontalSteps + a);
 
1036
    }
 
1037
 
 
1038
    d->setDirtyRegion(visualRect(index));
 
1039
}
 
1040
 
 
1041
/*!
 
1042
    This slot is called to change the height of the given \a row. The
 
1043
    old height is specified by \a oldHeight, and the new height by \a
 
1044
    newHeight.
 
1045
 
 
1046
    \sa columnResized()
 
1047
*/
 
1048
void QTableView::rowResized(int row, int, int)
 
1049
{
 
1050
    Q_D(QTableView);
 
1051
 
 
1052
    int y = rowViewportPosition(row);
 
1053
    d->viewport->update(QRect(0, y, d->viewport->width(), d->viewport->height() - y));
 
1054
    updateGeometries();
 
1055
}
 
1056
 
 
1057
/*!
 
1058
    This slot is called to change the width of the given \a column.
 
1059
    The old width is specified by \a oldWidth, and the new width by \a
 
1060
    newWidth.
 
1061
 
 
1062
    \sa rowResized()
 
1063
*/
 
1064
void QTableView::columnResized(int column, int, int)
 
1065
{
 
1066
    Q_D(QTableView);
 
1067
 
 
1068
    int x = columnViewportPosition(column);
 
1069
    QRect rect;
 
1070
    if (isRightToLeft())
 
1071
        rect.setRect(0, 0, x + columnWidth(column), d->viewport->height());
 
1072
    else
 
1073
        rect.setRect(x, 0, d->viewport->width() - x, d->viewport->height());
 
1074
    d->viewport->update(rect.normalized());
 
1075
    updateGeometries();
 
1076
}
 
1077
 
 
1078
/*!
 
1079
    This slot is called to change the index of the given \a row in the
 
1080
    table view. The old index is specified by \a oldIndex, and the new
 
1081
    index by \a newIndex.
 
1082
 
 
1083
    \sa columnMoved()
 
1084
*/
 
1085
void QTableView::rowMoved(int, int oldIndex, int newIndex)
 
1086
{
 
1087
    Q_D(QTableView);
 
1088
 
 
1089
    int o = rowViewportPosition(d->verticalHeader->logicalIndex(oldIndex));
 
1090
    int n = rowViewportPosition(d->verticalHeader->logicalIndex(newIndex));
 
1091
    int top = (o < n ? o : n);
 
1092
    int height = d->viewport->height() - (o > n ? o : n);
 
1093
    updateGeometries();
 
1094
    d->viewport->update(0, top, d->viewport->width(), height);
 
1095
}
 
1096
 
 
1097
/*!
 
1098
    This slot is called to change the index of the given \a column in
 
1099
    the table view. The old index is specified by \a oldIndex, and
 
1100
    the new index by \a newIndex.
 
1101
 
 
1102
    \sa rowMoved()
 
1103
*/
 
1104
void QTableView::columnMoved(int, int oldIndex, int newIndex)
 
1105
{
 
1106
    Q_D(QTableView);
 
1107
 
 
1108
    int o = columnViewportPosition(d->horizontalHeader->logicalIndex(oldIndex));
 
1109
    int n = columnViewportPosition(d->horizontalHeader->logicalIndex(newIndex));
 
1110
    int left = (o < n ? o : n);
 
1111
    int width = d->viewport->width() - (o > n ? o : n);
 
1112
    updateGeometries();
 
1113
    d->viewport->update(left, 0, width, d->viewport->height());
 
1114
}
 
1115
 
 
1116
/*!
 
1117
    Selects the given \a row in the table view.
 
1118
 
 
1119
    \sa selectColumn()
 
1120
*/
 
1121
void QTableView::selectRow(int row)
 
1122
{
 
1123
    Q_D(QTableView);
 
1124
 
 
1125
    if (row >= 0 && row < model()->rowCount(rootIndex())) {
 
1126
        QItemSelectionModel::SelectionFlags command = selectionCommand(QModelIndex());
 
1127
        QModelIndex index = model()->index(row, 0, rootIndex());
 
1128
        if (selectionMode() == SingleSelection) {
 
1129
            selectionModel()->setCurrentIndex(index, command);
 
1130
        } else {
 
1131
            selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
 
1132
            if ((command & QItemSelectionModel::Current) == 0)
 
1133
                d->rowSectionAnchor = row;
 
1134
            QModelIndex tl = model()->index(qMin(d->rowSectionAnchor, row), 0, rootIndex());
 
1135
            QModelIndex br = model()->index(qMax(d->rowSectionAnchor, row),
 
1136
                                            model()->columnCount(rootIndex()) - 1, rootIndex());
 
1137
            selectionModel()->select(QItemSelection(tl, br), command);
 
1138
        }
 
1139
    }
 
1140
}
 
1141
 
 
1142
/*!
 
1143
    Selects the given \a column in the table view.
 
1144
 
 
1145
    \sa selectRow()
 
1146
*/
 
1147
void QTableView::selectColumn(int column)
 
1148
{
 
1149
    Q_D(QTableView);
 
1150
 
 
1151
    if (column >= 0 && column < model()->columnCount(rootIndex())) {
 
1152
        QItemSelectionModel::SelectionFlags command = selectionCommand(QModelIndex());
 
1153
        QModelIndex index = model()->index(0, column, rootIndex());
 
1154
        if (selectionMode() == SingleSelection) {
 
1155
            selectionModel()->setCurrentIndex(index, command);
 
1156
        } else {
 
1157
            selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
 
1158
            if ((command & QItemSelectionModel::Current) == 0)
 
1159
                d->columnSectionAnchor = column;
 
1160
            QModelIndex tl = model()->index(0, qMin(d->columnSectionAnchor, column), rootIndex());
 
1161
            QModelIndex br = model()->index(model()->rowCount(rootIndex()) - 1,
 
1162
                                            qMax(d->columnSectionAnchor, column), rootIndex());
 
1163
            selectionModel()->select(QItemSelection(tl, br), command);
 
1164
        }
 
1165
    }
 
1166
}
 
1167
 
 
1168
/*!
 
1169
    Hide the given \a row.
 
1170
 
 
1171
    \sa showRow() hideColumn()
 
1172
*/
 
1173
void QTableView::hideRow(int row)
 
1174
{
 
1175
    d_func()->verticalHeader->hideSection(row);
 
1176
}
 
1177
 
 
1178
/*!
 
1179
    Hide the given \a column.
 
1180
 
 
1181
    \sa showColumn() hideRow()
 
1182
*/
 
1183
void QTableView::hideColumn(int column)
 
1184
{
 
1185
    d_func()->horizontalHeader->hideSection(column);
 
1186
}
 
1187
 
 
1188
/*!
 
1189
    Show the given \a row.
 
1190
 
 
1191
    \sa hideRow() showColumn()
 
1192
*/
 
1193
void QTableView::showRow(int row)
 
1194
{
 
1195
    d_func()->verticalHeader->showSection(row);
 
1196
}
 
1197
 
 
1198
/*!
 
1199
    Show the given \a column.
 
1200
 
 
1201
    \sa hideColumn() showRow()
 
1202
*/
 
1203
void QTableView::showColumn(int column)
 
1204
{
 
1205
    d_func()->horizontalHeader->showSection(column);
 
1206
}
 
1207
 
 
1208
/*!
 
1209
    Resizes the given \a row based on the size hints of the delegates
 
1210
    used to render each item in the row.
 
1211
*/
 
1212
void QTableView::resizeRowToContents(int row)
 
1213
{
 
1214
    Q_D(QTableView);
 
1215
 
 
1216
    int content = sizeHintForRow(row);
 
1217
    int header = d->verticalHeader->isHidden() ? 0 : d->verticalHeader->sectionSizeHint(row);
 
1218
    d->verticalHeader->resizeSection(row, qMax(content, header));
 
1219
}
 
1220
 
 
1221
/*!
 
1222
    Resizes the given \a column based on the size hints of the delegates
 
1223
    used to render each item in the column.
 
1224
*/
 
1225
void QTableView::resizeColumnToContents(int column)
 
1226
{
 
1227
    Q_D(QTableView);
 
1228
 
 
1229
    int content = sizeHintForColumn(column);
 
1230
    int header = d->horizontalHeader->isHidden() ? 0 : d->horizontalHeader->sectionSizeHint(column);
 
1231
    d->horizontalHeader->resizeSection(column, qMax(content, header));
 
1232
}
 
1233
 
 
1234
/*!
 
1235
  Sorts the model by the values in the given \a column.
 
1236
 */
 
1237
void QTableView::sortByColumn(int column)
 
1238
{
 
1239
    Q_D(QTableView);
 
1240
 
 
1241
    if (!d->model)
 
1242
        return;
 
1243
    bool ascending = (horizontalHeader()->sortIndicatorSection() == column
 
1244
                      && horizontalHeader()->sortIndicatorOrder() == Qt::DescendingOrder);
 
1245
    Qt::SortOrder order = ascending ? Qt::AscendingOrder : Qt::DescendingOrder;
 
1246
    horizontalHeader()->setSortIndicator(column, order);
 
1247
    d->model->sort(column, order);
 
1248
}
 
1249
 
 
1250
/*!
 
1251
    \internal
 
1252
*/
 
1253
void QTableView::verticalScrollbarAction(int action)
 
1254
{
 
1255
    Q_D(QTableView);
 
1256
 
 
1257
    int steps = verticalStepsPerItem();
 
1258
    int value = verticalScrollBar()->value();
 
1259
    int row = value / steps;
 
1260
    int above = (value % steps) * d->verticalHeader->sectionSize(row); // what's left; in "item units"
 
1261
    int y = -(above / steps); // above the page
 
1262
 
 
1263
    if (action == QScrollBar::SliderPageStepAdd) {
 
1264
        // go down to the bottom of the page
 
1265
        int h = d->viewport->height();
 
1266
        while (y < h && row < d->model->rowCount(rootIndex()))
 
1267
            y += d->verticalHeader->sectionSize(row++);
 
1268
        value = row * steps; // i is now the last item on the page
 
1269
        if (y > h && row)
 
1270
            value -= steps * (y - h) / d->verticalHeader->sectionSize(row - 1);
 
1271
        verticalScrollBar()->setSliderPosition(value);
 
1272
    } else if (action == QScrollBar::SliderPageStepSub) {
 
1273
        y += d->viewport->height();
 
1274
        // go up to the top of the page
 
1275
        while (y > 0 && row > 0)
 
1276
            y -= d->verticalHeader->sectionSize(--row);
 
1277
        value = row * steps; // i is now the first item in the page
 
1278
        if (y < 0)
 
1279
            value += steps * -y / d->verticalHeader->sectionSize(row);
 
1280
        verticalScrollBar()->setSliderPosition(value);
 
1281
    }
 
1282
}
 
1283
 
 
1284
/*!
 
1285
    \internal
 
1286
*/
 
1287
void QTableView::horizontalScrollbarAction(int action)
 
1288
{
 
1289
    Q_D(QTableView);
 
1290
 
 
1291
    int steps = horizontalStepsPerItem();
 
1292
    int value = horizontalScrollBar()->value();
 
1293
    int column = value / steps;
 
1294
    int above = (value % steps) * d->horizontalHeader->sectionSize(column); // what's left; in "item units"
 
1295
    int x = -(above / steps); // above the page
 
1296
 
 
1297
    if (action == QScrollBar::SliderPageStepAdd) {
 
1298
        // go down to the right of the page
 
1299
        int w = d->viewport->width();
 
1300
        while (x < w && column < d->model->columnCount(rootIndex()))
 
1301
            x += d->horizontalHeader->sectionSize(column++);
 
1302
        value = column * steps; // i is now the last item on the page
 
1303
        if (x > w && column)
 
1304
            value -= steps * (x - w) / d->horizontalHeader->sectionSize(column - 1);
 
1305
        horizontalScrollBar()->setSliderPosition(value);
 
1306
 
 
1307
    } else if (action == QScrollBar::SliderPageStepSub) {
 
1308
        x += d->viewport->width();
 
1309
        // go up to the left of the page
 
1310
        while (x > 0 && column > 0)
 
1311
            x -= d->horizontalHeader->sectionSize(--column);
 
1312
        value = column * steps; // i is now the first item in the page
 
1313
        if (x < 0)
 
1314
            value += steps * -x / d->horizontalHeader->sectionSize(column);
 
1315
        horizontalScrollBar()->setSliderPosition(value);
 
1316
    }
 
1317
}
 
1318
 
 
1319
/*!
 
1320
  \reimp
 
1321
*/
 
1322
bool QTableView::isIndexHidden(const QModelIndex &index) const
 
1323
{
 
1324
    return isRowHidden(index.row()) || isColumnHidden(index.column());
 
1325
}