1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** Contact: Qt Software Information ([email protected])
|
---|
5 | **
|
---|
6 | ** This file is part of the QtGui module of the Qt Toolkit.
|
---|
7 | **
|
---|
8 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
9 | ** Commercial Usage
|
---|
10 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
11 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
12 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
13 | ** a written agreement between you and Nokia.
|
---|
14 | **
|
---|
15 | ** GNU Lesser General Public License Usage
|
---|
16 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
17 | ** General Public License version 2.1 as published by the Free Software
|
---|
18 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
19 | ** packaging of this file. Please review the following information to
|
---|
20 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
21 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
22 | **
|
---|
23 | ** In addition, as a special exception, Nokia gives you certain
|
---|
24 | ** additional rights. These rights are described in the Nokia Qt LGPL
|
---|
25 | ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
|
---|
26 | ** package.
|
---|
27 | **
|
---|
28 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you are unsure which license is appropriate for your use, please
|
---|
37 | ** contact the sales department at [email protected].
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include "qtableview.h"
|
---|
43 |
|
---|
44 | #ifndef QT_NO_TABLEVIEW
|
---|
45 | #include <qheaderview.h>
|
---|
46 | #include <qitemdelegate.h>
|
---|
47 | #include <qapplication.h>
|
---|
48 | #include <qpainter.h>
|
---|
49 | #include <qstyle.h>
|
---|
50 | #include <qsize.h>
|
---|
51 | #include <qevent.h>
|
---|
52 | #include <qbitarray.h>
|
---|
53 | #include <qscrollbar.h>
|
---|
54 | #include <qabstractbutton.h>
|
---|
55 | #include <private/qtableview_p.h>
|
---|
56 | #ifndef QT_NO_ACCESSIBILITY
|
---|
57 | #include <qaccessible.h>
|
---|
58 | #endif
|
---|
59 |
|
---|
60 | QT_BEGIN_NAMESPACE
|
---|
61 |
|
---|
62 | class QTableCornerButton : public QAbstractButton
|
---|
63 | {
|
---|
64 | Q_OBJECT
|
---|
65 | public:
|
---|
66 | QTableCornerButton(QWidget *parent) : QAbstractButton(parent) {}
|
---|
67 | void paintEvent(QPaintEvent*) {
|
---|
68 | QStyleOptionHeader opt;
|
---|
69 | opt.init(this);
|
---|
70 | QStyle::State state = QStyle::State_None;
|
---|
71 | if (isEnabled())
|
---|
72 | state |= QStyle::State_Enabled;
|
---|
73 | if (isActiveWindow())
|
---|
74 | state |= QStyle::State_Active;
|
---|
75 | if (isDown())
|
---|
76 | state |= QStyle::State_Sunken;
|
---|
77 | opt.state = state;
|
---|
78 | opt.rect = rect();
|
---|
79 | opt.position = QStyleOptionHeader::OnlyOneSection;
|
---|
80 | QPainter painter(this);
|
---|
81 | style()->drawControl(QStyle::CE_Header, &opt, &painter, this);
|
---|
82 | }
|
---|
83 | };
|
---|
84 |
|
---|
85 | void QTableViewPrivate::init()
|
---|
86 | {
|
---|
87 | Q_Q(QTableView);
|
---|
88 |
|
---|
89 | q->setEditTriggers(editTriggers|QAbstractItemView::AnyKeyPressed);
|
---|
90 |
|
---|
91 | QHeaderView *vertical = new QHeaderView(Qt::Vertical, q);
|
---|
92 | vertical->setClickable(true);
|
---|
93 | vertical->setHighlightSections(true);
|
---|
94 | q->setVerticalHeader(vertical);
|
---|
95 |
|
---|
96 | QHeaderView *horizontal = new QHeaderView(Qt::Horizontal, q);
|
---|
97 | horizontal->setClickable(true);
|
---|
98 | horizontal->setHighlightSections(true);
|
---|
99 | q->setHorizontalHeader(horizontal);
|
---|
100 |
|
---|
101 | tabKeyNavigation = true;
|
---|
102 |
|
---|
103 | cornerWidget = new QTableCornerButton(q);
|
---|
104 | cornerWidget->setFocusPolicy(Qt::NoFocus);
|
---|
105 | QObject::connect(cornerWidget, SIGNAL(clicked()), q, SLOT(selectAll()));
|
---|
106 | }
|
---|
107 |
|
---|
108 | /*!
|
---|
109 | \internal
|
---|
110 | Trims away indices that are hidden in the treeview due to hidden horizontal or vertical sections.
|
---|
111 | */
|
---|
112 | void QTableViewPrivate::trimHiddenSelections(QItemSelectionRange *range) const
|
---|
113 | {
|
---|
114 | Q_ASSERT(range && range->isValid());
|
---|
115 |
|
---|
116 | int top = range->top();
|
---|
117 | int left = range->left();
|
---|
118 | int bottom = range->bottom();
|
---|
119 | int right = range->right();
|
---|
120 |
|
---|
121 | while (bottom >= top && verticalHeader->isSectionHidden(bottom))
|
---|
122 | --bottom;
|
---|
123 | while (right >= left && horizontalHeader->isSectionHidden(right))
|
---|
124 | --right;
|
---|
125 |
|
---|
126 | if (top > bottom || left > right) { // everything is hidden
|
---|
127 | *range = QItemSelectionRange();
|
---|
128 | return;
|
---|
129 | }
|
---|
130 |
|
---|
131 | while (verticalHeader->isSectionHidden(top) && top <= bottom)
|
---|
132 | ++top;
|
---|
133 | while (horizontalHeader->isSectionHidden(left) && left <= right)
|
---|
134 | ++left;
|
---|
135 |
|
---|
136 | if (top > bottom || left > right) { // everything is hidden
|
---|
137 | *range = QItemSelectionRange();
|
---|
138 | return;
|
---|
139 | }
|
---|
140 |
|
---|
141 | QModelIndex bottomRight = model->index(bottom, right, range->parent());
|
---|
142 | QModelIndex topLeft = model->index(top, left, range->parent());
|
---|
143 | *range = QItemSelectionRange(topLeft, bottomRight);
|
---|
144 | }
|
---|
145 |
|
---|
146 | /*!
|
---|
147 | \internal
|
---|
148 | Sets the span for the cell at (\a row, \a column).
|
---|
149 | */
|
---|
150 | void QTableViewPrivate::setSpan(int row, int column, int rowSpan, int columnSpan)
|
---|
151 | {
|
---|
152 | if (row < 0 || column < 0 || rowSpan < 0 || columnSpan < 0)
|
---|
153 | return;
|
---|
154 | Span sp(row, column, rowSpan, columnSpan);
|
---|
155 | QList<Span>::iterator it;
|
---|
156 | for (it = spans.begin(); it != spans.end(); ++it) {
|
---|
157 | if (((*it).top() == sp.top()) && ((*it).left() == sp.left())) {
|
---|
158 | if ((sp.height() == 1) && (sp.width() == 1))
|
---|
159 | spans.erase(it); // "Implicit" span (1, 1), no need to store it
|
---|
160 | else
|
---|
161 | *it = sp; // Replace
|
---|
162 | return;
|
---|
163 | }
|
---|
164 | }
|
---|
165 | spans.append(sp);
|
---|
166 | }
|
---|
167 |
|
---|
168 | /*!
|
---|
169 | \internal
|
---|
170 | Gets the span information for the cell at (\a row, \a column).
|
---|
171 | */
|
---|
172 | QTableViewPrivate::Span QTableViewPrivate::span(int row, int column) const
|
---|
173 | {
|
---|
174 | QList<Span>::const_iterator it;
|
---|
175 | for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
|
---|
176 | Span span = *it;
|
---|
177 | if (isInSpan(row, column, span))
|
---|
178 | return span;
|
---|
179 | }
|
---|
180 | return Span(row, column, 1, 1);
|
---|
181 | }
|
---|
182 |
|
---|
183 | /*!
|
---|
184 | \internal
|
---|
185 | Returns the logical index of the last section that's part of the span.
|
---|
186 | */
|
---|
187 | int QTableViewPrivate::sectionSpanEndLogical(const QHeaderView *header, int logical, int span) const
|
---|
188 | {
|
---|
189 | int visual = header->visualIndex(logical);
|
---|
190 | for (int i = 1; i < span; ) {
|
---|
191 | if (++visual >= header->count())
|
---|
192 | break;
|
---|
193 | logical = header->logicalIndex(visual);
|
---|
194 | ++i;
|
---|
195 | }
|
---|
196 | return logical;
|
---|
197 | }
|
---|
198 |
|
---|
199 | /*!
|
---|
200 | \internal
|
---|
201 | Returns the size of the span starting at logical index \a logical
|
---|
202 | and spanning \a span sections.
|
---|
203 | */
|
---|
204 | int QTableViewPrivate::sectionSpanSize(const QHeaderView *header, int logical, int span) const
|
---|
205 | {
|
---|
206 | int endLogical = sectionSpanEndLogical(header, logical, span);
|
---|
207 | return header->sectionPosition(endLogical)
|
---|
208 | - header->sectionPosition(logical)
|
---|
209 | + header->sectionSize(endLogical);
|
---|
210 | }
|
---|
211 |
|
---|
212 | /*!
|
---|
213 | \internal
|
---|
214 | Returns true if the section at logical index \a logical is part of the span
|
---|
215 | starting at logical index \a spanLogical and spanning \a span sections;
|
---|
216 | otherwise, returns false.
|
---|
217 | */
|
---|
218 | bool QTableViewPrivate::spanContainsSection(const QHeaderView *header, int logical, int spanLogical, int span) const
|
---|
219 | {
|
---|
220 | if (logical == spanLogical)
|
---|
221 | return true; // it's the start of the span
|
---|
222 | int visual = header->visualIndex(spanLogical);
|
---|
223 | for (int i = 1; i < span; ) {
|
---|
224 | if (++visual >= header->count())
|
---|
225 | break;
|
---|
226 | spanLogical = header->logicalIndex(visual);
|
---|
227 | if (logical == spanLogical)
|
---|
228 | return true;
|
---|
229 | ++i;
|
---|
230 | }
|
---|
231 | return false;
|
---|
232 | }
|
---|
233 |
|
---|
234 | /*!
|
---|
235 | \internal
|
---|
236 | Returns true if one or more spans intersect column \a column.
|
---|
237 | */
|
---|
238 | bool QTableViewPrivate::spansIntersectColumn(int column) const
|
---|
239 | {
|
---|
240 | QList<Span>::const_iterator it;
|
---|
241 | for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
|
---|
242 | Span span = *it;
|
---|
243 | if (spanContainsColumn(column, span.left(), span.width()))
|
---|
244 | return true;
|
---|
245 | }
|
---|
246 | return false;
|
---|
247 | }
|
---|
248 |
|
---|
249 | /*!
|
---|
250 | \internal
|
---|
251 | Returns true if one or more spans intersect row \a row.
|
---|
252 | */
|
---|
253 | bool QTableViewPrivate::spansIntersectRow(int row) const
|
---|
254 | {
|
---|
255 | QList<Span>::const_iterator it;
|
---|
256 | for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
|
---|
257 | Span span = *it;
|
---|
258 | if (spanContainsRow(row, span.top(), span.height()))
|
---|
259 | return true;
|
---|
260 | }
|
---|
261 | return false;
|
---|
262 | }
|
---|
263 |
|
---|
264 | /*!
|
---|
265 | \internal
|
---|
266 | Returns true if one or more spans intersect one or more columns.
|
---|
267 | */
|
---|
268 | bool QTableViewPrivate::spansIntersectColumns(const QList<int> &columns) const
|
---|
269 | {
|
---|
270 | QList<int>::const_iterator it;
|
---|
271 | for (it = columns.constBegin(); it != columns.constEnd(); ++it) {
|
---|
272 | if (spansIntersectColumn(*it))
|
---|
273 | return true;
|
---|
274 | }
|
---|
275 | return false;
|
---|
276 | }
|
---|
277 |
|
---|
278 | /*!
|
---|
279 | \internal
|
---|
280 | Returns true if one or more spans intersect one or more rows.
|
---|
281 | */
|
---|
282 | bool QTableViewPrivate::spansIntersectRows(const QList<int> &rows) const
|
---|
283 | {
|
---|
284 | QList<int>::const_iterator it;
|
---|
285 | for (it = rows.constBegin(); it != rows.constEnd(); ++it) {
|
---|
286 | if (spansIntersectRow(*it))
|
---|
287 | return true;
|
---|
288 | }
|
---|
289 | return false;
|
---|
290 | }
|
---|
291 |
|
---|
292 | /*!
|
---|
293 | \internal
|
---|
294 | Returns the visual rect for the given \a span.
|
---|
295 | */
|
---|
296 | QRect QTableViewPrivate::visualSpanRect(const Span &span) const
|
---|
297 | {
|
---|
298 | Q_Q(const QTableView);
|
---|
299 | // vertical
|
---|
300 | int row = span.top();
|
---|
301 | int rowp = verticalHeader->sectionViewportPosition(row);
|
---|
302 | int rowh = rowSpanHeight(row, span.height());
|
---|
303 | // horizontal
|
---|
304 | int column = span.left();
|
---|
305 | int colw = columnSpanWidth(column, span.width());
|
---|
306 | if (q->isRightToLeft())
|
---|
307 | column = span.right();
|
---|
308 | int colp = horizontalHeader->sectionViewportPosition(column);
|
---|
309 |
|
---|
310 | const int i = showGrid ? 1 : 0;
|
---|
311 | if (q->isRightToLeft())
|
---|
312 | return QRect(colp + i, rowp, colw - i, rowh - i);
|
---|
313 | return QRect(colp, rowp, colw - i, rowh - i);
|
---|
314 | }
|
---|
315 |
|
---|
316 | /*!
|
---|
317 | \internal
|
---|
318 | Draws the spanning cells within rect \a area, and clips them off as
|
---|
319 | preparation for the main drawing loop.
|
---|
320 | \a drawn is a QBitArray of visualRowCountxvisualCoulumnCount which say if particular cell has been drawn
|
---|
321 | */
|
---|
322 | void QTableViewPrivate::drawAndClipSpans(const QRect &area, QPainter *painter,
|
---|
323 | const QStyleOptionViewItemV4 &option, QBitArray *drawn,
|
---|
324 | int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn)
|
---|
325 | {
|
---|
326 | bool alternateBase = false;
|
---|
327 | QRegion region = viewport->rect();
|
---|
328 |
|
---|
329 | QList<Span>::const_iterator it;
|
---|
330 | for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
|
---|
331 | Span span = *it;
|
---|
332 |
|
---|
333 | int row = span.top();
|
---|
334 | int col = span.left();
|
---|
335 | if (isHidden(row, col))
|
---|
336 | continue;
|
---|
337 | QModelIndex index = model->index(row, col, root);
|
---|
338 | if (!index.isValid())
|
---|
339 | continue;
|
---|
340 | QRect rect = visualSpanRect(span);
|
---|
341 | rect.translate(scrollDelayOffset);
|
---|
342 | if (!rect.intersects(area))
|
---|
343 | continue;
|
---|
344 | QStyleOptionViewItemV4 opt = option;
|
---|
345 | opt.rect = rect;
|
---|
346 | alternateBase = alternatingColors && (span.top() & 1);
|
---|
347 | if (alternateBase)
|
---|
348 | opt.features |= QStyleOptionViewItemV2::Alternate;
|
---|
349 | else
|
---|
350 | opt.features &= ~QStyleOptionViewItemV2::Alternate;
|
---|
351 | drawCell(painter, opt, index);
|
---|
352 | region -= rect;
|
---|
353 | for (int r = span.top(); r <= span.bottom(); ++r) {
|
---|
354 | const int vr = visualRow(r);
|
---|
355 | if (vr < firstVisualRow || vr > lastVisualRow)
|
---|
356 | continue;
|
---|
357 | for (int c = span.left(); c <= span.right(); ++c) {
|
---|
358 | const int vc = visualColumn(c);
|
---|
359 | if (vc < firstVisualColumn || vc > lastVisualColumn)
|
---|
360 | continue;
|
---|
361 | drawn->setBit((vr - firstVisualRow) * (lastVisualColumn - firstVisualColumn + 1)
|
---|
362 | + vc - firstVisualColumn);
|
---|
363 | }
|
---|
364 | }
|
---|
365 |
|
---|
366 | }
|
---|
367 | painter->setClipRegion(region);
|
---|
368 | }
|
---|
369 |
|
---|
370 | /*!
|
---|
371 | \internal
|
---|
372 | Draws a table cell.
|
---|
373 | */
|
---|
374 | void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItemV4 &option, const QModelIndex &index)
|
---|
375 | {
|
---|
376 | Q_Q(QTableView);
|
---|
377 | QStyleOptionViewItemV4 opt = option;
|
---|
378 |
|
---|
379 | if (selectionModel && selectionModel->isSelected(index))
|
---|
380 | opt.state |= QStyle::State_Selected;
|
---|
381 | if (index == hover)
|
---|
382 | opt.state |= QStyle::State_MouseOver;
|
---|
383 | if (option.state & QStyle::State_Enabled) {
|
---|
384 | QPalette::ColorGroup cg;
|
---|
385 | if ((model->flags(index) & Qt::ItemIsEnabled) == 0) {
|
---|
386 | opt.state &= ~QStyle::State_Enabled;
|
---|
387 | cg = QPalette::Disabled;
|
---|
388 | } else {
|
---|
389 | cg = QPalette::Normal;
|
---|
390 | }
|
---|
391 | opt.palette.setCurrentColorGroup(cg);
|
---|
392 | }
|
---|
393 |
|
---|
394 | if (index == q->currentIndex()) {
|
---|
395 | const bool focus = (q->hasFocus() || viewport->hasFocus()) && q->currentIndex().isValid();
|
---|
396 | if (focus)
|
---|
397 | opt.state |= QStyle::State_HasFocus;
|
---|
398 | }
|
---|
399 |
|
---|
400 | if (opt.features & QStyleOptionViewItemV2::Alternate)
|
---|
401 | painter->fillRect(opt.rect, opt.palette.brush(QPalette::AlternateBase));
|
---|
402 |
|
---|
403 | if (const QWidget *widget = editorForIndex(index).editor) {
|
---|
404 | painter->save();
|
---|
405 | painter->setClipRect(widget->geometry());
|
---|
406 | q->itemDelegate(index)->paint(painter, opt, index);
|
---|
407 | painter->restore();
|
---|
408 | } else {
|
---|
409 | q->itemDelegate(index)->paint(painter, opt, index);
|
---|
410 | }
|
---|
411 | }
|
---|
412 |
|
---|
413 | /*!
|
---|
414 | \class QTableView
|
---|
415 |
|
---|
416 | \brief The QTableView class provides a default model/view
|
---|
417 | implementation of a table view.
|
---|
418 |
|
---|
419 | \ingroup model-view
|
---|
420 | \ingroup advanced
|
---|
421 | \mainclass
|
---|
422 |
|
---|
423 | A QTableView implements a table view that displays items from a
|
---|
424 | model. This class is used to provide standard tables that were
|
---|
425 | previously provided by the QTable class, but using the more
|
---|
426 | flexible approach provided by Qt's model/view architecture.
|
---|
427 |
|
---|
428 | The QTableView class is one of the \l{Model/View Classes}
|
---|
429 | and is part of Qt's \l{Model/View Programming}{model/view framework}.
|
---|
430 |
|
---|
431 | QTableView implements the interfaces defined by the
|
---|
432 | QAbstractItemView class to allow it to display data provided by
|
---|
433 | models derived from the QAbstractItemModel class.
|
---|
434 |
|
---|
435 | \section1 Navigation
|
---|
436 |
|
---|
437 | You can navigate the cells in the table by clicking on a cell with the
|
---|
438 | mouse, or by using the arrow keys. Because QTableView enables
|
---|
439 | \l{QAbstractItemView::tabKeyNavigation}{tabKeyNavigation} by default, you
|
---|
440 | can also hit Tab and Backtab to move from cell to cell.
|
---|
441 |
|
---|
442 | \section1 Visual Appearance
|
---|
443 |
|
---|
444 | The table has a vertical header that can be obtained using the
|
---|
445 | verticalHeader() function, and a horizontal header that is available
|
---|
446 | through the horizontalHeader() function. The height of each row in the
|
---|
447 | table can be found by using rowHeight(); similarly, the width of
|
---|
448 | columns can be found using columnWidth(). Since both of these are plain
|
---|
449 | widgets, you can hide either of them using their hide() functions.
|
---|
450 |
|
---|
451 | Rows and columns can be hidden and shown with hideRow(), hideColumn(),
|
---|
452 | showRow(), and showColumn(). They can be selected with selectRow()
|
---|
453 | and selectColumn(). The table will show a grid depending on the
|
---|
454 | \l showGrid property.
|
---|
455 |
|
---|
456 | The items shown in a table view, like those in the other item views, are
|
---|
457 | rendered and edited using standard \l{QItemDelegate}{delegates}. However,
|
---|
458 | for some tasks it is sometimes useful to be able to insert widgets in a
|
---|
459 | table instead. Widgets are set for particular indexes with the
|
---|
460 | \l{QAbstractItemView::}{setIndexWidget()} function, and
|
---|
461 | later retrieved with \l{QAbstractItemView::}{indexWidget()}.
|
---|
462 |
|
---|
463 | \table
|
---|
464 | \row \o \inlineimage qtableview-resized.png
|
---|
465 | \o By default, the cells in a table do not expand to fill the available space.
|
---|
466 |
|
---|
467 | You can make the cells fill the available space by stretching the last
|
---|
468 | header section. Access the relevant header using horizontalHeader()
|
---|
469 | or verticalHeader() and set the header's \l{QHeaderView::}{stretchLastSection}
|
---|
470 | property.
|
---|
471 |
|
---|
472 | To distribute the available space according to the space requirement of
|
---|
473 | each column or row, call the view's resizeColumnsToContents() or
|
---|
474 | resizeRowsToContents() functions.
|
---|
475 | \endtable
|
---|
476 |
|
---|
477 | \section1 Coordinate Systems
|
---|
478 |
|
---|
479 | For some specialized forms of tables it is useful to be able to
|
---|
480 | convert between row and column indexes and widget coordinates.
|
---|
481 | The rowAt() function provides the y-coordinate within the view of the
|
---|
482 | specified row; the row index can be used to obtain a corresponding
|
---|
483 | y-coordinate with rowViewportPosition(). The columnAt() and
|
---|
484 | columnViewportPosition() functions provide the equivalent conversion
|
---|
485 | operations between x-coordinates and column indexes.
|
---|
486 |
|
---|
487 | \section1 Styles
|
---|
488 |
|
---|
489 | QTableView is styled appropriately for each platform. The following images show
|
---|
490 | how it looks on three different platforms. Go to the \l{Qt Widget Gallery} to see
|
---|
491 | its appearance in other styles.
|
---|
492 |
|
---|
493 | \table 100%
|
---|
494 | \row \o \inlineimage windowsxp-tableview.png Screenshot of a Windows XP style table view
|
---|
495 | \o \inlineimage macintosh-tableview.png Screenshot of a Macintosh style table view
|
---|
496 | \o \inlineimage plastique-tableview.png Screenshot of a Plastique style table view
|
---|
497 | \row \o A \l{Windows XP Style Widget Gallery}{Windows XP style} table view.
|
---|
498 | \o A \l{Macintosh Style Widget Gallery}{Macintosh style} table view.
|
---|
499 | \o A \l{Plastique Style Widget Gallery}{Plastique style} table view.
|
---|
500 | \endtable
|
---|
501 |
|
---|
502 | \sa QTableWidget, {View Classes}, QAbstractItemModel, QAbstractItemView,
|
---|
503 | {Chart Example}, {Pixelator Example}, {Table Model Example}
|
---|
504 | */
|
---|
505 |
|
---|
506 | /*!
|
---|
507 | Constructs a table view with a \a parent to represent the data.
|
---|
508 |
|
---|
509 | \sa QAbstractItemModel
|
---|
510 | */
|
---|
511 |
|
---|
512 | QTableView::QTableView(QWidget *parent)
|
---|
513 | : QAbstractItemView(*new QTableViewPrivate, parent)
|
---|
514 | {
|
---|
515 | Q_D(QTableView);
|
---|
516 | d->init();
|
---|
517 | }
|
---|
518 |
|
---|
519 | /*!
|
---|
520 | \internal
|
---|
521 | */
|
---|
522 | QTableView::QTableView(QTableViewPrivate &dd, QWidget *parent)
|
---|
523 | : QAbstractItemView(dd, parent)
|
---|
524 | {
|
---|
525 | Q_D(QTableView);
|
---|
526 | d->init();
|
---|
527 | }
|
---|
528 |
|
---|
529 | /*!
|
---|
530 | Destroys the table view.
|
---|
531 | */
|
---|
532 | QTableView::~QTableView()
|
---|
533 | {
|
---|
534 | }
|
---|
535 |
|
---|
536 | /*!
|
---|
537 | \reimp
|
---|
538 | */
|
---|
539 | void QTableView::setModel(QAbstractItemModel *model)
|
---|
540 | {
|
---|
541 | Q_D(QTableView);
|
---|
542 | d->verticalHeader->setModel(model);
|
---|
543 | d->horizontalHeader->setModel(model);
|
---|
544 | QAbstractItemView::setModel(model);
|
---|
545 | }
|
---|
546 |
|
---|
547 | /*!
|
---|
548 | \reimp
|
---|
549 | */
|
---|
550 | void QTableView::setRootIndex(const QModelIndex &index)
|
---|
551 | {
|
---|
552 | Q_D(QTableView);
|
---|
553 | if (index == d->root) {
|
---|
554 | viewport()->update();
|
---|
555 | return;
|
---|
556 | }
|
---|
557 | d->verticalHeader->setRootIndex(index);
|
---|
558 | d->horizontalHeader->setRootIndex(index);
|
---|
559 | QAbstractItemView::setRootIndex(index);
|
---|
560 | }
|
---|
561 |
|
---|
562 | /*!
|
---|
563 | \reimp
|
---|
564 | */
|
---|
565 | void QTableView::setSelectionModel(QItemSelectionModel *selectionModel)
|
---|
566 | {
|
---|
567 | Q_D(QTableView);
|
---|
568 | Q_ASSERT(selectionModel);
|
---|
569 | d->verticalHeader->setSelectionModel(selectionModel);
|
---|
570 | d->horizontalHeader->setSelectionModel(selectionModel);
|
---|
571 | QAbstractItemView::setSelectionModel(selectionModel);
|
---|
572 | }
|
---|
573 |
|
---|
574 | /*!
|
---|
575 | Returns the table view's horizontal header.
|
---|
576 |
|
---|
577 | \sa setHorizontalHeader(), verticalHeader(), QAbstractItemModel::headerData()
|
---|
578 | */
|
---|
579 | QHeaderView *QTableView::horizontalHeader() const
|
---|
580 | {
|
---|
581 | Q_D(const QTableView);
|
---|
582 | return d->horizontalHeader;
|
---|
583 | }
|
---|
584 |
|
---|
585 | /*!
|
---|
586 | Returns the table view's vertical header.
|
---|
587 |
|
---|
588 | \sa setVerticalHeader(), horizontalHeader(), QAbstractItemModel::headerData()
|
---|
589 | */
|
---|
590 | QHeaderView *QTableView::verticalHeader() const
|
---|
591 | {
|
---|
592 | Q_D(const QTableView);
|
---|
593 | return d->verticalHeader;
|
---|
594 | }
|
---|
595 |
|
---|
596 | /*!
|
---|
597 | Sets the widget to use for the horizontal header to \a header.
|
---|
598 |
|
---|
599 | \sa horizontalHeader() setVerticalHeader()
|
---|
600 | */
|
---|
601 | void QTableView::setHorizontalHeader(QHeaderView *header)
|
---|
602 | {
|
---|
603 | Q_D(QTableView);
|
---|
604 |
|
---|
605 | if (!header || header == d->horizontalHeader)
|
---|
606 | return;
|
---|
607 | if (d->horizontalHeader && d->horizontalHeader->parent() == this)
|
---|
608 | delete d->horizontalHeader;
|
---|
609 | d->horizontalHeader = header;
|
---|
610 | d->horizontalHeader->setParent(this);
|
---|
611 | if (!d->horizontalHeader->model()) {
|
---|
612 | d->horizontalHeader->setModel(d->model);
|
---|
613 | if (d->selectionModel)
|
---|
614 | d->horizontalHeader->setSelectionModel(d->selectionModel);
|
---|
615 | }
|
---|
616 |
|
---|
617 | connect(d->horizontalHeader,SIGNAL(sectionResized(int,int,int)),
|
---|
618 | this, SLOT(columnResized(int,int,int)));
|
---|
619 | connect(d->horizontalHeader, SIGNAL(sectionMoved(int,int,int)),
|
---|
620 | this, SLOT(columnMoved(int,int,int)));
|
---|
621 | connect(d->horizontalHeader, SIGNAL(sectionCountChanged(int,int)),
|
---|
622 | this, SLOT(columnCountChanged(int,int)));
|
---|
623 | connect(d->horizontalHeader, SIGNAL(sectionPressed(int)), this, SLOT(selectColumn(int)));
|
---|
624 | connect(d->horizontalHeader, SIGNAL(sectionEntered(int)), this, SLOT(_q_selectColumn(int)));
|
---|
625 | connect(d->horizontalHeader, SIGNAL(sectionHandleDoubleClicked(int)),
|
---|
626 | this, SLOT(resizeColumnToContents(int)));
|
---|
627 | connect(d->horizontalHeader, SIGNAL(geometriesChanged()), this, SLOT(updateGeometries()));
|
---|
628 | }
|
---|
629 |
|
---|
630 | /*!
|
---|
631 | Sets the widget to use for the vertical header to \a header.
|
---|
632 |
|
---|
633 | \sa verticalHeader() setHorizontalHeader()
|
---|
634 | */
|
---|
635 | void QTableView::setVerticalHeader(QHeaderView *header)
|
---|
636 | {
|
---|
637 | Q_D(QTableView);
|
---|
638 |
|
---|
639 | if (!header || header == d->verticalHeader)
|
---|
640 | return;
|
---|
641 | if (d->verticalHeader && d->verticalHeader->parent() == this)
|
---|
642 | delete d->verticalHeader;
|
---|
643 | d->verticalHeader = header;
|
---|
644 | d->verticalHeader->setParent(this);
|
---|
645 | if (!d->verticalHeader->model()) {
|
---|
646 | d->verticalHeader->setModel(d->model);
|
---|
647 | if (d->selectionModel)
|
---|
648 | d->verticalHeader->setSelectionModel(d->selectionModel);
|
---|
649 | }
|
---|
650 |
|
---|
651 | connect(d->verticalHeader, SIGNAL(sectionResized(int,int,int)),
|
---|
652 | this, SLOT(rowResized(int,int,int)));
|
---|
653 | connect(d->verticalHeader, SIGNAL(sectionMoved(int,int,int)),
|
---|
654 | this, SLOT(rowMoved(int,int,int)));
|
---|
655 | connect(d->verticalHeader, SIGNAL(sectionCountChanged(int,int)),
|
---|
656 | this, SLOT(rowCountChanged(int,int)));
|
---|
657 | connect(d->verticalHeader, SIGNAL(sectionPressed(int)), this, SLOT(selectRow(int)));
|
---|
658 | connect(d->verticalHeader, SIGNAL(sectionEntered(int)), this, SLOT(_q_selectRow(int)));
|
---|
659 | connect(d->verticalHeader, SIGNAL(sectionHandleDoubleClicked(int)),
|
---|
660 | this, SLOT(resizeRowToContents(int)));
|
---|
661 | connect(d->verticalHeader, SIGNAL(geometriesChanged()), this, SLOT(updateGeometries()));
|
---|
662 | }
|
---|
663 |
|
---|
664 | /*!
|
---|
665 | \internal
|
---|
666 |
|
---|
667 | Scroll the contents of the table view by (\a dx, \a dy).
|
---|
668 | */
|
---|
669 | void QTableView::scrollContentsBy(int dx, int dy)
|
---|
670 | {
|
---|
671 | Q_D(QTableView);
|
---|
672 |
|
---|
673 | d->delayedAutoScroll.stop(); // auto scroll was canceled by the user scrolling
|
---|
674 |
|
---|
675 | dx = isRightToLeft() ? -dx : dx;
|
---|
676 | if (dx) {
|
---|
677 | if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
|
---|
678 | int oldOffset = d->horizontalHeader->offset();
|
---|
679 | if (horizontalScrollBar()->value() == horizontalScrollBar()->maximum())
|
---|
680 | d->horizontalHeader->setOffsetToLastSection();
|
---|
681 | else
|
---|
682 | d->horizontalHeader->setOffsetToSectionPosition(horizontalScrollBar()->value());
|
---|
683 | int newOffset = d->horizontalHeader->offset();
|
---|
684 | dx = isRightToLeft() ? newOffset - oldOffset : oldOffset - newOffset;
|
---|
685 | } else {
|
---|
686 | d->horizontalHeader->setOffset(horizontalScrollBar()->value());
|
---|
687 | }
|
---|
688 | }
|
---|
689 | if (dy) {
|
---|
690 | if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
|
---|
691 | int oldOffset = d->verticalHeader->offset();
|
---|
692 | if (verticalScrollBar()->value() == verticalScrollBar()->maximum())
|
---|
693 | d->verticalHeader->setOffsetToLastSection();
|
---|
694 | else
|
---|
695 | d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
|
---|
696 | int newOffset = d->verticalHeader->offset();
|
---|
697 | dy = oldOffset - newOffset;
|
---|
698 | } else {
|
---|
699 | d->verticalHeader->setOffset(verticalScrollBar()->value());
|
---|
700 | }
|
---|
701 | }
|
---|
702 | d->scrollContentsBy(dx, dy);
|
---|
703 |
|
---|
704 | if (d->showGrid) {
|
---|
705 | //we need to update the first line of the previous top item in the view
|
---|
706 | //because it has the grid drawn if the header is invisible.
|
---|
707 | //It is strictly related to what's done at then end of the paintEvent
|
---|
708 | if (dy > 0 && d->horizontalHeader->isHidden() && d->verticalScrollMode == ScrollPerItem) {
|
---|
709 | d->viewport->update(0, dy, d->viewport->width(), dy);
|
---|
710 | }
|
---|
711 | if (dx > 0 && d->verticalHeader->isHidden() && d->horizontalScrollMode == ScrollPerItem) {
|
---|
712 | d->viewport->update(dx, 0, dx, d->viewport->height());
|
---|
713 | }
|
---|
714 | }
|
---|
715 | }
|
---|
716 |
|
---|
717 | /*!
|
---|
718 | \reimp
|
---|
719 | */
|
---|
720 | QStyleOptionViewItem QTableView::viewOptions() const
|
---|
721 | {
|
---|
722 | QStyleOptionViewItem option = QAbstractItemView::viewOptions();
|
---|
723 | option.showDecorationSelected = true;
|
---|
724 | return option;
|
---|
725 | }
|
---|
726 |
|
---|
727 | /*!
|
---|
728 | Paints the table on receipt of the given paint event \a event.
|
---|
729 | */
|
---|
730 | void QTableView::paintEvent(QPaintEvent *event)
|
---|
731 | {
|
---|
732 | Q_D(QTableView);
|
---|
733 | // setup temp variables for the painting
|
---|
734 | QStyleOptionViewItemV4 option = d->viewOptionsV4();
|
---|
735 | const QPoint offset = d->scrollDelayOffset;
|
---|
736 | const bool showGrid = d->showGrid;
|
---|
737 | const int gridSize = showGrid ? 1 : 0;
|
---|
738 | const int gridHint = style()->styleHint(QStyle::SH_Table_GridLineColor, &option, this);
|
---|
739 | const QColor gridColor = static_cast<QRgb>(gridHint);
|
---|
740 | const QPen gridPen = QPen(gridColor, 0, d->gridStyle);
|
---|
741 | const QHeaderView *verticalHeader = d->verticalHeader;
|
---|
742 | const QHeaderView *horizontalHeader = d->horizontalHeader;
|
---|
743 | const QStyle::State state = option.state;
|
---|
744 | const bool alternate = d->alternatingColors;
|
---|
745 | const bool rightToLeft = isRightToLeft();
|
---|
746 |
|
---|
747 | QPainter painter(d->viewport);
|
---|
748 |
|
---|
749 | // if there's nothing to do, clear the area and return
|
---|
750 | if (horizontalHeader->count() == 0 || verticalHeader->count() == 0 || !d->itemDelegate)
|
---|
751 | return;
|
---|
752 |
|
---|
753 | uint x = horizontalHeader->length() - horizontalHeader->offset() - (rightToLeft ? 0 : 1);
|
---|
754 | uint y = verticalHeader->length() - verticalHeader->offset() - 1;
|
---|
755 |
|
---|
756 | QVector<QRect> rects = event->region().rects();
|
---|
757 |
|
---|
758 | //firstVisualRow is the visual index of the first visible row. lastVisualRow is the visual index of the last visible Row.
|
---|
759 | //same goes for ...VisualColumn
|
---|
760 | int firstVisualRow = qMax(verticalHeader->visualIndexAt(0),0);
|
---|
761 | int lastVisualRow = verticalHeader->visualIndexAt(verticalHeader->viewport()->height());
|
---|
762 | if (lastVisualRow == -1)
|
---|
763 | lastVisualRow = d->model->rowCount(d->root) - 1;
|
---|
764 |
|
---|
765 | int firstVisualColumn = horizontalHeader->visualIndexAt(0);
|
---|
766 | int lastVisualColumn = horizontalHeader->visualIndexAt(horizontalHeader->viewport()->width());
|
---|
767 | if (rightToLeft)
|
---|
768 | qSwap(firstVisualColumn, lastVisualColumn);
|
---|
769 | if (firstVisualColumn == -1)
|
---|
770 | firstVisualColumn = 0;
|
---|
771 | if (lastVisualColumn == -1)
|
---|
772 | lastVisualColumn = horizontalHeader->count() - 1;
|
---|
773 |
|
---|
774 | QBitArray drawn((lastVisualRow - firstVisualRow + 1) * (lastVisualColumn - firstVisualColumn + 1));
|
---|
775 |
|
---|
776 | for (int i = 0; i < rects.size(); ++i) {
|
---|
777 | QRect dirtyArea = rects.at(i);
|
---|
778 | dirtyArea.translate(offset);
|
---|
779 | dirtyArea.setBottom(qMin(dirtyArea.bottom(), int(y)));
|
---|
780 | if (rightToLeft) {
|
---|
781 | dirtyArea.setLeft(qMax(dirtyArea.left(), d->viewport->width() - int(x)));
|
---|
782 | } else {
|
---|
783 | dirtyArea.setRight(qMin(dirtyArea.right(), int(x)));
|
---|
784 | }
|
---|
785 |
|
---|
786 | if (d->hasSpans())
|
---|
787 | d->drawAndClipSpans(dirtyArea, &painter, option, &drawn,
|
---|
788 | firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn);
|
---|
789 |
|
---|
790 | // get the horizontal start and end visual sections
|
---|
791 | int left = horizontalHeader->visualIndexAt(dirtyArea.left());
|
---|
792 | int right = horizontalHeader->visualIndexAt(dirtyArea.right());
|
---|
793 | if (rightToLeft)
|
---|
794 | qSwap(left, right);
|
---|
795 | if (left == -1) left = 0;
|
---|
796 | if (right == -1) right = horizontalHeader->count() - 1;
|
---|
797 |
|
---|
798 | // get the vertical start and end visual sections and if alternate color
|
---|
799 | int bottom = verticalHeader->visualIndexAt(dirtyArea.bottom());
|
---|
800 | if (bottom == -1) bottom = verticalHeader->count() - 1;
|
---|
801 | int top = 0;
|
---|
802 | bool alternateBase = false;
|
---|
803 | if (alternate && verticalHeader->sectionsHidden()) {
|
---|
804 | uint verticalOffset = verticalHeader->offset();
|
---|
805 | int row = verticalHeader->logicalIndex(top);
|
---|
806 | for (int y = 0;
|
---|
807 | ((uint)(y += verticalHeader->sectionSize(top)) <= verticalOffset) && (top < bottom);
|
---|
808 | ++top) {
|
---|
809 | row = verticalHeader->logicalIndex(top);
|
---|
810 | if (alternate && !verticalHeader->isSectionHidden(row))
|
---|
811 | alternateBase = !alternateBase;
|
---|
812 | }
|
---|
813 | } else {
|
---|
814 | top = verticalHeader->visualIndexAt(dirtyArea.top());
|
---|
815 | alternateBase = (top & 1) && alternate;
|
---|
816 | }
|
---|
817 | if (top == -1 || top > bottom)
|
---|
818 | continue;
|
---|
819 |
|
---|
820 | // Paint each row item
|
---|
821 | for (int visualRowIndex = top; visualRowIndex <= bottom; ++visualRowIndex) {
|
---|
822 | int row = verticalHeader->logicalIndex(visualRowIndex);
|
---|
823 | if (verticalHeader->isSectionHidden(row))
|
---|
824 | continue;
|
---|
825 | int rowY = rowViewportPosition(row);
|
---|
826 | rowY += offset.y();
|
---|
827 | int rowh = rowHeight(row) - gridSize;
|
---|
828 |
|
---|
829 | // Paint each column item
|
---|
830 | for (int visualColumnIndex = left; visualColumnIndex <= right; ++visualColumnIndex) {
|
---|
831 | int currentBit = (visualRowIndex - firstVisualRow) * (lastVisualColumn - firstVisualColumn + 1)
|
---|
832 | + visualColumnIndex - firstVisualColumn;
|
---|
833 |
|
---|
834 | if (currentBit < 0 || currentBit >= drawn.size() || drawn.testBit(currentBit))
|
---|
835 | continue;
|
---|
836 | drawn.setBit(currentBit);
|
---|
837 |
|
---|
838 | int col = horizontalHeader->logicalIndex(visualColumnIndex);
|
---|
839 | if (horizontalHeader->isSectionHidden(col))
|
---|
840 | continue;
|
---|
841 | int colp = columnViewportPosition(col);
|
---|
842 | colp += offset.x();
|
---|
843 | int colw = columnWidth(col) - gridSize;
|
---|
844 |
|
---|
845 | const QModelIndex index = d->model->index(row, col, d->root);
|
---|
846 | if (index.isValid()) {
|
---|
847 | option.rect = QRect(colp + (showGrid && rightToLeft ? 1 : 0), rowY, colw, rowh);
|
---|
848 | if (alternate) {
|
---|
849 | if (alternateBase)
|
---|
850 | option.features |= QStyleOptionViewItemV2::Alternate;
|
---|
851 | else
|
---|
852 | option.features &= ~QStyleOptionViewItemV2::Alternate;
|
---|
853 | }
|
---|
854 | d->drawCell(&painter, option, index);
|
---|
855 | }
|
---|
856 | }
|
---|
857 | alternateBase = !alternateBase && alternate;
|
---|
858 | }
|
---|
859 |
|
---|
860 | if (showGrid) {
|
---|
861 | // Find the bottom right (the last rows/coloumns might be hidden)
|
---|
862 | while (verticalHeader->isSectionHidden(verticalHeader->logicalIndex(bottom))) --bottom;
|
---|
863 | QPen old = painter.pen();
|
---|
864 | painter.setPen(gridPen);
|
---|
865 | // Paint each row
|
---|
866 | for (int visualIndex = top; visualIndex <= bottom; ++visualIndex) {
|
---|
867 | int row = verticalHeader->logicalIndex(visualIndex);
|
---|
868 | if (verticalHeader->isSectionHidden(row))
|
---|
869 | continue;
|
---|
870 | int rowY = rowViewportPosition(row);
|
---|
871 | rowY += offset.y();
|
---|
872 | int rowh = rowHeight(row) - gridSize;
|
---|
873 | painter.drawLine(dirtyArea.left(), rowY + rowh, dirtyArea.right(), rowY + rowh);
|
---|
874 | }
|
---|
875 |
|
---|
876 | // Paint each column
|
---|
877 | for (int h = left; h <= right; ++h) {
|
---|
878 | int col = horizontalHeader->logicalIndex(h);
|
---|
879 | if (horizontalHeader->isSectionHidden(col))
|
---|
880 | continue;
|
---|
881 | int colp = columnViewportPosition(col);
|
---|
882 | colp += offset.x();
|
---|
883 | if (!rightToLeft)
|
---|
884 | colp += columnWidth(col) - gridSize;
|
---|
885 | painter.drawLine(colp, dirtyArea.top(), colp, dirtyArea.bottom());
|
---|
886 | }
|
---|
887 |
|
---|
888 | //draw the top & left grid lines if the headers are not visible.
|
---|
889 | //We do update this line when subsequent scroll happen (see scrollContentsBy)
|
---|
890 | if (horizontalHeader->isHidden() && verticalScrollMode() == ScrollPerItem)
|
---|
891 | painter.drawLine(dirtyArea.left(), 0, dirtyArea.right(), 0);
|
---|
892 | if (verticalHeader->isHidden() && horizontalScrollMode() == ScrollPerItem)
|
---|
893 | painter.drawLine(0, dirtyArea.top(), 0, dirtyArea.bottom());
|
---|
894 | painter.setPen(old);
|
---|
895 | }
|
---|
896 | }
|
---|
897 |
|
---|
898 | #ifndef QT_NO_DRAGANDDROP
|
---|
899 | // Paint the dropIndicator
|
---|
900 | d->paintDropIndicator(&painter);
|
---|
901 | #endif
|
---|
902 | }
|
---|
903 |
|
---|
904 | /*!
|
---|
905 | Returns the index position of the model item corresponding to the
|
---|
906 | table item at position \a pos in contents coordinates.
|
---|
907 | */
|
---|
908 | QModelIndex QTableView::indexAt(const QPoint &pos) const
|
---|
909 | {
|
---|
910 | Q_D(const QTableView);
|
---|
911 | d->executePostedLayout();
|
---|
912 | int r = rowAt(pos.y());
|
---|
913 | int c = columnAt(pos.x());
|
---|
914 | if (r >= 0 && c >= 0) {
|
---|
915 | if (d->hasSpans()) {
|
---|
916 | QTableViewPrivate::Span span = d->span(r, c);
|
---|
917 | r = span.top();
|
---|
918 | c = span.left();
|
---|
919 | }
|
---|
920 | return d->model->index(r, c, d->root);
|
---|
921 | }
|
---|
922 | return QModelIndex();
|
---|
923 | }
|
---|
924 |
|
---|
925 | /*!
|
---|
926 | Returns the horizontal offset of the items in the table view.
|
---|
927 |
|
---|
928 | Note that the table view uses the horizontal header section
|
---|
929 | positions to determine the positions of columns in the view.
|
---|
930 |
|
---|
931 | \sa verticalOffset()
|
---|
932 | */
|
---|
933 | int QTableView::horizontalOffset() const
|
---|
934 | {
|
---|
935 | Q_D(const QTableView);
|
---|
936 | return d->horizontalHeader->offset();
|
---|
937 | }
|
---|
938 |
|
---|
939 | /*!
|
---|
940 | Returns the vertical offset of the items in the table view.
|
---|
941 |
|
---|
942 | Note that the table view uses the vertical header section
|
---|
943 | positions to determine the positions of rows in the view.
|
---|
944 |
|
---|
945 | \sa horizontalOffset()
|
---|
946 | */
|
---|
947 | int QTableView::verticalOffset() const
|
---|
948 | {
|
---|
949 | Q_D(const QTableView);
|
---|
950 | return d->verticalHeader->offset();
|
---|
951 | }
|
---|
952 |
|
---|
953 | /*!
|
---|
954 | \fn QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
|
---|
955 |
|
---|
956 | Moves the cursor in accordance with the given \a cursorAction, using the
|
---|
957 | information provided by the \a modifiers.
|
---|
958 |
|
---|
959 | \sa QAbstractItemView::CursorAction
|
---|
960 | */
|
---|
961 | QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
|
---|
962 | {
|
---|
963 | Q_D(QTableView);
|
---|
964 | Q_UNUSED(modifiers);
|
---|
965 |
|
---|
966 | int bottom = d->model->rowCount(d->root) - 1;
|
---|
967 | // make sure that bottom is the bottommost *visible* row
|
---|
968 | while (bottom >= 0 && isRowHidden(d->logicalRow(bottom)))
|
---|
969 | --bottom;
|
---|
970 |
|
---|
971 | int right = d->model->columnCount(d->root) - 1;
|
---|
972 |
|
---|
973 | while (right >= 0 && isColumnHidden(d->logicalColumn(right)))
|
---|
974 | --right;
|
---|
975 |
|
---|
976 | if (bottom == -1 || right == -1)
|
---|
977 | return QModelIndex(); // model is empty
|
---|
978 |
|
---|
979 | QModelIndex current = currentIndex();
|
---|
980 |
|
---|
981 | if (!current.isValid()) {
|
---|
982 | int row = 0;
|
---|
983 | int column = 0;
|
---|
984 | while (column < right && isColumnHidden(d->logicalColumn(column)))
|
---|
985 | ++column;
|
---|
986 | while (isRowHidden(d->logicalRow(row)) && row < bottom)
|
---|
987 | ++row;
|
---|
988 | return d->model->index(d->logicalRow(row), d->logicalColumn(column), d->root);
|
---|
989 | }
|
---|
990 |
|
---|
991 | int visualRow = d->visualRow(current.row());
|
---|
992 | Q_ASSERT(visualRow != -1);
|
---|
993 | int visualColumn = d->visualColumn(current.column());
|
---|
994 | Q_ASSERT(visualColumn != -1);
|
---|
995 |
|
---|
996 | if (isRightToLeft()) {
|
---|
997 | if (cursorAction == MoveLeft)
|
---|
998 | cursorAction = MoveRight;
|
---|
999 | else if (cursorAction == MoveRight)
|
---|
1000 | cursorAction = MoveLeft;
|
---|
1001 | }
|
---|
1002 |
|
---|
1003 | switch (cursorAction) {
|
---|
1004 | case MoveUp:
|
---|
1005 | #ifdef QT_KEYPAD_NAVIGATION
|
---|
1006 | if (QApplication::keypadNavigationEnabled() && visualRow == 0)
|
---|
1007 | visualRow = d->visualRow(model()->rowCount() - 1) + 1;
|
---|
1008 | #endif
|
---|
1009 | --visualRow;
|
---|
1010 | while (visualRow > 0 && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn))
|
---|
1011 | --visualRow;
|
---|
1012 | if (d->hasSpans()) {
|
---|
1013 | int row = d->logicalRow(visualRow);
|
---|
1014 | QTableViewPrivate::Span span = d->span(row, current.column());
|
---|
1015 | visualRow = d->visualRow(span.top());
|
---|
1016 | visualColumn = d->visualColumn(span.left());
|
---|
1017 | }
|
---|
1018 | break;
|
---|
1019 | case MoveDown:
|
---|
1020 | if (d->hasSpans()) {
|
---|
1021 | QTableViewPrivate::Span span = d->span(current.row(), current.column());
|
---|
1022 | visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
|
---|
1023 | }
|
---|
1024 | #ifdef QT_KEYPAD_NAVIGATION
|
---|
1025 | if (QApplication::keypadNavigationEnabled() && visualRow >= bottom)
|
---|
1026 | visualRow = -1;
|
---|
1027 | #endif
|
---|
1028 | ++visualRow;
|
---|
1029 | while (visualRow < bottom && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn))
|
---|
1030 | ++visualRow;
|
---|
1031 | if (d->hasSpans()) {
|
---|
1032 | int row = d->logicalRow(visualRow);
|
---|
1033 | QTableViewPrivate::Span span = d->span(row, current.column());
|
---|
1034 | visualColumn = d->visualColumn(span.left());
|
---|
1035 | }
|
---|
1036 | break;
|
---|
1037 | case MovePrevious: {
|
---|
1038 | int left = 0;
|
---|
1039 | while (d->isVisualColumnHiddenOrDisabled(visualRow, left) && left < right)
|
---|
1040 | ++left;
|
---|
1041 | if (visualColumn == left) {
|
---|
1042 | visualColumn = right;
|
---|
1043 | int top = 0;
|
---|
1044 | while (top < bottom && d->isVisualRowHiddenOrDisabled(top, visualColumn))
|
---|
1045 | ++top;
|
---|
1046 | if (visualRow == top)
|
---|
1047 | visualRow = bottom;
|
---|
1048 | else
|
---|
1049 | --visualRow;
|
---|
1050 | while (visualRow > 0 && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn))
|
---|
1051 | --visualRow;
|
---|
1052 | break;
|
---|
1053 | } // else MoveLeft
|
---|
1054 | }
|
---|
1055 | case MoveLeft:
|
---|
1056 | --visualColumn;
|
---|
1057 | while (visualColumn > 0 && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn))
|
---|
1058 | --visualColumn;
|
---|
1059 | if (d->hasSpans()) {
|
---|
1060 | int column = d->logicalColumn(visualColumn);
|
---|
1061 | QTableViewPrivate::Span span = d->span(current.row(), column);
|
---|
1062 | visualRow = d->visualRow(span.top());
|
---|
1063 | visualColumn = d->visualColumn(span.left());
|
---|
1064 | }
|
---|
1065 | break;
|
---|
1066 | case MoveNext:
|
---|
1067 | if (visualColumn == right) {
|
---|
1068 | visualColumn = 0;
|
---|
1069 | while (visualColumn < right && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn))
|
---|
1070 | ++visualColumn;
|
---|
1071 | if (visualRow == bottom)
|
---|
1072 | visualRow = 0;
|
---|
1073 | else
|
---|
1074 | ++visualRow;
|
---|
1075 | while (visualRow < bottom && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn))
|
---|
1076 | ++visualRow;
|
---|
1077 | break;
|
---|
1078 | } // else MoveRight
|
---|
1079 | case MoveRight:
|
---|
1080 | if (d->hasSpans()) {
|
---|
1081 | QTableViewPrivate::Span span = d->span(current.row(), current.column());
|
---|
1082 | visualColumn = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width()));
|
---|
1083 | }
|
---|
1084 | ++visualColumn;
|
---|
1085 | while (visualColumn < right && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn))
|
---|
1086 | ++visualColumn;
|
---|
1087 | if (d->hasSpans()) {
|
---|
1088 | int column = d->logicalColumn(visualColumn);
|
---|
1089 | QTableViewPrivate::Span span = d->span(current.row(), column);
|
---|
1090 | visualRow = d->visualRow(span.top());
|
---|
1091 | }
|
---|
1092 | break;
|
---|
1093 | case MoveHome:
|
---|
1094 | visualColumn = 0;
|
---|
1095 | while (visualColumn < right && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn))
|
---|
1096 | ++visualColumn;
|
---|
1097 | if (modifiers & Qt::ControlModifier) {
|
---|
1098 | visualRow = 0;
|
---|
1099 | while (visualRow < bottom && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn))
|
---|
1100 | ++visualRow;
|
---|
1101 | }
|
---|
1102 | break;
|
---|
1103 | case MoveEnd:
|
---|
1104 | visualColumn = right;
|
---|
1105 | if (modifiers & Qt::ControlModifier)
|
---|
1106 | visualRow = bottom;
|
---|
1107 | break;
|
---|
1108 | case MovePageUp: {
|
---|
1109 | int top = 0;
|
---|
1110 | while (top < bottom && d->isVisualRowHiddenOrDisabled(top, visualColumn))
|
---|
1111 | ++top;
|
---|
1112 | int newRow = qMax(rowAt(visualRect(current).top() - d->viewport->height()), top);
|
---|
1113 | return d->model->index(qBound(0, newRow, bottom), current.column(), d->root);
|
---|
1114 | }
|
---|
1115 | case MovePageDown: {
|
---|
1116 | int newRow = qMin(rowAt(visualRect(current).bottom() + d->viewport->height()), bottom);
|
---|
1117 | if (newRow < 0)
|
---|
1118 | newRow = bottom;
|
---|
1119 | return d->model->index(qBound(0, newRow, bottom), current.column(), d->root);
|
---|
1120 | }}
|
---|
1121 |
|
---|
1122 | int logicalRow = d->logicalRow(visualRow);
|
---|
1123 | int logicalColumn = d->logicalColumn(visualColumn);
|
---|
1124 | if (!d->model->hasIndex(logicalRow, logicalColumn, d->root))
|
---|
1125 | return QModelIndex();
|
---|
1126 |
|
---|
1127 | QModelIndex result = d->model->index(logicalRow, logicalColumn, d->root);
|
---|
1128 | if (!isIndexHidden(result) && d->isIndexEnabled(result))
|
---|
1129 | return d->model->index(logicalRow, logicalColumn, d->root);
|
---|
1130 |
|
---|
1131 | return QModelIndex();
|
---|
1132 | }
|
---|
1133 |
|
---|
1134 | /*!
|
---|
1135 | \fn void QTableView::setSelection(const QRect &rect,
|
---|
1136 | QItemSelectionModel::SelectionFlags flags)
|
---|
1137 |
|
---|
1138 | Selects the items within the given \a rect and in accordance with
|
---|
1139 | the specified selection \a flags.
|
---|
1140 | */
|
---|
1141 | void QTableView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
|
---|
1142 | {
|
---|
1143 | Q_D(QTableView);
|
---|
1144 | QModelIndex tl = indexAt(QPoint(isRightToLeft() ? qMax(rect.left(), rect.right())
|
---|
1145 | : qMin(rect.left(), rect.right()), qMin(rect.top(), rect.bottom())));
|
---|
1146 | QModelIndex br = indexAt(QPoint(isRightToLeft() ? qMin(rect.left(), rect.right()) :
|
---|
1147 | qMax(rect.left(), rect.right()), qMax(rect.top(), rect.bottom())));
|
---|
1148 | if (!d->selectionModel || !tl.isValid() || !br.isValid() || !d->isIndexEnabled(tl) || !d->isIndexEnabled(br))
|
---|
1149 | return;
|
---|
1150 |
|
---|
1151 | bool verticalMoved = verticalHeader()->sectionsMoved();
|
---|
1152 | bool horizontalMoved = horizontalHeader()->sectionsMoved();
|
---|
1153 |
|
---|
1154 | QItemSelection selection;
|
---|
1155 |
|
---|
1156 | if (d->hasSpans()) {
|
---|
1157 | bool expanded;
|
---|
1158 | int top = qMin(d->visualRow(tl.row()), d->visualRow(br.row()));
|
---|
1159 | int left = qMin(d->visualColumn(tl.column()), d->visualColumn(br.column()));
|
---|
1160 | int bottom = qMax(d->visualRow(tl.row()), d->visualRow(br.row()));
|
---|
1161 | int right = qMax(d->visualColumn(tl.column()), d->visualColumn(br.column()));
|
---|
1162 | do {
|
---|
1163 | expanded = false;
|
---|
1164 | QList<QTableViewPrivate::Span>::const_iterator it;
|
---|
1165 | for (it = d->spans.constBegin(); it != d->spans.constEnd(); ++it) {
|
---|
1166 | QTableViewPrivate::Span span = *it;
|
---|
1167 | int t = d->visualRow(span.top());
|
---|
1168 | int l = d->visualColumn(span.left());
|
---|
1169 | int b = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
|
---|
1170 | int r = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width()));
|
---|
1171 | if ((t > bottom) || (l > right) || (top > b) || (left > r))
|
---|
1172 | continue; // no intersect
|
---|
1173 | if (t < top) {
|
---|
1174 | top = t;
|
---|
1175 | expanded = true;
|
---|
1176 | }
|
---|
1177 | if (l < left) {
|
---|
1178 | left = l;
|
---|
1179 | expanded = true;
|
---|
1180 | }
|
---|
1181 | if (b > bottom) {
|
---|
1182 | bottom = b;
|
---|
1183 | expanded = true;
|
---|
1184 | }
|
---|
1185 | if (r > right) {
|
---|
1186 | right = r;
|
---|
1187 | expanded = true;
|
---|
1188 | }
|
---|
1189 | if (expanded)
|
---|
1190 | break;
|
---|
1191 | }
|
---|
1192 | } while (expanded);
|
---|
1193 | for (int horizontal = left; horizontal <= right; ++horizontal) {
|
---|
1194 | int column = d->logicalColumn(horizontal);
|
---|
1195 | for (int vertical = top; vertical <= bottom; ++vertical) {
|
---|
1196 | int row = d->logicalRow(vertical);
|
---|
1197 | QModelIndex index = d->model->index(row, column, d->root);
|
---|
1198 | selection.append(QItemSelectionRange(index));
|
---|
1199 | }
|
---|
1200 | }
|
---|
1201 | } else if (verticalMoved && horizontalMoved) {
|
---|
1202 | int top = d->visualRow(tl.row());
|
---|
1203 | int left = d->visualColumn(tl.column());
|
---|
1204 | int bottom = d->visualRow(br.row());
|
---|
1205 | int right = d->visualColumn(br.column());
|
---|
1206 | for (int horizontal = left; horizontal <= right; ++horizontal) {
|
---|
1207 | int column = d->logicalColumn(horizontal);
|
---|
1208 | for (int vertical = top; vertical <= bottom; ++vertical) {
|
---|
1209 | int row = d->logicalRow(vertical);
|
---|
1210 | QModelIndex index = d->model->index(row, column, d->root);
|
---|
1211 | selection.append(QItemSelectionRange(index));
|
---|
1212 | }
|
---|
1213 | }
|
---|
1214 | } else if (horizontalMoved) {
|
---|
1215 | int left = d->visualColumn(tl.column());
|
---|
1216 | int right = d->visualColumn(br.column());
|
---|
1217 | for (int visual = left; visual <= right; ++visual) {
|
---|
1218 | int column = d->logicalColumn(visual);
|
---|
1219 | QModelIndex topLeft = d->model->index(tl.row(), column, d->root);
|
---|
1220 | QModelIndex bottomRight = d->model->index(br.row(), column, d->root);
|
---|
1221 | selection.append(QItemSelectionRange(topLeft, bottomRight));
|
---|
1222 | }
|
---|
1223 | } else if (verticalMoved) {
|
---|
1224 | int top = d->visualRow(tl.row());
|
---|
1225 | int bottom = d->visualRow(br.row());
|
---|
1226 | for (int visual = top; visual <= bottom; ++visual) {
|
---|
1227 | int row = d->logicalRow(visual);
|
---|
1228 | QModelIndex topLeft = d->model->index(row, tl.column(), d->root);
|
---|
1229 | QModelIndex bottomRight = d->model->index(row, br.column(), d->root);
|
---|
1230 | selection.append(QItemSelectionRange(topLeft, bottomRight));
|
---|
1231 | }
|
---|
1232 | } else { // nothing moved
|
---|
1233 | selection.append(QItemSelectionRange(tl, br));
|
---|
1234 | }
|
---|
1235 |
|
---|
1236 | d->selectionModel->select(selection, command);
|
---|
1237 | }
|
---|
1238 |
|
---|
1239 | /*!
|
---|
1240 | \internal
|
---|
1241 |
|
---|
1242 | Returns the rectangle from the viewport of the items in the given
|
---|
1243 | \a selection.
|
---|
1244 | */
|
---|
1245 | QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) const
|
---|
1246 | {
|
---|
1247 | Q_D(const QTableView);
|
---|
1248 |
|
---|
1249 | if (selection.isEmpty())
|
---|
1250 | return QRegion();
|
---|
1251 |
|
---|
1252 | QRegion selectionRegion;
|
---|
1253 | bool verticalMoved = verticalHeader()->sectionsMoved();
|
---|
1254 | bool horizontalMoved = horizontalHeader()->sectionsMoved();
|
---|
1255 |
|
---|
1256 | if ((verticalMoved && horizontalMoved) || d->hasSpans()) {
|
---|
1257 | for (int i = 0; i < selection.count(); ++i) {
|
---|
1258 | QItemSelectionRange range = selection.at(i);
|
---|
1259 | if (range.parent() != d->root || !range.isValid())
|
---|
1260 | continue;
|
---|
1261 | for (int r = range.top(); r <= range.bottom(); ++r)
|
---|
1262 | for (int c = range.left(); c <= range.right(); ++c)
|
---|
1263 | selectionRegion += QRegion(visualRect(d->model->index(r, c, d->root)));
|
---|
1264 | }
|
---|
1265 | } else if (horizontalMoved) {
|
---|
1266 | for (int i = 0; i < selection.count(); ++i) {
|
---|
1267 | QItemSelectionRange range = selection.at(i);
|
---|
1268 | if (range.parent() != d->root || !range.isValid())
|
---|
1269 | continue;
|
---|
1270 | int top = rowViewportPosition(range.top());
|
---|
1271 | int bottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom());
|
---|
1272 | if (top > bottom)
|
---|
1273 | qSwap<int>(top, bottom);
|
---|
1274 | int height = bottom - top;
|
---|
1275 | for (int c = range.left(); c <= range.right(); ++c)
|
---|
1276 | selectionRegion += QRegion(QRect(columnViewportPosition(c), top,
|
---|
1277 | columnWidth(c), height));
|
---|
1278 | }
|
---|
1279 | } else if (verticalMoved) {
|
---|
1280 | for (int i = 0; i < selection.count(); ++i) {
|
---|
1281 | QItemSelectionRange range = selection.at(i);
|
---|
1282 | if (range.parent() != d->root || !range.isValid())
|
---|
1283 | continue;
|
---|
1284 | int left = columnViewportPosition(range.left());
|
---|
1285 | int right = columnViewportPosition(range.right()) + columnWidth(range.right());
|
---|
1286 | if (left > right)
|
---|
1287 | qSwap<int>(left, right);
|
---|
1288 | int width = right - left;
|
---|
1289 | for (int r = range.top(); r <= range.bottom(); ++r)
|
---|
1290 | selectionRegion += QRegion(QRect(left, rowViewportPosition(r),
|
---|
1291 | width, rowHeight(r)));
|
---|
1292 | }
|
---|
1293 | } else { // nothing moved
|
---|
1294 | for (int i = 0; i < selection.count(); ++i) {
|
---|
1295 | QItemSelectionRange range = selection.at(i);
|
---|
1296 | if (range.parent() != d->root || !range.isValid())
|
---|
1297 | continue;
|
---|
1298 | d->trimHiddenSelections(&range);
|
---|
1299 | QRect tl = visualRect(range.topLeft());
|
---|
1300 | QRect br = visualRect(range.bottomRight());
|
---|
1301 | selectionRegion += QRegion(tl|br);
|
---|
1302 | }
|
---|
1303 | }
|
---|
1304 |
|
---|
1305 | return selectionRegion;
|
---|
1306 | }
|
---|
1307 |
|
---|
1308 |
|
---|
1309 | /*!
|
---|
1310 | \reimp
|
---|
1311 | */
|
---|
1312 | QModelIndexList QTableView::selectedIndexes() const
|
---|
1313 | {
|
---|
1314 | Q_D(const QTableView);
|
---|
1315 | QModelIndexList viewSelected;
|
---|
1316 | QModelIndexList modelSelected;
|
---|
1317 | if (d->selectionModel)
|
---|
1318 | modelSelected = d->selectionModel->selectedIndexes();
|
---|
1319 | for (int i = 0; i < modelSelected.count(); ++i) {
|
---|
1320 | QModelIndex index = modelSelected.at(i);
|
---|
1321 | if (!isIndexHidden(index) && index.parent() == d->root)
|
---|
1322 | viewSelected.append(index);
|
---|
1323 | }
|
---|
1324 | return viewSelected;
|
---|
1325 | }
|
---|
1326 |
|
---|
1327 |
|
---|
1328 | /*!
|
---|
1329 | This slot is called whenever rows are added or deleted. The
|
---|
1330 | previous number of rows is specified by \a oldCount, and the new
|
---|
1331 | number of rows is specified by \a newCount.
|
---|
1332 | */
|
---|
1333 | void QTableView::rowCountChanged(int /*oldCount*/, int /*newCount*/ )
|
---|
1334 | {
|
---|
1335 | Q_D(QTableView);
|
---|
1336 | updateGeometries();
|
---|
1337 | if (verticalScrollMode() == QAbstractItemView::ScrollPerItem)
|
---|
1338 | d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
|
---|
1339 | else
|
---|
1340 | d->verticalHeader->setOffset(verticalScrollBar()->value());
|
---|
1341 | d->viewport->update();
|
---|
1342 | }
|
---|
1343 |
|
---|
1344 | /*!
|
---|
1345 | This slot is called whenever columns are added or deleted. The
|
---|
1346 | previous number of columns is specified by \a oldCount, and the new
|
---|
1347 | number of columns is specified by \a newCount.
|
---|
1348 | */
|
---|
1349 | void QTableView::columnCountChanged(int, int)
|
---|
1350 | {
|
---|
1351 | Q_D(QTableView);
|
---|
1352 | updateGeometries();
|
---|
1353 | if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem)
|
---|
1354 | d->horizontalHeader->setOffsetToSectionPosition(horizontalScrollBar()->value());
|
---|
1355 | else
|
---|
1356 | d->horizontalHeader->setOffset(horizontalScrollBar()->value());
|
---|
1357 | d->viewport->update();
|
---|
1358 | }
|
---|
1359 |
|
---|
1360 | /*!
|
---|
1361 | \reimp
|
---|
1362 | */
|
---|
1363 | void QTableView::updateGeometries()
|
---|
1364 | {
|
---|
1365 | Q_D(QTableView);
|
---|
1366 | if (d->geometryRecursionBlock)
|
---|
1367 | return;
|
---|
1368 | d->geometryRecursionBlock = true;
|
---|
1369 |
|
---|
1370 | int width = 0;
|
---|
1371 | if (!d->verticalHeader->isHidden()) {
|
---|
1372 | width = qMax(d->verticalHeader->minimumWidth(), d->verticalHeader->sizeHint().width());
|
---|
1373 | width = qMin(width, d->verticalHeader->maximumWidth());
|
---|
1374 | }
|
---|
1375 | int height = 0;
|
---|
1376 | if (!d->horizontalHeader->isHidden()) {
|
---|
1377 | height = qMax(d->horizontalHeader->minimumHeight(), d->horizontalHeader->sizeHint().height());
|
---|
1378 | height = qMin(height, d->horizontalHeader->maximumHeight());
|
---|
1379 | }
|
---|
1380 | bool reverse = isRightToLeft();
|
---|
1381 | if (reverse)
|
---|
1382 | setViewportMargins(0, height, width, 0);
|
---|
1383 | else
|
---|
1384 | setViewportMargins(width, height, 0, 0);
|
---|
1385 |
|
---|
1386 | // update headers
|
---|
1387 |
|
---|
1388 | QRect vg = d->viewport->geometry();
|
---|
1389 |
|
---|
1390 | int verticalLeft = reverse ? vg.right() + 1 : (vg.left() - width);
|
---|
1391 | d->verticalHeader->setGeometry(verticalLeft, vg.top(), width, vg.height());
|
---|
1392 | if (d->verticalHeader->isHidden())
|
---|
1393 | QMetaObject::invokeMethod(d->verticalHeader, "updateGeometries");
|
---|
1394 |
|
---|
1395 | int horizontalTop = vg.top() - height;
|
---|
1396 | d->horizontalHeader->setGeometry(vg.left(), horizontalTop, vg.width(), height);
|
---|
1397 | if (d->horizontalHeader->isHidden())
|
---|
1398 | QMetaObject::invokeMethod(d->horizontalHeader, "updateGeometries");
|
---|
1399 |
|
---|
1400 | // update cornerWidget
|
---|
1401 | if (d->horizontalHeader->isHidden() || d->verticalHeader->isHidden()) {
|
---|
1402 | d->cornerWidget->setHidden(true);
|
---|
1403 | } else {
|
---|
1404 | d->cornerWidget->setHidden(false);
|
---|
1405 | d->cornerWidget->setGeometry(verticalLeft, horizontalTop, width, height);
|
---|
1406 | }
|
---|
1407 |
|
---|
1408 | // update scroll bars
|
---|
1409 |
|
---|
1410 | // ### move this block into the if
|
---|
1411 | QSize vsize = d->viewport->size();
|
---|
1412 | QSize max = maximumViewportSize();
|
---|
1413 | uint horizontalLength = d->horizontalHeader->length();
|
---|
1414 | uint verticalLength = d->verticalHeader->length();
|
---|
1415 | if ((uint)max.width() >= horizontalLength && (uint)max.height() >= verticalLength)
|
---|
1416 | vsize = max;
|
---|
1417 |
|
---|
1418 | // horizontal scroll bar
|
---|
1419 | const int columnCount = d->horizontalHeader->count();
|
---|
1420 | const int viewportWidth = vsize.width();
|
---|
1421 | int columnsInViewport = 0;
|
---|
1422 | for (int width = 0, column = columnCount - 1; column >= 0; --column) {
|
---|
1423 | int logical = d->horizontalHeader->logicalIndex(column);
|
---|
1424 | if (!d->horizontalHeader->isSectionHidden(logical)) {
|
---|
1425 | width += d->horizontalHeader->sectionSize(logical);
|
---|
1426 | if (width > viewportWidth)
|
---|
1427 | break;
|
---|
1428 | ++columnsInViewport;
|
---|
1429 | }
|
---|
1430 | }
|
---|
1431 | if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
|
---|
1432 | const int visibleColumns = columnCount - d->horizontalHeader->hiddenSectionCount();
|
---|
1433 | horizontalScrollBar()->setRange(0, visibleColumns - columnsInViewport);
|
---|
1434 | horizontalScrollBar()->setPageStep(columnsInViewport);
|
---|
1435 | if (columnsInViewport >= visibleColumns)
|
---|
1436 | d->horizontalHeader->setOffset(0);
|
---|
1437 | horizontalScrollBar()->setSingleStep(1);
|
---|
1438 | } else { // ScrollPerPixel
|
---|
1439 | horizontalScrollBar()->setPageStep(vsize.width());
|
---|
1440 | horizontalScrollBar()->setRange(0, horizontalLength - vsize.width());
|
---|
1441 | horizontalScrollBar()->setSingleStep(qMax(vsize.width() / (columnsInViewport + 1), 2));
|
---|
1442 | }
|
---|
1443 |
|
---|
1444 | // vertical scroll bar
|
---|
1445 | const int rowCount = d->verticalHeader->count();
|
---|
1446 | const int viewportHeight = vsize.height();
|
---|
1447 | int rowsInViewport = 0;
|
---|
1448 | for (int height = 0, row = rowCount - 1; row >= 0; --row) {
|
---|
1449 | int logical = d->verticalHeader->logicalIndex(row);
|
---|
1450 | if (!d->verticalHeader->isSectionHidden(logical)) {
|
---|
1451 | height += d->verticalHeader->sectionSize(logical);
|
---|
1452 | if (height > viewportHeight)
|
---|
1453 | break;
|
---|
1454 | ++rowsInViewport;
|
---|
1455 | }
|
---|
1456 | }
|
---|
1457 | if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
|
---|
1458 | const int visibleRows = rowCount - d->verticalHeader->hiddenSectionCount();
|
---|
1459 | verticalScrollBar()->setRange(0, visibleRows - rowsInViewport);
|
---|
1460 | verticalScrollBar()->setPageStep(rowsInViewport);
|
---|
1461 | if (rowsInViewport >= visibleRows)
|
---|
1462 | d->verticalHeader->setOffset(0);
|
---|
1463 | verticalScrollBar()->setSingleStep(1);
|
---|
1464 | } else { // ScrollPerPixel
|
---|
1465 | verticalScrollBar()->setPageStep(vsize.height());
|
---|
1466 | verticalScrollBar()->setRange(0, verticalLength - vsize.height());
|
---|
1467 | verticalScrollBar()->setSingleStep(qMax(vsize.height() / (rowsInViewport + 1), 2));
|
---|
1468 | }
|
---|
1469 |
|
---|
1470 | d->geometryRecursionBlock = false;
|
---|
1471 | QAbstractItemView::updateGeometries();
|
---|
1472 | }
|
---|
1473 |
|
---|
1474 | /*!
|
---|
1475 | Returns the size hint for the given \a row's height or -1 if there
|
---|
1476 | is no model.
|
---|
1477 |
|
---|
1478 | If you need to set the height of a given row to a fixed value, call
|
---|
1479 | QHeaderView::resizeSection() on the table's vertical header.
|
---|
1480 |
|
---|
1481 | If you reimplement this function in a subclass, note that the value you
|
---|
1482 | return is only used when resizeRowToContents() is called. In that case,
|
---|
1483 | if a larger row height is required by either the vertical header or
|
---|
1484 | the item delegate, that width will be used instead.
|
---|
1485 |
|
---|
1486 | \sa QWidget::sizeHint, verticalHeader()
|
---|
1487 | */
|
---|
1488 | int QTableView::sizeHintForRow(int row) const
|
---|
1489 | {
|
---|
1490 | Q_D(const QTableView);
|
---|
1491 |
|
---|
1492 | if (!model())
|
---|
1493 | return -1;
|
---|
1494 |
|
---|
1495 | int left = qMax(0, columnAt(0));
|
---|
1496 | int right = columnAt(d->viewport->width());
|
---|
1497 | if (right == -1) // the table don't have enough columns to fill the viewport
|
---|
1498 | right = d->model->columnCount(d->root) - 1;
|
---|
1499 |
|
---|
1500 | QStyleOptionViewItemV4 option = d->viewOptionsV4();
|
---|
1501 |
|
---|
1502 | int hint = 0;
|
---|
1503 | QModelIndex index;
|
---|
1504 | for (int column = left; column <= right; ++column) {
|
---|
1505 | int logicalColumn = d->horizontalHeader->logicalIndex(column);
|
---|
1506 | if (d->horizontalHeader->isSectionHidden(logicalColumn))
|
---|
1507 | continue;
|
---|
1508 | index = d->model->index(row, logicalColumn, d->root);
|
---|
1509 | if (d->wrapItemText) {// for wrapping boundaries
|
---|
1510 | option.rect.setY(rowViewportPosition(index.row()));
|
---|
1511 | option.rect.setHeight(rowHeight(index.row()));
|
---|
1512 | option.rect.setX(columnViewportPosition(index.column()));
|
---|
1513 | option.rect.setWidth(columnWidth(index.column()));
|
---|
1514 | }
|
---|
1515 |
|
---|
1516 | QWidget *editor = d->editorForIndex(index).editor;
|
---|
1517 | if (editor && d->persistent.contains(editor)) {
|
---|
1518 | hint = qMax(hint, editor->sizeHint().height());
|
---|
1519 | int min = editor->minimumSize().height();
|
---|
1520 | int max = editor->maximumSize().height();
|
---|
1521 | hint = qBound(min, hint, max);
|
---|
1522 | }
|
---|
1523 |
|
---|
1524 | hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).height());
|
---|
1525 | }
|
---|
1526 |
|
---|
1527 | return d->showGrid ? hint + 1 : hint;
|
---|
1528 | }
|
---|
1529 |
|
---|
1530 | /*!
|
---|
1531 | Returns the size hint for the given \a column's width or -1 if
|
---|
1532 | there is no model.
|
---|
1533 |
|
---|
1534 | If you need to set the width of a given column to a fixed value, call
|
---|
1535 | QHeaderView::resizeSection() on the table's horizontal header.
|
---|
1536 |
|
---|
1537 | If you reimplement this function in a subclass, note that the value you
|
---|
1538 | return will be used when resizeColumnToContents() or
|
---|
1539 | QHeaderView::resizeSections() is called. If a larger column width is
|
---|
1540 | required by either the horizontal header or the item delegate, the larger
|
---|
1541 | width will be used instead.
|
---|
1542 |
|
---|
1543 | \sa QWidget::sizeHint, horizontalHeader()
|
---|
1544 | */
|
---|
1545 | int QTableView::sizeHintForColumn(int column) const
|
---|
1546 | {
|
---|
1547 | Q_D(const QTableView);
|
---|
1548 |
|
---|
1549 | if (!model())
|
---|
1550 | return -1;
|
---|
1551 |
|
---|
1552 | int top = qMax(0, rowAt(0));
|
---|
1553 | int bottom = rowAt(d->viewport->height());
|
---|
1554 | if (!isVisible() || bottom == -1) // the table don't have enough rows to fill the viewport
|
---|
1555 | bottom = d->model->rowCount(d->root) - 1;
|
---|
1556 |
|
---|
1557 | QStyleOptionViewItemV4 option = d->viewOptionsV4();
|
---|
1558 |
|
---|
1559 | int hint = 0;
|
---|
1560 | QModelIndex index;
|
---|
1561 | for (int row = top; row <= bottom; ++row) {
|
---|
1562 | int logicalRow = d->verticalHeader->logicalIndex(row);
|
---|
1563 | if (d->verticalHeader->isSectionHidden(logicalRow))
|
---|
1564 | continue;
|
---|
1565 | index = d->model->index(logicalRow, column, d->root);
|
---|
1566 |
|
---|
1567 | QWidget *editor = d->editorForIndex(index).editor;
|
---|
1568 | if (editor && d->persistent.contains(editor)) {
|
---|
1569 | hint = qMax(hint, editor->sizeHint().width());
|
---|
1570 | int min = editor->minimumSize().width();
|
---|
1571 | int max = editor->maximumSize().width();
|
---|
1572 | hint = qBound(min, hint, max);
|
---|
1573 | }
|
---|
1574 |
|
---|
1575 | hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).width());
|
---|
1576 | }
|
---|
1577 |
|
---|
1578 | return d->showGrid ? hint + 1 : hint;
|
---|
1579 | }
|
---|
1580 |
|
---|
1581 | /*!
|
---|
1582 | Returns the y-coordinate in contents coordinates of the given \a
|
---|
1583 | row.
|
---|
1584 | */
|
---|
1585 | int QTableView::rowViewportPosition(int row) const
|
---|
1586 | {
|
---|
1587 | Q_D(const QTableView);
|
---|
1588 | return d->verticalHeader->sectionViewportPosition(row);
|
---|
1589 | }
|
---|
1590 |
|
---|
1591 | /*!
|
---|
1592 | Returns the row in which the given y-coordinate, \a y, in contents
|
---|
1593 | coordinates is located.
|
---|
1594 |
|
---|
1595 | \note This function returns -1 if the given coordinate is not valid
|
---|
1596 | (has no row).
|
---|
1597 |
|
---|
1598 | \sa columnAt()
|
---|
1599 | */
|
---|
1600 | int QTableView::rowAt(int y) const
|
---|
1601 | {
|
---|
1602 | Q_D(const QTableView);
|
---|
1603 | return d->verticalHeader->logicalIndexAt(y);
|
---|
1604 | }
|
---|
1605 |
|
---|
1606 | /*!
|
---|
1607 | \since 4.1
|
---|
1608 |
|
---|
1609 | Sets the height of the given \a row to be \a height.
|
---|
1610 | */
|
---|
1611 | void QTableView::setRowHeight(int row, int height)
|
---|
1612 | {
|
---|
1613 | Q_D(const QTableView);
|
---|
1614 | d->verticalHeader->resizeSection(row, height);
|
---|
1615 | }
|
---|
1616 |
|
---|
1617 | /*!
|
---|
1618 | Returns the height of the given \a row.
|
---|
1619 |
|
---|
1620 | \sa resizeRowToContents(), columnWidth()
|
---|
1621 | */
|
---|
1622 | int QTableView::rowHeight(int row) const
|
---|
1623 | {
|
---|
1624 | Q_D(const QTableView);
|
---|
1625 | return d->verticalHeader->sectionSize(row);
|
---|
1626 | }
|
---|
1627 |
|
---|
1628 | /*!
|
---|
1629 | Returns the x-coordinate in contents coordinates of the given \a
|
---|
1630 | column.
|
---|
1631 | */
|
---|
1632 | int QTableView::columnViewportPosition(int column) const
|
---|
1633 | {
|
---|
1634 | Q_D(const QTableView);
|
---|
1635 | return d->horizontalHeader->sectionViewportPosition(column);
|
---|
1636 | }
|
---|
1637 |
|
---|
1638 | /*!
|
---|
1639 | Returns the column in which the given x-coordinate, \a x, in contents
|
---|
1640 | coordinates is located.
|
---|
1641 |
|
---|
1642 | \note This function returns -1 if the given coordinate is not valid
|
---|
1643 | (has no column).
|
---|
1644 |
|
---|
1645 | \sa rowAt()
|
---|
1646 | */
|
---|
1647 | int QTableView::columnAt(int x) const
|
---|
1648 | {
|
---|
1649 | Q_D(const QTableView);
|
---|
1650 | return d->horizontalHeader->logicalIndexAt(x);
|
---|
1651 | }
|
---|
1652 |
|
---|
1653 | /*!
|
---|
1654 | \since 4.1
|
---|
1655 |
|
---|
1656 | Sets the width of the given \a column to be \a width.
|
---|
1657 | */
|
---|
1658 | void QTableView::setColumnWidth(int column, int width)
|
---|
1659 | {
|
---|
1660 | Q_D(const QTableView);
|
---|
1661 | d->horizontalHeader->resizeSection(column, width);
|
---|
1662 | }
|
---|
1663 |
|
---|
1664 | /*!
|
---|
1665 | Returns the width of the given \a column.
|
---|
1666 |
|
---|
1667 | \sa resizeColumnToContents(), rowHeight()
|
---|
1668 | */
|
---|
1669 | int QTableView::columnWidth(int column) const
|
---|
1670 | {
|
---|
1671 | Q_D(const QTableView);
|
---|
1672 | return d->horizontalHeader->sectionSize(column);
|
---|
1673 | }
|
---|
1674 |
|
---|
1675 | /*!
|
---|
1676 | Returns true if the given \a row is hidden; otherwise returns false.
|
---|
1677 |
|
---|
1678 | \sa isColumnHidden()
|
---|
1679 | */
|
---|
1680 | bool QTableView::isRowHidden(int row) const
|
---|
1681 | {
|
---|
1682 | Q_D(const QTableView);
|
---|
1683 | return d->verticalHeader->isSectionHidden(row);
|
---|
1684 | }
|
---|
1685 |
|
---|
1686 | /*!
|
---|
1687 | If \a hide is true \a row will be hidden, otherwise it will be shown.
|
---|
1688 |
|
---|
1689 | \sa setColumnHidden()
|
---|
1690 | */
|
---|
1691 | void QTableView::setRowHidden(int row, bool hide)
|
---|
1692 | {
|
---|
1693 | Q_D(QTableView);
|
---|
1694 | if (row < 0 || row >= d->verticalHeader->count())
|
---|
1695 | return;
|
---|
1696 | d->verticalHeader->setSectionHidden(row, hide);
|
---|
1697 | }
|
---|
1698 |
|
---|
1699 | /*!
|
---|
1700 | Returns true if the given \a column is hidden; otherwise returns false.
|
---|
1701 |
|
---|
1702 | \sa isRowHidden()
|
---|
1703 | */
|
---|
1704 | bool QTableView::isColumnHidden(int column) const
|
---|
1705 | {
|
---|
1706 | Q_D(const QTableView);
|
---|
1707 | return d->horizontalHeader->isSectionHidden(column);
|
---|
1708 | }
|
---|
1709 |
|
---|
1710 | /*!
|
---|
1711 | If \a hide is true the given \a column will be hidden; otherwise it
|
---|
1712 | will be shown.
|
---|
1713 |
|
---|
1714 | \sa setRowHidden()
|
---|
1715 | */
|
---|
1716 | void QTableView::setColumnHidden(int column, bool hide)
|
---|
1717 | {
|
---|
1718 | Q_D(QTableView);
|
---|
1719 | if (column < 0 || column >= d->horizontalHeader->count())
|
---|
1720 | return;
|
---|
1721 | d->horizontalHeader->setSectionHidden(column, hide);
|
---|
1722 | }
|
---|
1723 |
|
---|
1724 | /*!
|
---|
1725 | \since 4.2
|
---|
1726 | \property QTableView::sortingEnabled
|
---|
1727 | \brief whether sorting is enabled
|
---|
1728 |
|
---|
1729 | If this property is true, sorting is enabled for the table; if the
|
---|
1730 | property is false, sorting is not enabled. The default value is false.
|
---|
1731 |
|
---|
1732 | \sa sortByColumn()
|
---|
1733 | */
|
---|
1734 |
|
---|
1735 | void QTableView::setSortingEnabled(bool enable)
|
---|
1736 | {
|
---|
1737 | Q_D(QTableView);
|
---|
1738 | d->sortingEnabled = enable;
|
---|
1739 | horizontalHeader()->setSortIndicatorShown(enable);
|
---|
1740 | if (enable) {
|
---|
1741 | disconnect(d->horizontalHeader, SIGNAL(sectionEntered(int)),
|
---|
1742 | this, SLOT(_q_selectColumn(int)));
|
---|
1743 | disconnect(horizontalHeader(), SIGNAL(sectionPressed(int)),
|
---|
1744 | this, SLOT(selectColumn(int)));
|
---|
1745 | connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
|
---|
1746 | this, SLOT(sortByColumn(int)));
|
---|
1747 | sortByColumn(horizontalHeader()->sortIndicatorSection(),
|
---|
1748 | horizontalHeader()->sortIndicatorOrder());
|
---|
1749 | } else {
|
---|
1750 | connect(d->horizontalHeader, SIGNAL(sectionEntered(int)),
|
---|
1751 | this, SLOT(_q_selectColumn(int)));
|
---|
1752 | connect(horizontalHeader(), SIGNAL(sectionPressed(int)),
|
---|
1753 | this, SLOT(selectColumn(int)));
|
---|
1754 | disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
|
---|
1755 | this, SLOT(sortByColumn(int)));
|
---|
1756 | }
|
---|
1757 | }
|
---|
1758 |
|
---|
1759 | bool QTableView::isSortingEnabled() const
|
---|
1760 | {
|
---|
1761 | Q_D(const QTableView);
|
---|
1762 | return d->sortingEnabled;
|
---|
1763 | }
|
---|
1764 |
|
---|
1765 | /*!
|
---|
1766 | \property QTableView::showGrid
|
---|
1767 | \brief whether the grid is shown
|
---|
1768 |
|
---|
1769 | If this property is true a grid is drawn for the table; if the
|
---|
1770 | property is false, no grid is drawn. The default value is true.
|
---|
1771 | */
|
---|
1772 | bool QTableView::showGrid() const
|
---|
1773 | {
|
---|
1774 | Q_D(const QTableView);
|
---|
1775 | return d->showGrid;
|
---|
1776 | }
|
---|
1777 |
|
---|
1778 | void QTableView::setShowGrid(bool show)
|
---|
1779 | {
|
---|
1780 | Q_D(QTableView);
|
---|
1781 | if (d->showGrid != show) {
|
---|
1782 | d->showGrid = show;
|
---|
1783 | d->viewport->update();
|
---|
1784 | }
|
---|
1785 | }
|
---|
1786 |
|
---|
1787 | /*!
|
---|
1788 | \property QTableView::gridStyle
|
---|
1789 | \brief the pen style used to draw the grid.
|
---|
1790 |
|
---|
1791 | This property holds the style used when drawing the grid (see \l{showGrid}).
|
---|
1792 | */
|
---|
1793 | Qt::PenStyle QTableView::gridStyle() const
|
---|
1794 | {
|
---|
1795 | Q_D(const QTableView);
|
---|
1796 | return d->gridStyle;
|
---|
1797 | }
|
---|
1798 |
|
---|
1799 | void QTableView::setGridStyle(Qt::PenStyle style)
|
---|
1800 | {
|
---|
1801 | Q_D(QTableView);
|
---|
1802 | if (d->gridStyle != style) {
|
---|
1803 | d->gridStyle = style;
|
---|
1804 | d->viewport->update();
|
---|
1805 | }
|
---|
1806 | }
|
---|
1807 |
|
---|
1808 | /*!
|
---|
1809 | \property QTableView::wordWrap
|
---|
1810 | \brief the item text word-wrapping policy
|
---|
1811 | \since 4.3
|
---|
1812 |
|
---|
1813 | If this property is true then the item text is wrapped where
|
---|
1814 | necessary at word-breaks; otherwise it is not wrapped at all.
|
---|
1815 | This property is true by default.
|
---|
1816 |
|
---|
1817 | Note that even of wrapping is enabled, the cell will not be
|
---|
1818 | expanded to fit all text. Ellipsis will be inserted according to
|
---|
1819 | the current \l{QAbstractItemView::}{textElideMode}.
|
---|
1820 |
|
---|
1821 | */
|
---|
1822 | void QTableView::setWordWrap(bool on)
|
---|
1823 | {
|
---|
1824 | Q_D(QTableView);
|
---|
1825 | if (d->wrapItemText == on)
|
---|
1826 | return;
|
---|
1827 | d->wrapItemText = on;
|
---|
1828 | QMetaObject::invokeMethod(d->verticalHeader, "resizeSections");
|
---|
1829 | QMetaObject::invokeMethod(d->horizontalHeader, "resizeSections");
|
---|
1830 | }
|
---|
1831 |
|
---|
1832 | bool QTableView::wordWrap() const
|
---|
1833 | {
|
---|
1834 | Q_D(const QTableView);
|
---|
1835 | return d->wrapItemText;
|
---|
1836 | }
|
---|
1837 |
|
---|
1838 | /*!
|
---|
1839 | \property QTableView::cornerButtonEnabled
|
---|
1840 | \brief whether the button in the top-left corner is enabled
|
---|
1841 | \since 4.3
|
---|
1842 |
|
---|
1843 | If this property is true then button in the top-left corner
|
---|
1844 | of the table view is enabled. Clicking on this button will
|
---|
1845 | select all the cells in the table view.
|
---|
1846 |
|
---|
1847 | This property is true by default.
|
---|
1848 | */
|
---|
1849 | void QTableView::setCornerButtonEnabled(bool enable)
|
---|
1850 | {
|
---|
1851 | Q_D(QTableView);
|
---|
1852 | d->cornerWidget->setEnabled(enable);
|
---|
1853 | }
|
---|
1854 |
|
---|
1855 | bool QTableView::isCornerButtonEnabled() const
|
---|
1856 | {
|
---|
1857 | Q_D(const QTableView);
|
---|
1858 | return d->cornerWidget->isEnabled();
|
---|
1859 | }
|
---|
1860 |
|
---|
1861 | /*!
|
---|
1862 | \internal
|
---|
1863 |
|
---|
1864 | Returns the rectangle on the viewport occupied by the given \a
|
---|
1865 | index.
|
---|
1866 | If the index is hidden in the view it will return a null QRect.
|
---|
1867 | */
|
---|
1868 | QRect QTableView::visualRect(const QModelIndex &index) const
|
---|
1869 | {
|
---|
1870 | Q_D(const QTableView);
|
---|
1871 | if (!d->isIndexValid(index) || index.parent() != d->root || isIndexHidden(index) )
|
---|
1872 | return QRect();
|
---|
1873 |
|
---|
1874 | d->executePostedLayout();
|
---|
1875 |
|
---|
1876 | if (d->hasSpans()) {
|
---|
1877 | QTableViewPrivate::Span span = d->span(index.row(), index.column());
|
---|
1878 | return d->visualSpanRect(span);
|
---|
1879 | }
|
---|
1880 |
|
---|
1881 | int rowp = rowViewportPosition(index.row());
|
---|
1882 | int rowh = rowHeight(index.row());
|
---|
1883 | int colp = columnViewportPosition(index.column());
|
---|
1884 | int colw = columnWidth(index.column());
|
---|
1885 |
|
---|
1886 | const int i = showGrid() ? 1 : 0;
|
---|
1887 | return QRect(colp, rowp, colw - i, rowh - i);
|
---|
1888 | }
|
---|
1889 |
|
---|
1890 | /*!
|
---|
1891 | \internal
|
---|
1892 |
|
---|
1893 | Makes sure that the given \a item is visible in the table view,
|
---|
1894 | scrolling if necessary.
|
---|
1895 | */
|
---|
1896 | void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint)
|
---|
1897 | {
|
---|
1898 | Q_D(QTableView);
|
---|
1899 |
|
---|
1900 | // check if we really need to do anything
|
---|
1901 | if (!d->isIndexValid(index)
|
---|
1902 | || (d->model->parent(index) != d->root)
|
---|
1903 | || isIndexHidden(index))
|
---|
1904 | return;
|
---|
1905 |
|
---|
1906 | QTableViewPrivate::Span span;
|
---|
1907 | if (d->hasSpans())
|
---|
1908 | span = d->span(index.row(), index.column());
|
---|
1909 |
|
---|
1910 | // Adjust horizontal position
|
---|
1911 |
|
---|
1912 | int viewportWidth = d->viewport->width();
|
---|
1913 | int horizontalOffset = d->horizontalHeader->offset();
|
---|
1914 | int horizontalPosition = d->horizontalHeader->sectionPosition(index.column());
|
---|
1915 | int horizontalIndex = d->horizontalHeader->visualIndex(index.column());
|
---|
1916 | int cellWidth = d->hasSpans()
|
---|
1917 | ? d->columnSpanWidth(index.column(), span.width())
|
---|
1918 | : d->horizontalHeader->sectionSize(index.column());
|
---|
1919 |
|
---|
1920 | if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
|
---|
1921 |
|
---|
1922 | bool positionAtLeft = (horizontalPosition - horizontalOffset < 0);
|
---|
1923 | bool positionAtRight = (horizontalPosition - horizontalOffset + cellWidth > viewportWidth);
|
---|
1924 |
|
---|
1925 | if (hint == PositionAtCenter || positionAtRight) {
|
---|
1926 | int w = (hint == PositionAtCenter ? viewportWidth / 2 : viewportWidth);
|
---|
1927 | int x = cellWidth;
|
---|
1928 | while (horizontalIndex > 0) {
|
---|
1929 | x += columnWidth(d->horizontalHeader->logicalIndex(horizontalIndex-1));
|
---|
1930 | if (x > w)
|
---|
1931 | break;
|
---|
1932 | --horizontalIndex;
|
---|
1933 | }
|
---|
1934 | }
|
---|
1935 |
|
---|
1936 | if (positionAtRight || hint == PositionAtCenter || positionAtLeft) {
|
---|
1937 | int hiddenSections = 0;
|
---|
1938 | if (d->horizontalHeader->sectionsHidden()) {
|
---|
1939 | for (int s = horizontalIndex; s >= 0; --s) {
|
---|
1940 | int column = d->horizontalHeader->logicalIndex(s);
|
---|
1941 | if (d->horizontalHeader->isSectionHidden(column))
|
---|
1942 | ++hiddenSections;
|
---|
1943 | }
|
---|
1944 | }
|
---|
1945 | horizontalScrollBar()->setValue(horizontalIndex - hiddenSections);
|
---|
1946 | }
|
---|
1947 |
|
---|
1948 | } else { // ScrollPerPixel
|
---|
1949 | if (hint == PositionAtCenter) {
|
---|
1950 | horizontalScrollBar()->setValue(horizontalPosition - ((viewportWidth - cellWidth) / 2));
|
---|
1951 | } else {
|
---|
1952 | if (horizontalPosition - horizontalOffset < 0 || cellWidth > viewportWidth)
|
---|
1953 | horizontalScrollBar()->setValue(horizontalPosition);
|
---|
1954 | else if (horizontalPosition - horizontalOffset + cellWidth > viewportWidth)
|
---|
1955 | horizontalScrollBar()->setValue(horizontalPosition - viewportWidth + cellWidth);
|
---|
1956 | }
|
---|
1957 | }
|
---|
1958 |
|
---|
1959 | // Adjust vertical position
|
---|
1960 |
|
---|
1961 | int viewportHeight = d->viewport->height();
|
---|
1962 | int verticalOffset = d->verticalHeader->offset();
|
---|
1963 | int verticalPosition = d->verticalHeader->sectionPosition(index.row());
|
---|
1964 | int verticalIndex = d->verticalHeader->visualIndex(index.row());
|
---|
1965 | int cellHeight = d->hasSpans()
|
---|
1966 | ? d->rowSpanHeight(index.row(), span.height())
|
---|
1967 | : d->verticalHeader->sectionSize(index.row());
|
---|
1968 |
|
---|
1969 | if (verticalPosition - verticalOffset < 0 || cellHeight > viewportHeight) {
|
---|
1970 | if (hint == EnsureVisible)
|
---|
1971 | hint = PositionAtTop;
|
---|
1972 | } else if (verticalPosition - verticalOffset + cellHeight > viewportHeight) {
|
---|
1973 | if (hint == EnsureVisible)
|
---|
1974 | hint = PositionAtBottom;
|
---|
1975 | }
|
---|
1976 |
|
---|
1977 | if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
|
---|
1978 |
|
---|
1979 | if (hint == PositionAtBottom || hint == PositionAtCenter) {
|
---|
1980 | int h = (hint == PositionAtCenter ? viewportHeight / 2 : viewportHeight);
|
---|
1981 | int y = cellHeight;
|
---|
1982 | while (verticalIndex > 0) {
|
---|
1983 | int row = d->verticalHeader->logicalIndex(verticalIndex - 1);
|
---|
1984 | y += d->verticalHeader->sectionSize(row);
|
---|
1985 | if (y > h)
|
---|
1986 | break;
|
---|
1987 | --verticalIndex;
|
---|
1988 | }
|
---|
1989 | }
|
---|
1990 |
|
---|
1991 | if (hint == PositionAtBottom || hint == PositionAtCenter || hint == PositionAtTop) {
|
---|
1992 | int hiddenSections = 0;
|
---|
1993 | if (d->verticalHeader->sectionsHidden()) {
|
---|
1994 | for (int s = verticalIndex; s >= 0; --s) {
|
---|
1995 | int row = d->verticalHeader->logicalIndex(s);
|
---|
1996 | if (d->verticalHeader->isSectionHidden(row))
|
---|
1997 | ++hiddenSections;
|
---|
1998 | }
|
---|
1999 | }
|
---|
2000 | verticalScrollBar()->setValue(verticalIndex - hiddenSections);
|
---|
2001 | }
|
---|
2002 |
|
---|
2003 | } else { // ScrollPerPixel
|
---|
2004 | if (hint == PositionAtTop) {
|
---|
2005 | verticalScrollBar()->setValue(verticalPosition);
|
---|
2006 | } else if (hint == PositionAtBottom) {
|
---|
2007 | verticalScrollBar()->setValue(verticalPosition - viewportHeight + cellHeight);
|
---|
2008 | } else if (hint == PositionAtCenter) {
|
---|
2009 | verticalScrollBar()->setValue(verticalPosition - ((viewportHeight - cellHeight) / 2));
|
---|
2010 | }
|
---|
2011 | }
|
---|
2012 |
|
---|
2013 | d->setDirtyRegion(visualRect(index));
|
---|
2014 | }
|
---|
2015 |
|
---|
2016 | /*!
|
---|
2017 | This slot is called to change the height of the given \a row. The
|
---|
2018 | old height is specified by \a oldHeight, and the new height by \a
|
---|
2019 | newHeight.
|
---|
2020 |
|
---|
2021 | \sa columnResized()
|
---|
2022 | */
|
---|
2023 | void QTableView::rowResized(int row, int, int)
|
---|
2024 | {
|
---|
2025 | Q_D(QTableView);
|
---|
2026 | d->rowsToUpdate.append(row);
|
---|
2027 | if (d->rowResizeTimerID == 0)
|
---|
2028 | d->rowResizeTimerID = startTimer(0);
|
---|
2029 | }
|
---|
2030 |
|
---|
2031 | /*!
|
---|
2032 | This slot is called to change the width of the given \a column.
|
---|
2033 | The old width is specified by \a oldWidth, and the new width by \a
|
---|
2034 | newWidth.
|
---|
2035 |
|
---|
2036 | \sa rowResized()
|
---|
2037 | */
|
---|
2038 | void QTableView::columnResized(int column, int, int)
|
---|
2039 | {
|
---|
2040 | Q_D(QTableView);
|
---|
2041 | d->columnsToUpdate.append(column);
|
---|
2042 | if (d->columnResizeTimerID == 0)
|
---|
2043 | d->columnResizeTimerID = startTimer(0);
|
---|
2044 | }
|
---|
2045 |
|
---|
2046 | /*!
|
---|
2047 | \reimp
|
---|
2048 | */
|
---|
2049 | void QTableView::timerEvent(QTimerEvent *event)
|
---|
2050 | {
|
---|
2051 | Q_D(QTableView);
|
---|
2052 |
|
---|
2053 | if (event->timerId() == d->columnResizeTimerID) {
|
---|
2054 | updateGeometries();
|
---|
2055 | killTimer(d->columnResizeTimerID);
|
---|
2056 | d->columnResizeTimerID = 0;
|
---|
2057 |
|
---|
2058 | QRect rect;
|
---|
2059 | int viewportHeight = d->viewport->height();
|
---|
2060 | int viewportWidth = d->viewport->width();
|
---|
2061 | if (d->hasSpans() && d->spansIntersectColumns(d->columnsToUpdate)) {
|
---|
2062 | rect = QRect(0, 0, viewportWidth, viewportHeight);
|
---|
2063 | } else {
|
---|
2064 | for (int i = d->columnsToUpdate.size()-1; i >= 0; --i) {
|
---|
2065 | int column = d->columnsToUpdate.at(i);
|
---|
2066 | int x = columnViewportPosition(column);
|
---|
2067 | if (isRightToLeft())
|
---|
2068 | rect |= QRect(0, 0, x + columnWidth(column), viewportHeight);
|
---|
2069 | else
|
---|
2070 | rect |= QRect(x, 0, viewportWidth - x, viewportHeight);
|
---|
2071 | }
|
---|
2072 | }
|
---|
2073 |
|
---|
2074 | d->viewport->update(rect.normalized());
|
---|
2075 | d->columnsToUpdate.clear();
|
---|
2076 | }
|
---|
2077 |
|
---|
2078 | if (event->timerId() == d->rowResizeTimerID) {
|
---|
2079 | updateGeometries();
|
---|
2080 | killTimer(d->rowResizeTimerID);
|
---|
2081 | d->rowResizeTimerID = 0;
|
---|
2082 |
|
---|
2083 | int viewportHeight = d->viewport->height();
|
---|
2084 | int viewportWidth = d->viewport->width();
|
---|
2085 | int top;
|
---|
2086 | if (d->hasSpans() && d->spansIntersectRows(d->rowsToUpdate)) {
|
---|
2087 | top = 0;
|
---|
2088 | } else {
|
---|
2089 | top = viewportHeight;
|
---|
2090 | for (int i = d->rowsToUpdate.size()-1; i >= 0; --i) {
|
---|
2091 | int y = rowViewportPosition(d->rowsToUpdate.at(i));
|
---|
2092 | top = qMin(top, y);
|
---|
2093 | }
|
---|
2094 | }
|
---|
2095 |
|
---|
2096 | d->viewport->update(QRect(0, top, viewportWidth, viewportHeight - top));
|
---|
2097 | d->rowsToUpdate.clear();
|
---|
2098 | }
|
---|
2099 |
|
---|
2100 | QAbstractItemView::timerEvent(event);
|
---|
2101 | }
|
---|
2102 |
|
---|
2103 | /*!
|
---|
2104 | This slot is called to change the index of the given \a row in the
|
---|
2105 | table view. The old index is specified by \a oldIndex, and the new
|
---|
2106 | index by \a newIndex.
|
---|
2107 |
|
---|
2108 | \sa columnMoved()
|
---|
2109 | */
|
---|
2110 | void QTableView::rowMoved(int, int oldIndex, int newIndex)
|
---|
2111 | {
|
---|
2112 | Q_D(QTableView);
|
---|
2113 |
|
---|
2114 | updateGeometries();
|
---|
2115 | int logicalOldIndex = d->verticalHeader->logicalIndex(oldIndex);
|
---|
2116 | int logicalNewIndex = d->verticalHeader->logicalIndex(newIndex);
|
---|
2117 | if (d->hasSpans() && (d->spansIntersectRow(logicalOldIndex) || d->spansIntersectRow(logicalNewIndex))) {
|
---|
2118 | d->viewport->update();
|
---|
2119 | } else {
|
---|
2120 | int oldTop = rowViewportPosition(logicalOldIndex);
|
---|
2121 | int newTop = rowViewportPosition(logicalNewIndex);
|
---|
2122 | int oldBottom = oldTop + rowHeight(logicalOldIndex);
|
---|
2123 | int newBottom = newTop + rowHeight(logicalNewIndex);
|
---|
2124 | int top = qMin(oldTop, newTop);
|
---|
2125 | int bottom = qMax(oldBottom, newBottom);
|
---|
2126 | int height = bottom - top;
|
---|
2127 | d->viewport->update(0, top, d->viewport->width(), height);
|
---|
2128 | }
|
---|
2129 | }
|
---|
2130 |
|
---|
2131 | /*!
|
---|
2132 | This slot is called to change the index of the given \a column in
|
---|
2133 | the table view. The old index is specified by \a oldIndex, and
|
---|
2134 | the new index by \a newIndex.
|
---|
2135 |
|
---|
2136 | \sa rowMoved()
|
---|
2137 | */
|
---|
2138 | void QTableView::columnMoved(int, int oldIndex, int newIndex)
|
---|
2139 | {
|
---|
2140 | Q_D(QTableView);
|
---|
2141 |
|
---|
2142 | updateGeometries();
|
---|
2143 | int logicalOldIndex = d->horizontalHeader->logicalIndex(oldIndex);
|
---|
2144 | int logicalNewIndex = d->horizontalHeader->logicalIndex(newIndex);
|
---|
2145 | if (d->hasSpans() && (d->spansIntersectColumn(logicalOldIndex) || d->spansIntersectColumn(logicalNewIndex))) {
|
---|
2146 | d->viewport->update();
|
---|
2147 | } else {
|
---|
2148 | int oldLeft = columnViewportPosition(logicalOldIndex);
|
---|
2149 | int newLeft = columnViewportPosition(logicalNewIndex);
|
---|
2150 | int oldRight = oldLeft + columnWidth(logicalOldIndex);
|
---|
2151 | int newRight = newLeft + columnWidth(logicalNewIndex);
|
---|
2152 | int left = qMin(oldLeft, newLeft);
|
---|
2153 | int right = qMax(oldRight, newRight);
|
---|
2154 | int width = right - left;
|
---|
2155 | d->viewport->update(left, 0, width, d->viewport->height());
|
---|
2156 | }
|
---|
2157 | }
|
---|
2158 |
|
---|
2159 | /*!
|
---|
2160 | Selects the given \a row in the table view if the current
|
---|
2161 | SelectionMode and SelectionBehavior allows rows to be selected.
|
---|
2162 |
|
---|
2163 | \sa selectColumn()
|
---|
2164 | */
|
---|
2165 | void QTableView::selectRow(int row)
|
---|
2166 | {
|
---|
2167 | Q_D(QTableView);
|
---|
2168 | d->selectRow(row, true);
|
---|
2169 | }
|
---|
2170 |
|
---|
2171 | /*!
|
---|
2172 | Selects the given \a column in the table view if the current
|
---|
2173 | SelectionMode and SelectionBehavior allows columns to be selected.
|
---|
2174 |
|
---|
2175 | \sa selectRow()
|
---|
2176 | */
|
---|
2177 | void QTableView::selectColumn(int column)
|
---|
2178 | {
|
---|
2179 | Q_D(QTableView);
|
---|
2180 | d->selectColumn(column, true);
|
---|
2181 | }
|
---|
2182 |
|
---|
2183 | /*!
|
---|
2184 | Hide the given \a row.
|
---|
2185 |
|
---|
2186 | \sa showRow() hideColumn()
|
---|
2187 | */
|
---|
2188 | void QTableView::hideRow(int row)
|
---|
2189 | {
|
---|
2190 | Q_D(QTableView);
|
---|
2191 | d->verticalHeader->hideSection(row);
|
---|
2192 | }
|
---|
2193 |
|
---|
2194 | /*!
|
---|
2195 | Hide the given \a column.
|
---|
2196 |
|
---|
2197 | \sa showColumn() hideRow()
|
---|
2198 | */
|
---|
2199 | void QTableView::hideColumn(int column)
|
---|
2200 | {
|
---|
2201 | Q_D(QTableView);
|
---|
2202 | d->horizontalHeader->hideSection(column);
|
---|
2203 | }
|
---|
2204 |
|
---|
2205 | /*!
|
---|
2206 | Show the given \a row.
|
---|
2207 |
|
---|
2208 | \sa hideRow() showColumn()
|
---|
2209 | */
|
---|
2210 | void QTableView::showRow(int row)
|
---|
2211 | {
|
---|
2212 | Q_D(QTableView);
|
---|
2213 | d->verticalHeader->showSection(row);
|
---|
2214 | }
|
---|
2215 |
|
---|
2216 | /*!
|
---|
2217 | Show the given \a column.
|
---|
2218 |
|
---|
2219 | \sa hideColumn() showRow()
|
---|
2220 | */
|
---|
2221 | void QTableView::showColumn(int column)
|
---|
2222 | {
|
---|
2223 | Q_D(QTableView);
|
---|
2224 | d->horizontalHeader->showSection(column);
|
---|
2225 | }
|
---|
2226 |
|
---|
2227 | /*!
|
---|
2228 | Resizes the given \a row based on the size hints of the delegate
|
---|
2229 | used to render each item in the row.
|
---|
2230 | */
|
---|
2231 | void QTableView::resizeRowToContents(int row)
|
---|
2232 | {
|
---|
2233 | Q_D(QTableView);
|
---|
2234 | int content = sizeHintForRow(row);
|
---|
2235 | int header = d->verticalHeader->sectionSizeHint(row);
|
---|
2236 | d->verticalHeader->resizeSection(row, qMax(content, header));
|
---|
2237 | }
|
---|
2238 |
|
---|
2239 | /*!
|
---|
2240 | Resizes all rows based on the size hints of the delegate
|
---|
2241 | used to render each item in the rows.
|
---|
2242 | */
|
---|
2243 | void QTableView::resizeRowsToContents()
|
---|
2244 | {
|
---|
2245 | Q_D(QTableView);
|
---|
2246 | d->verticalHeader->resizeSections(QHeaderView::ResizeToContents);
|
---|
2247 | }
|
---|
2248 |
|
---|
2249 | /*!
|
---|
2250 | Resizes the given \a column based on the size hints of the delegate
|
---|
2251 | used to render each item in the column.
|
---|
2252 |
|
---|
2253 | \note Only visible columns will be resized. Reimplement sizeHintForColumn()
|
---|
2254 | to resize hidden columns as well.
|
---|
2255 | */
|
---|
2256 | void QTableView::resizeColumnToContents(int column)
|
---|
2257 | {
|
---|
2258 | Q_D(QTableView);
|
---|
2259 | int content = sizeHintForColumn(column);
|
---|
2260 | int header = d->horizontalHeader->sectionSizeHint(column);
|
---|
2261 | d->horizontalHeader->resizeSection(column, qMax(content, header));
|
---|
2262 | }
|
---|
2263 |
|
---|
2264 | /*!
|
---|
2265 | Resizes all columns based on the size hints of the delegate
|
---|
2266 | used to render each item in the columns.
|
---|
2267 | */
|
---|
2268 | void QTableView::resizeColumnsToContents()
|
---|
2269 | {
|
---|
2270 | Q_D(QTableView);
|
---|
2271 | d->horizontalHeader->resizeSections(QHeaderView::ResizeToContents);
|
---|
2272 | }
|
---|
2273 |
|
---|
2274 | /*!
|
---|
2275 | \obsolete
|
---|
2276 | \overload
|
---|
2277 |
|
---|
2278 | Sorts the model by the values in the given \a column.
|
---|
2279 | */
|
---|
2280 | void QTableView::sortByColumn(int column)
|
---|
2281 | {
|
---|
2282 | Q_D(QTableView);
|
---|
2283 | if (column == -1)
|
---|
2284 | return;
|
---|
2285 | d->model->sort(column, d->horizontalHeader->sortIndicatorOrder());
|
---|
2286 | }
|
---|
2287 |
|
---|
2288 | /*!
|
---|
2289 | \since 4.2
|
---|
2290 |
|
---|
2291 | Sorts the model by the values in the given \a column in the given \a order.
|
---|
2292 |
|
---|
2293 | \sa sortingEnabled
|
---|
2294 | */
|
---|
2295 | void QTableView::sortByColumn(int column, Qt::SortOrder order)
|
---|
2296 | {
|
---|
2297 | Q_D(QTableView);
|
---|
2298 | d->horizontalHeader->setSortIndicator(column, order);
|
---|
2299 | sortByColumn(column);
|
---|
2300 | }
|
---|
2301 |
|
---|
2302 | /*!
|
---|
2303 | \internal
|
---|
2304 | */
|
---|
2305 | void QTableView::verticalScrollbarAction(int action)
|
---|
2306 | {
|
---|
2307 | QAbstractItemView::verticalScrollbarAction(action);
|
---|
2308 | }
|
---|
2309 |
|
---|
2310 | /*!
|
---|
2311 | \internal
|
---|
2312 | */
|
---|
2313 | void QTableView::horizontalScrollbarAction(int action)
|
---|
2314 | {
|
---|
2315 | QAbstractItemView::horizontalScrollbarAction(action);
|
---|
2316 | }
|
---|
2317 |
|
---|
2318 | /*!
|
---|
2319 | \reimp
|
---|
2320 | */
|
---|
2321 | bool QTableView::isIndexHidden(const QModelIndex &index) const
|
---|
2322 | {
|
---|
2323 | Q_D(const QTableView);
|
---|
2324 | Q_ASSERT(d->isIndexValid(index));
|
---|
2325 | if (isRowHidden(index.row()) || isColumnHidden(index.column()))
|
---|
2326 | return true;
|
---|
2327 | if (d->hasSpans()) {
|
---|
2328 | QTableViewPrivate::Span span = d->span(index.row(), index.column());
|
---|
2329 | return !((span.top() == index.row()) && (span.left() == index.column()));
|
---|
2330 | }
|
---|
2331 | return false;
|
---|
2332 | }
|
---|
2333 |
|
---|
2334 | /*!
|
---|
2335 | \fn void QTableView::setSpan(int row, int column, int rowSpanCount, int columnSpanCount)
|
---|
2336 | \since 4.2
|
---|
2337 |
|
---|
2338 | Sets the span of the table element at (\a row, \a column) to the number of
|
---|
2339 | rows and columns specified by (\a rowSpanCount, \a columnSpanCount).
|
---|
2340 |
|
---|
2341 | \sa rowSpan(), columnSpan()
|
---|
2342 | */
|
---|
2343 | void QTableView::setSpan(int row, int column, int rowSpan, int columnSpan)
|
---|
2344 | {
|
---|
2345 | Q_D(QTableView);
|
---|
2346 | if (row < 0 || column < 0 || rowSpan < 0 || columnSpan < 0)
|
---|
2347 | return;
|
---|
2348 | d->setSpan(row, column, rowSpan, columnSpan);
|
---|
2349 | d->viewport->update();
|
---|
2350 | }
|
---|
2351 |
|
---|
2352 | /*!
|
---|
2353 | \since 4.2
|
---|
2354 |
|
---|
2355 | Returns the row span of the table element at (\a row, \a column).
|
---|
2356 | The default is 1.
|
---|
2357 |
|
---|
2358 | \sa setSpan(), columnSpan()
|
---|
2359 | */
|
---|
2360 | int QTableView::rowSpan(int row, int column) const
|
---|
2361 | {
|
---|
2362 | Q_D(const QTableView);
|
---|
2363 | return d->rowSpan(row, column);
|
---|
2364 | }
|
---|
2365 |
|
---|
2366 | /*!
|
---|
2367 | \since 4.2
|
---|
2368 |
|
---|
2369 | Returns the column span of the table element at (\a row, \a
|
---|
2370 | column). The default is 1.
|
---|
2371 |
|
---|
2372 | \sa setSpan(), rowSpan()
|
---|
2373 | */
|
---|
2374 | int QTableView::columnSpan(int row, int column) const
|
---|
2375 | {
|
---|
2376 | Q_D(const QTableView);
|
---|
2377 | return d->columnSpan(row, column);
|
---|
2378 | }
|
---|
2379 |
|
---|
2380 | /*!
|
---|
2381 | \since 4.4
|
---|
2382 |
|
---|
2383 | Removes all row and column spans in the table view.
|
---|
2384 |
|
---|
2385 | \sa setSpan()
|
---|
2386 | */
|
---|
2387 |
|
---|
2388 | void QTableView::clearSpans()
|
---|
2389 | {
|
---|
2390 | Q_D(QTableView);
|
---|
2391 | d->spans.clear();
|
---|
2392 | d->viewport->update();
|
---|
2393 | }
|
---|
2394 |
|
---|
2395 | void QTableViewPrivate::_q_selectRow(int row)
|
---|
2396 | {
|
---|
2397 | selectRow(row, false);
|
---|
2398 | }
|
---|
2399 |
|
---|
2400 | void QTableViewPrivate::_q_selectColumn(int column)
|
---|
2401 | {
|
---|
2402 | selectColumn(column, false);
|
---|
2403 | }
|
---|
2404 |
|
---|
2405 | void QTableViewPrivate::selectRow(int row, bool anchor)
|
---|
2406 | {
|
---|
2407 | Q_Q(QTableView);
|
---|
2408 |
|
---|
2409 | if (q->selectionBehavior() == QTableView::SelectColumns
|
---|
2410 | || (q->selectionMode() == QTableView::SingleSelection
|
---|
2411 | && q->selectionBehavior() == QTableView::SelectItems))
|
---|
2412 | return;
|
---|
2413 |
|
---|
2414 | if (row >= 0 && row < model->rowCount(root)) {
|
---|
2415 | int column = horizontalHeader->logicalIndexAt(q->isRightToLeft() ? viewport->width() : 0);
|
---|
2416 | QModelIndex index = model->index(row, column, root);
|
---|
2417 | QItemSelectionModel::SelectionFlags command = q->selectionCommand(index);
|
---|
2418 | selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
|
---|
2419 | if ((!(command & QItemSelectionModel::Current) && anchor)
|
---|
2420 | || (q->selectionMode() == QTableView::SingleSelection))
|
---|
2421 | rowSectionAnchor = row;
|
---|
2422 | QModelIndex tl = model->index(qMin(rowSectionAnchor, row), 0, root);
|
---|
2423 | QModelIndex br = model->index(qMax(rowSectionAnchor, row), model->columnCount(root) - 1, root);
|
---|
2424 | if (verticalHeader->sectionsMoved() && tl.row() != br.row())
|
---|
2425 | q->setSelection(q->visualRect(tl)|q->visualRect(br), command);
|
---|
2426 | else
|
---|
2427 | selectionModel->select(QItemSelection(tl, br), command);
|
---|
2428 | }
|
---|
2429 | }
|
---|
2430 |
|
---|
2431 | void QTableViewPrivate::selectColumn(int column, bool anchor)
|
---|
2432 | {
|
---|
2433 | Q_Q(QTableView);
|
---|
2434 |
|
---|
2435 | if (q->selectionBehavior() == QTableView::SelectRows
|
---|
2436 | || (q->selectionMode() == QTableView::SingleSelection
|
---|
2437 | && q->selectionBehavior() == QTableView::SelectItems))
|
---|
2438 | return;
|
---|
2439 |
|
---|
2440 | if (column >= 0 && column < model->columnCount(root)) {
|
---|
2441 | int row = verticalHeader->logicalIndexAt(0);
|
---|
2442 | QModelIndex index = model->index(row, column, root);
|
---|
2443 | QItemSelectionModel::SelectionFlags command = q->selectionCommand(index);
|
---|
2444 | selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
|
---|
2445 | if ((!(command & QItemSelectionModel::Current) && anchor)
|
---|
2446 | || (q->selectionMode() == QTableView::SingleSelection))
|
---|
2447 | columnSectionAnchor = column;
|
---|
2448 | QModelIndex tl = model->index(0, qMin(columnSectionAnchor, column), root);
|
---|
2449 | QModelIndex br = model->index(model->rowCount(root) - 1,
|
---|
2450 | qMax(columnSectionAnchor, column), root);
|
---|
2451 | if (horizontalHeader->sectionsMoved() && tl.column() != br.column())
|
---|
2452 | q->setSelection(q->visualRect(tl)|q->visualRect(br), command);
|
---|
2453 | else
|
---|
2454 | selectionModel->select(QItemSelection(tl, br), command);
|
---|
2455 | }
|
---|
2456 | }
|
---|
2457 |
|
---|
2458 | /*!
|
---|
2459 | \reimp
|
---|
2460 | */
|
---|
2461 | void QTableView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
---|
2462 | {
|
---|
2463 | #ifndef QT_NO_ACCESSIBILITY
|
---|
2464 | if (QAccessible::isActive()) {
|
---|
2465 | if (current.isValid()) {
|
---|
2466 | int entry = visualIndex(current) + 1;
|
---|
2467 | if (horizontalHeader())
|
---|
2468 | ++entry;
|
---|
2469 | QAccessible::updateAccessibility(viewport(), entry, QAccessible::Focus);
|
---|
2470 | }
|
---|
2471 | }
|
---|
2472 | #endif
|
---|
2473 | QAbstractItemView::currentChanged(current, previous);
|
---|
2474 | }
|
---|
2475 |
|
---|
2476 | /*!
|
---|
2477 | \reimp
|
---|
2478 | */
|
---|
2479 | void QTableView::selectionChanged(const QItemSelection &selected,
|
---|
2480 | const QItemSelection &deselected)
|
---|
2481 | {
|
---|
2482 | #ifndef QT_NO_ACCESSIBILITY
|
---|
2483 | if (QAccessible::isActive()) {
|
---|
2484 | // ### does not work properly for selection ranges.
|
---|
2485 | QModelIndex sel = selected.indexes().value(0);
|
---|
2486 | if (sel.isValid()) {
|
---|
2487 | int entry = visualIndex(sel);
|
---|
2488 | if (horizontalHeader())
|
---|
2489 | ++entry;
|
---|
2490 | QAccessible::updateAccessibility(viewport(), entry, QAccessible::Selection);
|
---|
2491 | }
|
---|
2492 | QModelIndex desel = deselected.indexes().value(0);
|
---|
2493 | if (desel.isValid()) {
|
---|
2494 | int entry = visualIndex(sel);
|
---|
2495 | if (horizontalHeader())
|
---|
2496 | ++entry;
|
---|
2497 | QAccessible::updateAccessibility(viewport(), entry, QAccessible::SelectionRemove);
|
---|
2498 | }
|
---|
2499 | }
|
---|
2500 | #endif
|
---|
2501 | QAbstractItemView::selectionChanged(selected, deselected);
|
---|
2502 | }
|
---|
2503 |
|
---|
2504 | int QTableView::visualIndex(const QModelIndex &index) const
|
---|
2505 | {
|
---|
2506 | return index.row();
|
---|
2507 | }
|
---|
2508 |
|
---|
2509 | QT_END_NAMESPACE
|
---|
2510 |
|
---|
2511 | #include "qtableview.moc"
|
---|
2512 |
|
---|
2513 | #include "moc_qtableview.cpp"
|
---|
2514 |
|
---|
2515 | #endif // QT_NO_TABLEVIEW
|
---|