1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the item views module of the Qt Toolkit.
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.
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.
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.
21
** Contact info@trolltech.com if any conditions of this licensing are
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.
27
****************************************************************************/
29
#include "qtableview.h"
30
#include <qheaderview.h>
31
#include <qitemdelegate.h>
32
#include <qapplication.h>
37
#include <qscrollbar.h>
38
#include <private/qtableview_p.h>
40
void QTableViewPrivate::init()
44
q->setEditTriggers(editTriggers|QAbstractItemView::AnyKeyPressed);
46
QHeaderView *vertical = new QHeaderView(Qt::Vertical, q);
47
vertical->setClickable(true);
48
vertical->setHighlightSections(true);
49
q->setVerticalHeader(vertical);
51
QHeaderView *horizontal = new QHeaderView(Qt::Horizontal, q);
52
horizontal->setClickable(true);
53
horizontal->setHighlightSections(true);
54
q->setHorizontalHeader(horizontal);
56
tabKeyNavigation = true;
59
void QTableViewPrivate::updateVerticalScrollbar()
63
int height = viewport->height();
64
int count = verticalHeader->count();
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);
72
// set the scroller range
74
while (y > 0 && count > 0)
75
y -= verticalHeader->sectionSize(--count);
76
int max = count * verticalStepsPerItem;
79
int visibleCount = verticalHeader->count() - count - 1;
80
q->verticalScrollBar()->setPageStep(visibleCount * verticalStepsPerItem);
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
88
q->verticalScrollBar()->setRange(0, max);
91
void QTableViewPrivate::updateHorizontalScrollbar()
95
int width = viewport->width();
96
int count = horizontalHeader->count();
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);
104
// set the scroller range
106
while (x > 0 && count > 0)
107
x -= horizontalHeader->sectionSize(--count);
108
int max = count * horizontalStepsPerItem;
110
// set page step size
111
int visibleCount = horizontalHeader->count() - count - 1;
112
q->horizontalScrollBar()->setPageStep(visibleCount * horizontalStepsPerItem);
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;
120
q->horizontalScrollBar()->setRange(0, max);
124
\class QTableView qtableview.h
126
\brief The QTableView class provides a default model/view
127
implementation of a table view.
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.
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}.
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.
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().
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.
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.
163
\sa \link model-view-programming.html Model/View Programming\endlink QAbstractItemModel QAbstractItemView
168
Constructs a table view with a \a parent to represent the data.
170
\sa QAbstractItemModel
173
QTableView::QTableView(QWidget *parent)
174
: QAbstractItemView(*new QTableViewPrivate, parent)
182
QTableView::QTableView(QTableViewPrivate &dd, QWidget *parent)
183
: QAbstractItemView(dd, parent)
189
Destroys the table view.
191
QTableView::~QTableView()
198
void QTableView::setModel(QAbstractItemModel *model)
202
if (d->selectionModel && d->model) // support row editing
203
disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
204
d->model, SLOT(submit()));
206
d->verticalHeader->setModel(model);
207
d->horizontalHeader->setModel(model);
208
QAbstractItemView::setModel(model);
214
void QTableView::setRootIndex(const QModelIndex &index)
218
d->verticalHeader->setRootIndex(index);
219
d->horizontalHeader->setRootIndex(index);
220
QAbstractItemView::setRootIndex(index);
226
void QTableView::setSelectionModel(QItemSelectionModel *selectionModel)
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()));
235
d->verticalHeader->setSelectionModel(selectionModel);
236
d->horizontalHeader->setSelectionModel(selectionModel);
237
QAbstractItemView::setSelectionModel(selectionModel);
239
if (d->model && d->selectionModel) // support row editing
240
connect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
241
d->model, SLOT(submit()));
245
Returns the table view's horizontal header.
247
\sa setHorizontalHeader() verticalHeader()
250
QHeaderView *QTableView::horizontalHeader() const
252
return d_func()->horizontalHeader;
256
Returns the table view's vertical header.
258
\sa setVerticalHeader() horizontalHeader()
260
QHeaderView *QTableView::verticalHeader() const
262
return d_func()->verticalHeader;
266
Sets the widget to use for the vertical header to \a header.
268
\sa horizontalHeader() setVerticalHeader()
270
void QTableView::setHorizontalHeader(QHeaderView *header)
275
delete d->horizontalHeader;
276
d->horizontalHeader = header;
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);
291
Sets the widget to use for the horizontal header to \a header.
293
\sa verticalHeader() setHorizontalHeader()
295
void QTableView::setVerticalHeader(QHeaderView *header)
300
delete d->verticalHeader;
301
d->verticalHeader = header;
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);
318
Scroll the contents of the table view by \a(dx, dy).
320
void QTableView::scrollContentsBy(int dx, int dy)
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);
331
dx = offset - d->horizontalHeader->offset();
333
dx = d->horizontalHeader->offset() - offset;
334
d->horizontalHeader->setOffset(offset);
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);
347
d->scrollContentsBy(dx, dy);
354
QStyleOptionViewItem QTableView::viewOptions() const
356
QStyleOptionViewItem option = QAbstractItemView::viewOptions();
357
option.showDecorationSelected = true;
362
Paints the table on receipt of the given paint event \a e.
364
void QTableView::paintEvent(QPaintEvent *e)
368
// setup temp variables for the painting
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;
385
QPainter painter(d->viewport);
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));
393
QVector<QRect> rects = e->region().rects();
394
for (int i = 0; i < rects.size(); ++i) {
396
QRect area = rects.at(i);
397
area.translate(offset);
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());
403
if (isRightToLeft()) {
404
left = (left == -1 ? model()->columnCount(rootIndex()) - 1 : left);
405
right = (right == -1 ? 0 : right);
407
left = (left == -1 ? 0 : left);
408
right = (right == -1 ? model()->columnCount(rootIndex()) - 1 : right);
412
left = qMin(left, right);
413
right = qMax(tmp, right);
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());
419
top = (top == -1 ? 0 : top);
420
bottom = (bottom == -1 ? d->model->rowCount(rootIndex()) - 1 : bottom);
423
top = qMin(top, bottom);
424
bottom = qMax(tmp, bottom);
426
// do the actual painting
428
for (int v = top; v <= bottom; ++v) {
429
int row = verticalHeader->logicalIndex(v);
430
if (verticalHeader->isSectionHidden(row))
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))
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;
451
cg = QPalette::Normal;
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));
459
painter.fillRect(colp, rowp, colw, rowh,
460
option.palette.brush(QPalette::Base));
461
itemDelegate()->paint(&painter, option, index);
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);
471
QPen old = painter.pen();
472
painter.setPen(gridPen);
473
painter.drawLine(area.left(), rowp + rowh, area.right(), rowp + rowh);
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));
490
QRect l(x, 0, w - x, h);
491
if (x < w && area.intersects(l))
492
painter.fillRect(l, option.palette.brush(QPalette::Base));
498
Returns the index position of the model item corresponding to the
499
table item at position \a pos in contents coordinates.
501
QModelIndex QTableView::indexAt(const QPoint &pos) const
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();
512
Returns the horizontal offset of the items in the table view.
516
int QTableView::horizontalOffset() const
518
return d_func()->horizontalHeader->offset();
522
Returns the vertical offset of the items in the table view.
524
\sa horizontalOffset()
526
int QTableView::verticalOffset() const
528
return d_func()->verticalHeader->offset();
532
\fn QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
534
Moves the cursor in accordance with the given \a cursorAction, using the
535
information provided by the \a modifiers.
537
\sa QAbstractItemView::CursorAction
539
QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
545
QModelIndex current = currentIndex();
546
if (!current.isValid())
548
int visualRow = verticalHeader()->visualIndex(current.row());
549
int visualColumn = horizontalHeader()->visualIndex(current.column());
550
int verticalStep = 0;
551
int horizontalStep = 0;
553
int bottom = model()->rowCount(rootIndex()) - 1;
554
int right = model()->columnCount(rootIndex()) - 1;
555
switch (cursorAction) {
558
visualRow += verticalStep;
562
visualRow += verticalStep;
566
horizontalStep = isRightToLeft() ? 1 : -1;
567
visualColumn += horizontalStep;
571
horizontalStep = isRightToLeft() ? -1 : 1;
572
visualColumn += horizontalStep;
583
int newRow = rowAt(visualRect(current).top() - d->viewport->height());
584
return model()->index(newRow <= bottom ? newRow : 0, current.column(), rootIndex());}
586
int newRow = rowAt(visualRect(current).bottom() + d->viewport->height());
587
return model()->index(newRow >= 0 ? newRow : bottom, current.column(), rootIndex());}
590
while (verticalStep != 0
592
&& visualRow <= bottom
593
&& verticalHeader()->isSectionHidden(verticalHeader()->logicalIndex(visualRow)))
594
visualRow += verticalStep;
596
while (horizontalStep != 0
598
&& visualColumn <= right
599
&& horizontalHeader()->isSectionHidden(horizontalHeader()->logicalIndex(visualColumn)))
600
visualColumn += horizontalStep;
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();
610
\fn void QTableView::setSelection(const QRect &rect,
611
QItemSelectionModel::SelectionFlags flags)
613
Selects the items within the given \a rect and in accordance with
614
the specified selection \a flags.
616
void QTableView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
618
if (!selectionModel())
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);
628
Returns the rectangle from the viewport of the items in the given
631
QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) const
633
Q_D(const QTableView);
635
if (selection.isEmpty())
638
QRegion selectionRegion;
639
bool verticalMoved = verticalHeader()->sectionsMoved();
640
bool horizontalMoved = horizontalHeader()->sectionsMoved();
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())
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())));
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())
656
int top = rowViewportPosition(range.top());
657
int bottom = rowViewportPosition(range.bottom()) + rowHeight(range.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));
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())
670
int left = columnViewportPosition(range.left());
671
int right = columnViewportPosition(range.right()) + columnWidth(range.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)));
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())
684
QRect tl = visualRect(range.topLeft());
685
QRect br = visualRect(range.bottomRight());
686
selectionRegion += QRegion(tl|br);
690
return selectionRegion;
697
QModelIndexList QTableView::selectedIndexes() const
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);
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.
717
void QTableView::rowCountChanged(int, int)
720
d_func()->viewport->update();
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.
728
void QTableView::columnCountChanged(int, int)
731
d_func()->viewport->update();
737
void QTableView::updateGeometries()
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);
746
QRect vg = d->viewport->geometry();
748
int verticalLeft = reverse ? vg.right() : (vg.left() - width);
749
d->verticalHeader->setGeometry(verticalLeft, vg.top(), width, vg.height());
751
int horizontalTop = vg.top() - height;
752
d->horizontalHeader->setGeometry(vg.left(), horizontalTop, vg.width(), height);
755
d->updateVerticalScrollbar();
756
d->updateHorizontalScrollbar();
759
QAbstractItemView::updateGeometries();
763
Returns the size hint for the given \a row's height or -1 if there
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.
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.
774
\sa QWidget::sizeHint, verticalHeader()
776
int QTableView::sizeHintForRow(int row) const
778
Q_D(const QTableView);
784
int columnfirst = columnAt(0);
785
int columnlast = columnAt(d->viewport->width());
787
columnlast = d->horizontalHeader->count() - 1;
789
QStyleOptionViewItem option = viewOptions();
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());
797
return d->showGrid ? hint + 1 : hint;
801
Returns the size hint for the given \a column's width or -1 if
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.
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.
812
\sa QWidget::sizeHint, horizontalHeader()
814
int QTableView::sizeHintForColumn(int column) const
816
Q_D(const QTableView);
822
int rowfirst = rowAt(0);
823
int rowlast = rowAt(d->viewport->height());
825
rowlast = d->verticalHeader->count() - 1;
827
QStyleOptionViewItem option = viewOptions();
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());
835
return d->showGrid ? hint + 1 : hint;
839
Returns the y-coordinate in contents coordinates of the given \a
842
int QTableView::rowViewportPosition(int row) const
844
return d_func()->verticalHeader->sectionViewportPosition(row);
848
Returns the height of the given \a row.
850
\sa resizeRowToContents()
852
int QTableView::rowHeight(int row) const
854
return d_func()->verticalHeader->sectionSize(row);
858
Returns the row in which the given y-coordinate, \a y, in contents
859
coordinates is located.
861
int QTableView::rowAt(int y) const
863
return d_func()->verticalHeader->logicalIndexAt(y);
867
Returns the x-coordinate in contents coordinates of the given \a
870
int QTableView::columnViewportPosition(int column) const
872
return d_func()->horizontalHeader->sectionViewportPosition(column);
876
Returns the width of the given \a column.
878
\sa resizeColumnToContents()
880
int QTableView::columnWidth(int column) const
882
return d_func()->horizontalHeader->sectionSize(column);
886
Returns the column in which the given x-coordinate, \a x, in contents
887
coordinates is located.
889
int QTableView::columnAt(int x) const
891
return d_func()->horizontalHeader->logicalIndexAt(x);
895
Returns true if the given \a row is hidden; otherwise returns false.
897
bool QTableView::isRowHidden(int row) const
899
return d_func()->verticalHeader->isSectionHidden(row);
903
If \a hide is true \a row will be hidden, otherwise it will be shown.
905
void QTableView::setRowHidden(int row, bool hide)
914
Returns true if the given \a column is hidden; otherwise returns false.
916
bool QTableView::isColumnHidden(int column) const
918
return d_func()->horizontalHeader->isSectionHidden(column);
922
If \a hide is true the given \a column will be hidden; otherwise it
925
void QTableView::setColumnHidden(int column, bool hide)
934
\property QTableView::showGrid
935
\brief whether the grid is shown
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.
940
bool QTableView::showGrid() const
942
return d_func()->showGrid;
945
void QTableView::setShowGrid(bool show)
947
d_func()->showGrid = show;
951
\property QTableView::gridStyle
952
\brief the pen style used to draw the grid.
954
This property holds the style used when drawing the grid (see \l{showGrid}).
956
Qt::PenStyle QTableView::gridStyle() const
958
return d_func()->gridStyle;
961
void QTableView::setGridStyle(Qt::PenStyle style)
963
d_func()->gridStyle = style;
969
Returns the rectangle on the viewport occupied by the given \a
972
QRect QTableView::visualRect(const QModelIndex &index) const
974
if (!index.isValid() || index.parent() != rootIndex())
976
d_func()->executePostedLayout();
977
return QRect(columnViewportPosition(index.column()), rowViewportPosition(index.row()),
978
columnWidth(index.column()) - 1, rowHeight(index.row()) - 1);
984
Makes sure that the given \a item is visible in the table view,
985
scrolling if necessary.
987
void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint)
991
// check if we really need to do anything
992
if (index.parent() != rootIndex() || isIndexHidden(index))
995
QRect area = d->viewport->rect();
996
QRect rect = visualRect(index);
997
if (hint == EnsureVisible && area.contains(rect)) {
998
d->setDirtyRegion(rect);
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);
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();
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);
1038
d->setDirtyRegion(visualRect(index));
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
1048
void QTableView::rowResized(int row, int, int)
1052
int y = rowViewportPosition(row);
1053
d->viewport->update(QRect(0, y, d->viewport->width(), d->viewport->height() - y));
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
1064
void QTableView::columnResized(int column, int, int)
1068
int x = columnViewportPosition(column);
1070
if (isRightToLeft())
1071
rect.setRect(0, 0, x + columnWidth(column), d->viewport->height());
1073
rect.setRect(x, 0, d->viewport->width() - x, d->viewport->height());
1074
d->viewport->update(rect.normalized());
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.
1085
void QTableView::rowMoved(int, int oldIndex, int newIndex)
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);
1094
d->viewport->update(0, top, d->viewport->width(), height);
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.
1104
void QTableView::columnMoved(int, int oldIndex, int newIndex)
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);
1113
d->viewport->update(left, 0, width, d->viewport->height());
1117
Selects the given \a row in the table view.
1121
void QTableView::selectRow(int row)
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);
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);
1143
Selects the given \a column in the table view.
1147
void QTableView::selectColumn(int column)
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);
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);
1169
Hide the given \a row.
1171
\sa showRow() hideColumn()
1173
void QTableView::hideRow(int row)
1175
d_func()->verticalHeader->hideSection(row);
1179
Hide the given \a column.
1181
\sa showColumn() hideRow()
1183
void QTableView::hideColumn(int column)
1185
d_func()->horizontalHeader->hideSection(column);
1189
Show the given \a row.
1191
\sa hideRow() showColumn()
1193
void QTableView::showRow(int row)
1195
d_func()->verticalHeader->showSection(row);
1199
Show the given \a column.
1201
\sa hideColumn() showRow()
1203
void QTableView::showColumn(int column)
1205
d_func()->horizontalHeader->showSection(column);
1209
Resizes the given \a row based on the size hints of the delegates
1210
used to render each item in the row.
1212
void QTableView::resizeRowToContents(int row)
1216
int content = sizeHintForRow(row);
1217
int header = d->verticalHeader->isHidden() ? 0 : d->verticalHeader->sectionSizeHint(row);
1218
d->verticalHeader->resizeSection(row, qMax(content, header));
1222
Resizes the given \a column based on the size hints of the delegates
1223
used to render each item in the column.
1225
void QTableView::resizeColumnToContents(int column)
1229
int content = sizeHintForColumn(column);
1230
int header = d->horizontalHeader->isHidden() ? 0 : d->horizontalHeader->sectionSizeHint(column);
1231
d->horizontalHeader->resizeSection(column, qMax(content, header));
1235
Sorts the model by the values in the given \a column.
1237
void QTableView::sortByColumn(int column)
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);
1253
void QTableView::verticalScrollbarAction(int action)
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
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
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
1279
value += steps * -y / d->verticalHeader->sectionSize(row);
1280
verticalScrollBar()->setSliderPosition(value);
1287
void QTableView::horizontalScrollbarAction(int action)
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
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);
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
1314
value += steps * -x / d->horizontalHeader->sectionSize(column);
1315
horizontalScrollBar()->setSliderPosition(value);
1322
bool QTableView::isIndexHidden(const QModelIndex &index) const
1324
return isRowHidden(index.row()) || isColumnHidden(index.column());