diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2011-05-07 00:02:01 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@nokia.com> | 2011-05-07 00:02:01 +0200 |
commit | f67b8df3ebdba2d398b9cce686b7c644adffff08 (patch) | |
tree | 062dd469f7cf8daa01a32d3e7b767b8fbdb7573a /src/gui/itemviews/qtableview.cpp | |
parent | 32ce4fe9e6a94e77828e976776cf08da85254ff2 (diff) |
library split
Diffstat (limited to 'src/gui/itemviews/qtableview.cpp')
-rw-r--r-- | src/gui/itemviews/qtableview.cpp | 3198 |
1 files changed, 0 insertions, 3198 deletions
diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp deleted file mode 100644 index e494ee5564..0000000000 --- a/src/gui/itemviews/qtableview.cpp +++ /dev/null @@ -1,3198 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qtableview.h" - -#ifndef QT_NO_TABLEVIEW -#include <qheaderview.h> -#include <qitemdelegate.h> -#include <qapplication.h> -#include <qpainter.h> -#include <qstyle.h> -#include <qsize.h> -#include <qevent.h> -#include <qbitarray.h> -#include <qscrollbar.h> -#include <qabstractbutton.h> -#include <private/qtableview_p.h> -#ifndef QT_NO_ACCESSIBILITY -#include <qaccessible.h> -#endif - -QT_BEGIN_NAMESPACE - -/** \internal - Add a span to the collection. the collection takes the ownership. - */ -void QSpanCollection::addSpan(QSpanCollection::Span *span) -{ - spans.append(span); - Index::iterator it_y = index.lowerBound(-span->top()); - if (it_y == index.end() || it_y.key() != -span->top()) { - //there is no spans that starts with the row in the index, so create a sublist for it. - SubIndex sub_index; - if (it_y != index.end()) { - //the previouslist is the list of spans that sarts _before_ the row of the span. - // and which may intersect this row. - const SubIndex previousList = it_y.value(); - foreach(Span *s, previousList) { - //If a subspans intersect the row, we need to split it into subspans - if(s->bottom() >= span->top()) - sub_index.insert(-s->left(), s); - } - } - it_y = index.insert(-span->top(), sub_index); - //we will insert span to *it_y in the later loop - } - - //insert the span as supspan in all the lists that intesects the span - while(-it_y.key() <= span->bottom()) { - (*it_y).insert(-span->left(), span); - if(it_y == index.begin()) - break; - --it_y; - } -} - - -/** \internal -* Has to be called after the height and width of a span is changed. -* -* old_height is the height before the change -* -* if the size of the span is now 0x0 the span will be deleted. -*/ -void QSpanCollection::updateSpan(QSpanCollection::Span *span, int old_height) -{ - if (old_height < span->height()) { - //add the span as subspan in all the lists that intersect the new covered columns - Index::iterator it_y = index.lowerBound(-(span->top() + old_height - 1)); - Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list - while (-it_y.key() <= span->bottom()) { - (*it_y).insert(-span->left(), span); - if(it_y == index.begin()) - break; - --it_y; - } - } else if (old_height > span->height()) { - //remove the span from all the subspans lists that intersect the columns not covered anymore - Index::iterator it_y = index.lowerBound(-qMax(span->bottom(), span->top())); //qMax useful if height is 0 - Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list - while (-it_y.key() <= span->top() + old_height -1) { - if (-it_y.key() > span->bottom()) { - int removed = (*it_y).remove(-span->left()); - Q_ASSERT(removed == 1); Q_UNUSED(removed); - if (it_y->isEmpty()) { - it_y = index.erase(it_y); - } - } - if(it_y == index.begin()) - break; - --it_y; - } - } - - if (span->width() == 0 && span->height() == 0) { - spans.removeOne(span); - delete span; - } -} - -/** \internal - * \return a spans that spans over cell x,y (column,row) or 0 if there is none. - */ -QSpanCollection::Span *QSpanCollection::spanAt(int x, int y) const -{ - Index::const_iterator it_y = index.lowerBound(-y); - if (it_y == index.end()) - return 0; - SubIndex::const_iterator it_x = (*it_y).lowerBound(-x); - if (it_x == (*it_y).end()) - return 0; - Span *span = *it_x; - if (span->right() >= x && span->bottom() >= y) - return span; - return 0; -} - - -/** \internal -* remove and deletes all spans inside the collection -*/ -void QSpanCollection::clear() -{ - qDeleteAll(spans); - index.clear(); - spans.clear(); -} - -/** \internal - * return a list to all the spans that spans over cells in the given rectangle - */ -QList<QSpanCollection::Span *> QSpanCollection::spansInRect(int x, int y, int w, int h) const -{ - QSet<Span *> list; - Index::const_iterator it_y = index.lowerBound(-y); - if(it_y == index.end()) - --it_y; - while(-it_y.key() <= y + h) { - SubIndex::const_iterator it_x = (*it_y).lowerBound(-x); - if (it_x == (*it_y).end()) - --it_x; - while(-it_x.key() <= x + w) { - Span *s = *it_x; - if (s->bottom() >= y && s->right() >= x) - list << s; - if (it_x == (*it_y).begin()) - break; - --it_x; - } - if(it_y == index.begin()) - break; - --it_y; - } - return list.toList(); -} - -#undef DEBUG_SPAN_UPDATE - -#ifdef DEBUG_SPAN_UPDATE -QDebug operator<<(QDebug str, const QSpanCollection::Span &span) -{ - str << "(" << span.top() << "," << span.left() << "," << span.bottom() << "," << span.right() << ")"; - return str; -} -#endif - -/** \internal -* Updates the span collection after row insertion. -*/ -void QSpanCollection::updateInsertedRows(int start, int end) -{ -#ifdef DEBUG_SPAN_UPDATE - qDebug() << Q_FUNC_INFO; - qDebug() << start << end; - qDebug() << index; -#endif - if (spans.isEmpty()) - return; - - int delta = end - start + 1; -#ifdef DEBUG_SPAN_UPDATE - qDebug("Before"); -#endif - for (SpanList::iterator it = spans.begin(); it != spans.end(); ++it) { - Span *span = *it; -#ifdef DEBUG_SPAN_UPDATE - qDebug() << span << *span; -#endif - if (span->m_bottom < start) - continue; - if (span->m_top >= start) - span->m_top += delta; - span->m_bottom += delta; - } - -#ifdef DEBUG_SPAN_UPDATE - qDebug("After"); - foreach (QSpanCollection::Span *span, spans) - qDebug() << span << *span; -#endif - - for (Index::iterator it_y = index.begin(); it_y != index.end(); ) { - int y = -it_y.key(); - if (y < start) { - ++it_y; - continue; - } - - index.insert(-y - delta, it_y.value()); - it_y = index.erase(it_y); - } -#ifdef DEBUG_SPAN_UPDATE - qDebug() << index; -#endif -} - -/** \internal -* Updates the span collection after column insertion. -*/ -void QSpanCollection::updateInsertedColumns(int start, int end) -{ -#ifdef DEBUG_SPAN_UPDATE - qDebug() << Q_FUNC_INFO; - qDebug() << start << end; - qDebug() << index; -#endif - if (spans.isEmpty()) - return; - - int delta = end - start + 1; -#ifdef DEBUG_SPAN_UPDATE - qDebug("Before"); -#endif - for (SpanList::iterator it = spans.begin(); it != spans.end(); ++it) { - Span *span = *it; -#ifdef DEBUG_SPAN_UPDATE - qDebug() << span << *span; -#endif - if (span->m_right < start) - continue; - if (span->m_left >= start) - span->m_left += delta; - span->m_right += delta; - } - -#ifdef DEBUG_SPAN_UPDATE - qDebug("After"); - foreach (QSpanCollection::Span *span, spans) - qDebug() << span << *span; -#endif - - for (Index::iterator it_y = index.begin(); it_y != index.end(); ++it_y) { - SubIndex &subindex = it_y.value(); - for (SubIndex::iterator it = subindex.begin(); it != subindex.end(); ) { - int x = -it.key(); - if (x < start) { - ++it; - continue; - } - subindex.insert(-x - delta, it.value()); - it = subindex.erase(it); - } - } -#ifdef DEBUG_SPAN_UPDATE - qDebug() << index; -#endif -} - -/** \internal -* Cleans a subindex from to be deleted spans. The update argument is used -* to move the spans inside the subindex, in case their anchor changed. -* \return true if no span in this subindex starts at y, and should thus be deleted. -*/ -bool QSpanCollection::cleanSpanSubIndex(QSpanCollection::SubIndex &subindex, int y, bool update) -{ - if (subindex.isEmpty()) - return true; - - bool should_be_deleted = true; - SubIndex::iterator it = subindex.end(); - do { - --it; - int x = -it.key(); - Span *span = it.value(); - if (span->will_be_deleted) { - it = subindex.erase(it); - continue; - } - if (update && span->m_left != x) { - subindex.insert(-span->m_left, span); - it = subindex.erase(it); - } - if (should_be_deleted && span->m_top == y) - should_be_deleted = false; - } while (it != subindex.begin()); - - return should_be_deleted; -} - -/** \internal -* Updates the span collection after row removal. -*/ -void QSpanCollection::updateRemovedRows(int start, int end) -{ -#ifdef DEBUG_SPAN_UPDATE - qDebug() << Q_FUNC_INFO; - qDebug() << start << end; - qDebug() << index; -#endif - if (spans.isEmpty()) - return; - - SpanList spansToBeDeleted; - int delta = end - start + 1; -#ifdef DEBUG_SPAN_UPDATE - qDebug("Before"); -#endif - for (SpanList::iterator it = spans.begin(); it != spans.end(); ) { - Span *span = *it; -#ifdef DEBUG_SPAN_UPDATE - qDebug() << span << *span; -#endif - if (span->m_bottom < start) { - ++it; - continue; - } - if (span->m_top < start) { - if (span->m_bottom <= end) - span->m_bottom = start - 1; - else - span->m_bottom -= delta; - } else { - if (span->m_bottom > end) { - if (span->m_top <= end) - span->m_top = start; - else - span->m_top -= delta; - span->m_bottom -= delta; - } else { - span->will_be_deleted = true; - } - } - if (span->m_top == span->m_bottom && span->m_left == span->m_right) - span->will_be_deleted = true; - if (span->will_be_deleted) { - spansToBeDeleted.append(span); - it = spans.erase(it); - } else { - ++it; - } - } - -#ifdef DEBUG_SPAN_UPDATE - qDebug("After"); - foreach (QSpanCollection::Span *span, spans) - qDebug() << span << *span; -#endif - if (spans.isEmpty()) { - qDeleteAll(spansToBeDeleted); - index.clear(); - return; - } - - Index::iterator it_y = index.end(); - do { - --it_y; - int y = -it_y.key(); - SubIndex &subindex = it_y.value(); - if (y < start) { - if (cleanSpanSubIndex(subindex, y)) - it_y = index.erase(it_y); - } else if (y >= start && y <= end) { - bool span_at_start = false; - SubIndex spansToBeMoved; - for (SubIndex::iterator it = subindex.begin(); it != subindex.end(); ++it) { - Span *span = it.value(); - if (span->will_be_deleted) - continue; - if (!span_at_start && span->m_top == start) - span_at_start = true; - spansToBeMoved.insert(it.key(), span); - } - - if (y == start && span_at_start) - subindex.clear(); - else - it_y = index.erase(it_y); - - if (span_at_start) { - Index::iterator it_start; - if (y == start) - it_start = it_y; - else { - it_start = index.find(-start); - if (it_start == index.end()) - it_start = index.insert(-start, SubIndex()); - } - SubIndex &start_subindex = it_start.value(); - for (SubIndex::iterator it = spansToBeMoved.begin(); it != spansToBeMoved.end(); ++it) - start_subindex.insert(it.key(), it.value()); - } - } else { - if (y == end + 1) { - Index::iterator it_top = index.find(-y + delta); - if (it_top == index.end()) - it_top = index.insert(-y + delta, SubIndex()); - for (SubIndex::iterator it = subindex.begin(); it != subindex.end(); ) { - Span *span = it.value(); - if (!span->will_be_deleted) - it_top.value().insert(it.key(), span); - ++it; - } - } else { - index.insert(-y + delta, subindex); - } - it_y = index.erase(it_y); - } - } while (it_y != index.begin()); - -#ifdef DEBUG_SPAN_UPDATE - qDebug() << index; - qDebug("Deleted"); - foreach (QSpanCollection::Span *span, spansToBeDeleted) - qDebug() << span << *span; -#endif - qDeleteAll(spansToBeDeleted); -} - -/** \internal -* Updates the span collection after column removal. -*/ -void QSpanCollection::updateRemovedColumns(int start, int end) -{ -#ifdef DEBUG_SPAN_UPDATE - qDebug() << Q_FUNC_INFO; - qDebug() << start << end; - qDebug() << index; -#endif - if (spans.isEmpty()) - return; - - SpanList toBeDeleted; - int delta = end - start + 1; -#ifdef DEBUG_SPAN_UPDATE - qDebug("Before"); -#endif - for (SpanList::iterator it = spans.begin(); it != spans.end(); ) { - Span *span = *it; -#ifdef DEBUG_SPAN_UPDATE - qDebug() << span << *span; -#endif - if (span->m_right < start) { - ++it; - continue; - } - if (span->m_left < start) { - if (span->m_right <= end) - span->m_right = start - 1; - else - span->m_right -= delta; - } else { - if (span->m_right > end) { - if (span->m_left <= end) - span->m_left = start; - else - span->m_left -= delta; - span->m_right -= delta; - } else { - span->will_be_deleted = true; - } - } - if (span->m_top == span->m_bottom && span->m_left == span->m_right) - span->will_be_deleted = true; - if (span->will_be_deleted) { - toBeDeleted.append(span); - it = spans.erase(it); - } else { - ++it; - } - } - -#ifdef DEBUG_SPAN_UPDATE - qDebug("After"); - foreach (QSpanCollection::Span *span, spans) - qDebug() << span << *span; -#endif - if (spans.isEmpty()) { - qDeleteAll(toBeDeleted); - index.clear(); - return; - } - - for (Index::iterator it_y = index.begin(); it_y != index.end(); ) { - int y = -it_y.key(); - if (cleanSpanSubIndex(it_y.value(), y, true)) - it_y = index.erase(it_y); - else - ++it_y; - } - -#ifdef DEBUG_SPAN_UPDATE - qDebug() << index; - qDebug("Deleted"); - foreach (QSpanCollection::Span *span, toBeDeleted) - qDebug() << span << *span; -#endif - qDeleteAll(toBeDeleted); -} - -#ifdef QT_BUILD_INTERNAL -/*! - \internal - Checks whether the span index structure is self-consistent, and consistent with the spans list. -*/ -bool QSpanCollection::checkConsistency() const -{ - for (Index::const_iterator it_y = index.begin(); it_y != index.end(); ++it_y) { - int y = -it_y.key(); - const SubIndex &subIndex = it_y.value(); - for (SubIndex::const_iterator it = subIndex.begin(); it != subIndex.end(); ++it) { - int x = -it.key(); - Span *span = it.value(); - if (!spans.contains(span) || span->left() != x - || y < span->top() || y > span->bottom()) - return false; - } - } - - foreach (const Span *span, spans) { - if (span->width() < 1 || span->height() < 1 - || (span->width() == 1 && span->height() == 1)) - return false; - for (int y = span->top(); y <= span->bottom(); ++y) { - Index::const_iterator it_y = index.find(-y); - if (it_y == index.end()) { - if (y == span->top()) - return false; - else - continue; - } - const SubIndex &subIndex = it_y.value(); - SubIndex::const_iterator it = subIndex.find(-span->left()); - if (it == subIndex.end() || it.value() != span) - return false; - } - } - return true; -} -#endif - -class QTableCornerButton : public QAbstractButton -{ - Q_OBJECT -public: - QTableCornerButton(QWidget *parent) : QAbstractButton(parent) {} - void paintEvent(QPaintEvent*) { - QStyleOptionHeader opt; - opt.init(this); - QStyle::State state = QStyle::State_None; - if (isEnabled()) - state |= QStyle::State_Enabled; - if (isActiveWindow()) - state |= QStyle::State_Active; - if (isDown()) - state |= QStyle::State_Sunken; - opt.state = state; - opt.rect = rect(); - opt.position = QStyleOptionHeader::OnlyOneSection; - QPainter painter(this); - style()->drawControl(QStyle::CE_Header, &opt, &painter, this); - } -}; - -void QTableViewPrivate::init() -{ - Q_Q(QTableView); - - q->setEditTriggers(editTriggers|QAbstractItemView::AnyKeyPressed); - - QHeaderView *vertical = new QHeaderView(Qt::Vertical, q); - vertical->setClickable(true); - vertical->setHighlightSections(true); - q->setVerticalHeader(vertical); - - QHeaderView *horizontal = new QHeaderView(Qt::Horizontal, q); - horizontal->setClickable(true); - horizontal->setHighlightSections(true); - q->setHorizontalHeader(horizontal); - - tabKeyNavigation = true; - - cornerWidget = new QTableCornerButton(q); - cornerWidget->setFocusPolicy(Qt::NoFocus); - QObject::connect(cornerWidget, SIGNAL(clicked()), q, SLOT(selectAll())); -} - -/*! - \internal - Trims away indices that are hidden in the treeview due to hidden horizontal or vertical sections. -*/ -void QTableViewPrivate::trimHiddenSelections(QItemSelectionRange *range) const -{ - Q_ASSERT(range && range->isValid()); - - int top = range->top(); - int left = range->left(); - int bottom = range->bottom(); - int right = range->right(); - - while (bottom >= top && verticalHeader->isSectionHidden(bottom)) - --bottom; - while (right >= left && horizontalHeader->isSectionHidden(right)) - --right; - - if (top > bottom || left > right) { // everything is hidden - *range = QItemSelectionRange(); - return; - } - - while (verticalHeader->isSectionHidden(top) && top <= bottom) - ++top; - while (horizontalHeader->isSectionHidden(left) && left <= right) - ++left; - - if (top > bottom || left > right) { // everything is hidden - *range = QItemSelectionRange(); - return; - } - - QModelIndex bottomRight = model->index(bottom, right, range->parent()); - QModelIndex topLeft = model->index(top, left, range->parent()); - *range = QItemSelectionRange(topLeft, bottomRight); -} - -/*! - \internal - Sets the span for the cell at (\a row, \a column). -*/ -void QTableViewPrivate::setSpan(int row, int column, int rowSpan, int columnSpan) -{ - if (row < 0 || column < 0 || rowSpan <= 0 || columnSpan <= 0) { - qWarning() << "QTableView::setSpan: invalid span given: (" << row << ',' << column << ',' << rowSpan << ',' << columnSpan << ')'; - return; - } - QSpanCollection::Span *sp = spans.spanAt(column, row); - if (sp) { - if (sp->top() != row || sp->left() != column) { - qWarning() << "QTableView::setSpan: span cannot overlap"; - return; - } - if (rowSpan == 1 && columnSpan == 1) { - rowSpan = columnSpan = 0; - } - const int old_height = sp->height(); - sp->m_bottom = row + rowSpan - 1; - sp->m_right = column + columnSpan - 1; - spans.updateSpan(sp, old_height); - return; - } else if (rowSpan == 1 && columnSpan == 1) { - qWarning() << "QTableView::setSpan: single cell span won't be added"; - return; - } - sp = new QSpanCollection::Span(row, column, rowSpan, columnSpan); - spans.addSpan(sp); -} - -/*! - \internal - Gets the span information for the cell at (\a row, \a column). -*/ -QSpanCollection::Span QTableViewPrivate::span(int row, int column) const -{ - QSpanCollection::Span *sp = spans.spanAt(column, row); - if (sp) - return *sp; - - return QSpanCollection::Span(row, column, 1, 1); -} - -/*! - \internal - Returns the logical index of the last section that's part of the span. -*/ -int QTableViewPrivate::sectionSpanEndLogical(const QHeaderView *header, int logical, int span) const -{ - int visual = header->visualIndex(logical); - for (int i = 1; i < span; ) { - if (++visual >= header->count()) - break; - logical = header->logicalIndex(visual); - ++i; - } - return logical; -} - -/*! - \internal - Returns the size of the span starting at logical index \a logical - and spanning \a span sections. -*/ -int QTableViewPrivate::sectionSpanSize(const QHeaderView *header, int logical, int span) const -{ - int endLogical = sectionSpanEndLogical(header, logical, span); - return header->sectionPosition(endLogical) - - header->sectionPosition(logical) - + header->sectionSize(endLogical); -} - -/*! - \internal - Returns true if the section at logical index \a logical is part of the span - starting at logical index \a spanLogical and spanning \a span sections; - otherwise, returns false. -*/ -bool QTableViewPrivate::spanContainsSection(const QHeaderView *header, int logical, int spanLogical, int span) const -{ - if (logical == spanLogical) - return true; // it's the start of the span - int visual = header->visualIndex(spanLogical); - for (int i = 1; i < span; ) { - if (++visual >= header->count()) - break; - spanLogical = header->logicalIndex(visual); - if (logical == spanLogical) - return true; - ++i; - } - return false; -} - -/*! - \internal - Returns the visual rect for the given \a span. -*/ -QRect QTableViewPrivate::visualSpanRect(const QSpanCollection::Span &span) const -{ - Q_Q(const QTableView); - // vertical - int row = span.top(); - int rowp = verticalHeader->sectionViewportPosition(row); - int rowh = rowSpanHeight(row, span.height()); - // horizontal - int column = span.left(); - int colw = columnSpanWidth(column, span.width()); - if (q->isRightToLeft()) - column = span.right(); - int colp = horizontalHeader->sectionViewportPosition(column); - - const int i = showGrid ? 1 : 0; - if (q->isRightToLeft()) - return QRect(colp + i, rowp, colw - i, rowh - i); - return QRect(colp, rowp, colw - i, rowh - i); -} - -/*! - \internal - Draws the spanning cells within rect \a area, and clips them off as - preparation for the main drawing loop. - \a drawn is a QBitArray of visualRowCountxvisualCoulumnCount which say if particular cell has been drawn -*/ -void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter, - const QStyleOptionViewItemV4 &option, QBitArray *drawn, - int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn) -{ - bool alternateBase = false; - QRegion region = viewport->rect(); - - QList<QSpanCollection::Span *> visibleSpans; - bool sectionMoved = verticalHeader->sectionsMoved() || horizontalHeader->sectionsMoved(); - - if (!sectionMoved) { - visibleSpans = spans.spansInRect(logicalColumn(firstVisualColumn), logicalRow(firstVisualRow), - lastVisualColumn - firstVisualColumn + 1, lastVisualRow - firstVisualRow + 1); - } else { - QSet<QSpanCollection::Span *> set; - for(int x = firstVisualColumn; x <= lastVisualColumn; x++) - for(int y = firstVisualRow; y <= lastVisualRow; y++) - set.insert(spans.spanAt(x,y)); - set.remove(0); - visibleSpans = set.toList(); - } - - foreach (QSpanCollection::Span *span, visibleSpans) { - int row = span->top(); - int col = span->left(); - QModelIndex index = model->index(row, col, root); - if (!index.isValid()) - continue; - QRect rect = visualSpanRect(*span); - rect.translate(scrollDelayOffset); - if (!area.intersects(rect)) - continue; - QStyleOptionViewItemV4 opt = option; - opt.rect = rect; - alternateBase = alternatingColors && (span->top() & 1); - if (alternateBase) - opt.features |= QStyleOptionViewItemV2::Alternate; - else - opt.features &= ~QStyleOptionViewItemV2::Alternate; - drawCell(painter, opt, index); - region -= rect; - for (int r = span->top(); r <= span->bottom(); ++r) { - const int vr = visualRow(r); - if (vr < firstVisualRow || vr > lastVisualRow) - continue; - for (int c = span->left(); c <= span->right(); ++c) { - const int vc = visualColumn(c); - if (vc < firstVisualColumn || vc > lastVisualColumn) - continue; - drawn->setBit((vr - firstVisualRow) * (lastVisualColumn - firstVisualColumn + 1) - + vc - firstVisualColumn); - } - } - - } - painter->setClipRegion(region); -} - -/*! - \internal - Updates spans after row insertion. -*/ -void QTableViewPrivate::_q_updateSpanInsertedRows(const QModelIndex &parent, int start, int end) -{ - Q_UNUSED(parent) - spans.updateInsertedRows(start, end); -} - -/*! - \internal - Updates spans after column insertion. -*/ -void QTableViewPrivate::_q_updateSpanInsertedColumns(const QModelIndex &parent, int start, int end) -{ - Q_UNUSED(parent) - spans.updateInsertedColumns(start, end); -} - -/*! - \internal - Updates spans after row removal. -*/ -void QTableViewPrivate::_q_updateSpanRemovedRows(const QModelIndex &parent, int start, int end) -{ - Q_UNUSED(parent) - spans.updateRemovedRows(start, end); -} - -/*! - \internal - Updates spans after column removal. -*/ -void QTableViewPrivate::_q_updateSpanRemovedColumns(const QModelIndex &parent, int start, int end) -{ - Q_UNUSED(parent) - spans.updateRemovedColumns(start, end); -} - -/*! - \internal - Draws a table cell. -*/ -void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItemV4 &option, const QModelIndex &index) -{ - Q_Q(QTableView); - QStyleOptionViewItemV4 opt = option; - - if (selectionModel && selectionModel->isSelected(index)) - opt.state |= QStyle::State_Selected; - if (index == hover) - opt.state |= QStyle::State_MouseOver; - if (option.state & QStyle::State_Enabled) { - QPalette::ColorGroup cg; - if ((model->flags(index) & Qt::ItemIsEnabled) == 0) { - opt.state &= ~QStyle::State_Enabled; - cg = QPalette::Disabled; - } else { - cg = QPalette::Normal; - } - opt.palette.setCurrentColorGroup(cg); - } - - if (index == q->currentIndex()) { - const bool focus = (q->hasFocus() || viewport->hasFocus()) && q->currentIndex().isValid(); - if (focus) - opt.state |= QStyle::State_HasFocus; - } - - q->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, q); - - q->itemDelegate(index)->paint(painter, opt, index); -} - -/*! - \class QTableView - - \brief The QTableView class provides a default model/view - implementation of a table view. - - \ingroup model-view - \ingroup advanced - - - A QTableView implements a table view that displays items from a - model. This class is used to provide standard tables that were - previously provided by the QTable class, but using the more - flexible approach provided by Qt's model/view architecture. - - The QTableView class is one of the \l{Model/View Classes} - and is part of Qt's \l{Model/View Programming}{model/view framework}. - - QTableView implements the interfaces defined by the - QAbstractItemView class to allow it to display data provided by - models derived from the QAbstractItemModel class. - - \section1 Navigation - - You can navigate the cells in the table by clicking on a cell with the - mouse, or by using the arrow keys. Because QTableView enables - \l{QAbstractItemView::tabKeyNavigation}{tabKeyNavigation} by default, you - can also hit Tab and Backtab to move from cell to cell. - - \section1 Visual Appearance - - The table has a vertical header that can be obtained using the - verticalHeader() function, and a horizontal header that is available - through the horizontalHeader() function. The height of each row in the - table can be found by using rowHeight(); similarly, the width of - columns can be found using columnWidth(). Since both of these are plain - widgets, you can hide either of them using their hide() functions. - - Rows and columns can be hidden and shown with hideRow(), hideColumn(), - showRow(), and showColumn(). They can be selected with selectRow() - and selectColumn(). The table will show a grid depending on the - \l showGrid property. - - The items shown in a table view, like those in the other item views, are - rendered and edited using standard \l{QItemDelegate}{delegates}. However, - for some tasks it is sometimes useful to be able to insert widgets in a - table instead. Widgets are set for particular indexes with the - \l{QAbstractItemView::}{setIndexWidget()} function, and - later retrieved with \l{QAbstractItemView::}{indexWidget()}. - - \table - \row \o \inlineimage qtableview-resized.png - \o By default, the cells in a table do not expand to fill the available space. - - You can make the cells fill the available space by stretching the last - header section. Access the relevant header using horizontalHeader() - or verticalHeader() and set the header's \l{QHeaderView::}{stretchLastSection} - property. - - To distribute the available space according to the space requirement of - each column or row, call the view's resizeColumnsToContents() or - resizeRowsToContents() functions. - \endtable - - \section1 Coordinate Systems - - For some specialized forms of tables it is useful to be able to - convert between row and column indexes and widget coordinates. - The rowAt() function provides the y-coordinate within the view of the - specified row; the row index can be used to obtain a corresponding - y-coordinate with rowViewportPosition(). The columnAt() and - columnViewportPosition() functions provide the equivalent conversion - operations between x-coordinates and column indexes. - - \section1 Styles - - QTableView is styled appropriately for each platform. The following images show - how it looks on three different platforms. Go to the \l{Qt Widget Gallery} to see - its appearance in other styles. - - \table 100% - \row \o \inlineimage windowsxp-tableview.png Screenshot of a Windows XP style table view - \o \inlineimage macintosh-tableview.png Screenshot of a Macintosh style table view - \o \inlineimage plastique-tableview.png Screenshot of a Plastique style table view - \row \o A \l{Windows XP Style Widget Gallery}{Windows XP style} table view. - \o A \l{Macintosh Style Widget Gallery}{Macintosh style} table view. - \o A \l{Plastique Style Widget Gallery}{Plastique style} table view. - \endtable - - \sa QTableWidget, {View Classes}, QAbstractItemModel, QAbstractItemView, - {Chart Example}, {Pixelator Example}, {Table Model Example} -*/ - -/*! - Constructs a table view with a \a parent to represent the data. - - \sa QAbstractItemModel -*/ - -QTableView::QTableView(QWidget *parent) - : QAbstractItemView(*new QTableViewPrivate, parent) -{ - Q_D(QTableView); - d->init(); -} - -/*! - \internal -*/ -QTableView::QTableView(QTableViewPrivate &dd, QWidget *parent) - : QAbstractItemView(dd, parent) -{ - Q_D(QTableView); - d->init(); -} - -/*! - Destroys the table view. -*/ -QTableView::~QTableView() -{ -} - -/*! - \reimp -*/ -void QTableView::setModel(QAbstractItemModel *model) -{ - Q_D(QTableView); - if (model == d->model) - return; - //let's disconnect from the old model - if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) { - disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(_q_updateSpanInsertedRows(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(_q_updateSpanInsertedColumns(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_updateSpanRemovedRows(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(_q_updateSpanRemovedColumns(QModelIndex,int,int))); - } - if (model) { //and connect to the new one - connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(_q_updateSpanInsertedRows(QModelIndex,int,int))); - connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(_q_updateSpanInsertedColumns(QModelIndex,int,int))); - connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_updateSpanRemovedRows(QModelIndex,int,int))); - connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(_q_updateSpanRemovedColumns(QModelIndex,int,int))); - } - d->verticalHeader->setModel(model); - d->horizontalHeader->setModel(model); - QAbstractItemView::setModel(model); -} - -/*! - \reimp -*/ -void QTableView::setRootIndex(const QModelIndex &index) -{ - Q_D(QTableView); - if (index == d->root) { - viewport()->update(); - return; - } - d->verticalHeader->setRootIndex(index); - d->horizontalHeader->setRootIndex(index); - QAbstractItemView::setRootIndex(index); -} - -/*! - \reimp -*/ -void QTableView::setSelectionModel(QItemSelectionModel *selectionModel) -{ - Q_D(QTableView); - Q_ASSERT(selectionModel); - d->verticalHeader->setSelectionModel(selectionModel); - d->horizontalHeader->setSelectionModel(selectionModel); - QAbstractItemView::setSelectionModel(selectionModel); -} - -/*! - Returns the table view's horizontal header. - - \sa setHorizontalHeader(), verticalHeader(), QAbstractItemModel::headerData() -*/ -QHeaderView *QTableView::horizontalHeader() const -{ - Q_D(const QTableView); - return d->horizontalHeader; -} - -/*! - Returns the table view's vertical header. - - \sa setVerticalHeader(), horizontalHeader(), QAbstractItemModel::headerData() -*/ -QHeaderView *QTableView::verticalHeader() const -{ - Q_D(const QTableView); - return d->verticalHeader; -} - -/*! - Sets the widget to use for the horizontal header to \a header. - - \sa horizontalHeader() setVerticalHeader() -*/ -void QTableView::setHorizontalHeader(QHeaderView *header) -{ - Q_D(QTableView); - - if (!header || header == d->horizontalHeader) - return; - if (d->horizontalHeader && d->horizontalHeader->parent() == this) - delete d->horizontalHeader; - d->horizontalHeader = header; - d->horizontalHeader->setParent(this); - if (!d->horizontalHeader->model()) { - d->horizontalHeader->setModel(d->model); - if (d->selectionModel) - d->horizontalHeader->setSelectionModel(d->selectionModel); - } - - connect(d->horizontalHeader,SIGNAL(sectionResized(int,int,int)), - this, SLOT(columnResized(int,int,int))); - connect(d->horizontalHeader, SIGNAL(sectionMoved(int,int,int)), - this, SLOT(columnMoved(int,int,int))); - connect(d->horizontalHeader, SIGNAL(sectionCountChanged(int,int)), - this, SLOT(columnCountChanged(int,int))); - connect(d->horizontalHeader, SIGNAL(sectionPressed(int)), this, SLOT(selectColumn(int))); - connect(d->horizontalHeader, SIGNAL(sectionEntered(int)), this, SLOT(_q_selectColumn(int))); - connect(d->horizontalHeader, SIGNAL(sectionHandleDoubleClicked(int)), - this, SLOT(resizeColumnToContents(int))); - connect(d->horizontalHeader, SIGNAL(geometriesChanged()), this, SLOT(updateGeometries())); - - //update the sorting enabled states on the new header - setSortingEnabled(d->sortingEnabled); -} - -/*! - Sets the widget to use for the vertical header to \a header. - - \sa verticalHeader() setHorizontalHeader() -*/ -void QTableView::setVerticalHeader(QHeaderView *header) -{ - Q_D(QTableView); - - if (!header || header == d->verticalHeader) - return; - if (d->verticalHeader && d->verticalHeader->parent() == this) - delete d->verticalHeader; - d->verticalHeader = header; - d->verticalHeader->setParent(this); - if (!d->verticalHeader->model()) { - d->verticalHeader->setModel(d->model); - if (d->selectionModel) - d->verticalHeader->setSelectionModel(d->selectionModel); - } - - connect(d->verticalHeader, SIGNAL(sectionResized(int,int,int)), - this, SLOT(rowResized(int,int,int))); - connect(d->verticalHeader, SIGNAL(sectionMoved(int,int,int)), - this, SLOT(rowMoved(int,int,int))); - connect(d->verticalHeader, SIGNAL(sectionCountChanged(int,int)), - this, SLOT(rowCountChanged(int,int))); - connect(d->verticalHeader, SIGNAL(sectionPressed(int)), this, SLOT(selectRow(int))); - connect(d->verticalHeader, SIGNAL(sectionEntered(int)), this, SLOT(_q_selectRow(int))); - connect(d->verticalHeader, SIGNAL(sectionHandleDoubleClicked(int)), - this, SLOT(resizeRowToContents(int))); - connect(d->verticalHeader, SIGNAL(geometriesChanged()), this, SLOT(updateGeometries())); -} - -/*! - \internal - - Scroll the contents of the table view by (\a dx, \a dy). -*/ -void QTableView::scrollContentsBy(int dx, int dy) -{ - Q_D(QTableView); - - d->delayedAutoScroll.stop(); // auto scroll was canceled by the user scrolling - - dx = isRightToLeft() ? -dx : dx; - if (dx) { - if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) { - int oldOffset = d->horizontalHeader->offset(); - if (horizontalScrollBar()->value() == horizontalScrollBar()->maximum()) - d->horizontalHeader->setOffsetToLastSection(); - else - d->horizontalHeader->setOffsetToSectionPosition(horizontalScrollBar()->value()); - int newOffset = d->horizontalHeader->offset(); - dx = isRightToLeft() ? newOffset - oldOffset : oldOffset - newOffset; - } else { - d->horizontalHeader->setOffset(horizontalScrollBar()->value()); - } - } - if (dy) { - if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) { - int oldOffset = d->verticalHeader->offset(); - if (verticalScrollBar()->value() == verticalScrollBar()->maximum()) - d->verticalHeader->setOffsetToLastSection(); - else - d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value()); - int newOffset = d->verticalHeader->offset(); - dy = oldOffset - newOffset; - } else { - d->verticalHeader->setOffset(verticalScrollBar()->value()); - } - } - d->scrollContentsBy(dx, dy); - - if (d->showGrid) { - //we need to update the first line of the previous top item in the view - //because it has the grid drawn if the header is invisible. - //It is strictly related to what's done at then end of the paintEvent - if (dy > 0 && d->horizontalHeader->isHidden() && d->verticalScrollMode == ScrollPerItem) { - d->viewport->update(0, dy, d->viewport->width(), dy); - } - if (dx > 0 && d->verticalHeader->isHidden() && d->horizontalScrollMode == ScrollPerItem) { - d->viewport->update(dx, 0, dx, d->viewport->height()); - } - } -} - -/*! - \reimp -*/ -QStyleOptionViewItem QTableView::viewOptions() const -{ - QStyleOptionViewItem option = QAbstractItemView::viewOptions(); - option.showDecorationSelected = true; - return option; -} - -/*! - Paints the table on receipt of the given paint event \a event. -*/ -void QTableView::paintEvent(QPaintEvent *event) -{ - Q_D(QTableView); - // setup temp variables for the painting - QStyleOptionViewItemV4 option = d->viewOptionsV4(); - const QPoint offset = d->scrollDelayOffset; - const bool showGrid = d->showGrid; - const int gridSize = showGrid ? 1 : 0; - const int gridHint = style()->styleHint(QStyle::SH_Table_GridLineColor, &option, this); - const QColor gridColor = static_cast<QRgb>(gridHint); - const QPen gridPen = QPen(gridColor, 0, d->gridStyle); - const QHeaderView *verticalHeader = d->verticalHeader; - const QHeaderView *horizontalHeader = d->horizontalHeader; - const QStyle::State state = option.state; - const bool alternate = d->alternatingColors; - const bool rightToLeft = isRightToLeft(); - - QPainter painter(d->viewport); - - // if there's nothing to do, clear the area and return - if (horizontalHeader->count() == 0 || verticalHeader->count() == 0 || !d->itemDelegate) - return; - - uint x = horizontalHeader->length() - horizontalHeader->offset() - (rightToLeft ? 0 : 1); - uint y = verticalHeader->length() - verticalHeader->offset() - 1; - - const QRegion region = event->region().translated(offset); - const QVector<QRect> rects = region.rects(); - - //firstVisualRow is the visual index of the first visible row. lastVisualRow is the visual index of the last visible Row. - //same goes for ...VisualColumn - int firstVisualRow = qMax(verticalHeader->visualIndexAt(0),0); - int lastVisualRow = verticalHeader->visualIndexAt(verticalHeader->viewport()->height()); - if (lastVisualRow == -1) - lastVisualRow = d->model->rowCount(d->root) - 1; - - int firstVisualColumn = horizontalHeader->visualIndexAt(0); - int lastVisualColumn = horizontalHeader->visualIndexAt(horizontalHeader->viewport()->width()); - if (rightToLeft) - qSwap(firstVisualColumn, lastVisualColumn); - if (firstVisualColumn == -1) - firstVisualColumn = 0; - if (lastVisualColumn == -1) - lastVisualColumn = horizontalHeader->count() - 1; - - QBitArray drawn((lastVisualRow - firstVisualRow + 1) * (lastVisualColumn - firstVisualColumn + 1)); - - if (d->hasSpans()) { - d->drawAndClipSpans(region, &painter, option, &drawn, - firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn); - } - - for (int i = 0; i < rects.size(); ++i) { - QRect dirtyArea = rects.at(i); - dirtyArea.setBottom(qMin(dirtyArea.bottom(), int(y))); - if (rightToLeft) { - dirtyArea.setLeft(qMax(dirtyArea.left(), d->viewport->width() - int(x))); - } else { - dirtyArea.setRight(qMin(dirtyArea.right(), int(x))); - } - - // get the horizontal start and end visual sections - int left = horizontalHeader->visualIndexAt(dirtyArea.left()); - int right = horizontalHeader->visualIndexAt(dirtyArea.right()); - if (rightToLeft) - qSwap(left, right); - if (left == -1) left = 0; - if (right == -1) right = horizontalHeader->count() - 1; - - // get the vertical start and end visual sections and if alternate color - int bottom = verticalHeader->visualIndexAt(dirtyArea.bottom()); - if (bottom == -1) bottom = verticalHeader->count() - 1; - int top = 0; - bool alternateBase = false; - if (alternate && verticalHeader->sectionsHidden()) { - uint verticalOffset = verticalHeader->offset(); - int row = verticalHeader->logicalIndex(top); - for (int y = 0; - ((uint)(y += verticalHeader->sectionSize(top)) <= verticalOffset) && (top < bottom); - ++top) { - row = verticalHeader->logicalIndex(top); - if (alternate && !verticalHeader->isSectionHidden(row)) - alternateBase = !alternateBase; - } - } else { - top = verticalHeader->visualIndexAt(dirtyArea.top()); - alternateBase = (top & 1) && alternate; - } - if (top == -1 || top > bottom) - continue; - - // Paint each row item - for (int visualRowIndex = top; visualRowIndex <= bottom; ++visualRowIndex) { - int row = verticalHeader->logicalIndex(visualRowIndex); - if (verticalHeader->isSectionHidden(row)) - continue; - int rowY = rowViewportPosition(row); - rowY += offset.y(); - int rowh = rowHeight(row) - gridSize; - - // Paint each column item - for (int visualColumnIndex = left; visualColumnIndex <= right; ++visualColumnIndex) { - int currentBit = (visualRowIndex - firstVisualRow) * (lastVisualColumn - firstVisualColumn + 1) - + visualColumnIndex - firstVisualColumn; - - if (currentBit < 0 || currentBit >= drawn.size() || drawn.testBit(currentBit)) - continue; - drawn.setBit(currentBit); - - int col = horizontalHeader->logicalIndex(visualColumnIndex); - if (horizontalHeader->isSectionHidden(col)) - continue; - int colp = columnViewportPosition(col); - colp += offset.x(); - int colw = columnWidth(col) - gridSize; - - const QModelIndex index = d->model->index(row, col, d->root); - if (index.isValid()) { - option.rect = QRect(colp + (showGrid && rightToLeft ? 1 : 0), rowY, colw, rowh); - if (alternate) { - if (alternateBase) - option.features |= QStyleOptionViewItemV2::Alternate; - else - option.features &= ~QStyleOptionViewItemV2::Alternate; - } - d->drawCell(&painter, option, index); - } - } - alternateBase = !alternateBase && alternate; - } - - if (showGrid) { - // Find the bottom right (the last rows/columns might be hidden) - while (verticalHeader->isSectionHidden(verticalHeader->logicalIndex(bottom))) --bottom; - QPen old = painter.pen(); - painter.setPen(gridPen); - // Paint each row - for (int visualIndex = top; visualIndex <= bottom; ++visualIndex) { - int row = verticalHeader->logicalIndex(visualIndex); - if (verticalHeader->isSectionHidden(row)) - continue; - int rowY = rowViewportPosition(row); - rowY += offset.y(); - int rowh = rowHeight(row) - gridSize; - painter.drawLine(dirtyArea.left(), rowY + rowh, dirtyArea.right(), rowY + rowh); - } - - // Paint each column - for (int h = left; h <= right; ++h) { - int col = horizontalHeader->logicalIndex(h); - if (horizontalHeader->isSectionHidden(col)) - continue; - int colp = columnViewportPosition(col); - colp += offset.x(); - if (!rightToLeft) - colp += columnWidth(col) - gridSize; - painter.drawLine(colp, dirtyArea.top(), colp, dirtyArea.bottom()); - } - - //draw the top & left grid lines if the headers are not visible. - //We do update this line when subsequent scroll happen (see scrollContentsBy) - if (horizontalHeader->isHidden() && verticalScrollMode() == ScrollPerItem) - painter.drawLine(dirtyArea.left(), 0, dirtyArea.right(), 0); - if (verticalHeader->isHidden() && horizontalScrollMode() == ScrollPerItem) - painter.drawLine(0, dirtyArea.top(), 0, dirtyArea.bottom()); - painter.setPen(old); - } - } - -#ifndef QT_NO_DRAGANDDROP - // Paint the dropIndicator - d->paintDropIndicator(&painter); -#endif -} - -/*! - Returns the index position of the model item corresponding to the - table item at position \a pos in contents coordinates. -*/ -QModelIndex QTableView::indexAt(const QPoint &pos) const -{ - Q_D(const QTableView); - d->executePostedLayout(); - int r = rowAt(pos.y()); - int c = columnAt(pos.x()); - if (r >= 0 && c >= 0) { - if (d->hasSpans()) { - QSpanCollection::Span span = d->span(r, c); - r = span.top(); - c = span.left(); - } - return d->model->index(r, c, d->root); - } - return QModelIndex(); -} - -/*! - Returns the horizontal offset of the items in the table view. - - Note that the table view uses the horizontal header section - positions to determine the positions of columns in the view. - - \sa verticalOffset() -*/ -int QTableView::horizontalOffset() const -{ - Q_D(const QTableView); - return d->horizontalHeader->offset(); -} - -/*! - Returns the vertical offset of the items in the table view. - - Note that the table view uses the vertical header section - positions to determine the positions of rows in the view. - - \sa horizontalOffset() -*/ -int QTableView::verticalOffset() const -{ - Q_D(const QTableView); - return d->verticalHeader->offset(); -} - -/*! - \fn QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) - - Moves the cursor in accordance with the given \a cursorAction, using the - information provided by the \a modifiers. - - \sa QAbstractItemView::CursorAction -*/ -QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) -{ - Q_D(QTableView); - Q_UNUSED(modifiers); - - int bottom = d->model->rowCount(d->root) - 1; - // make sure that bottom is the bottommost *visible* row - while (bottom >= 0 && isRowHidden(d->logicalRow(bottom))) - --bottom; - - int right = d->model->columnCount(d->root) - 1; - - while (right >= 0 && isColumnHidden(d->logicalColumn(right))) - --right; - - if (bottom == -1 || right == -1) - return QModelIndex(); // model is empty - - QModelIndex current = currentIndex(); - - if (!current.isValid()) { - int row = 0; - int column = 0; - while (column < right && isColumnHidden(d->logicalColumn(column))) - ++column; - while (isRowHidden(d->logicalRow(row)) && row < bottom) - ++row; - d->visualCursor = QPoint(column, row); - return d->model->index(d->logicalRow(row), d->logicalColumn(column), d->root); - } - - // Update visual cursor if current index has changed. - QPoint visualCurrent(d->visualColumn(current.column()), d->visualRow(current.row())); - if (visualCurrent != d->visualCursor) { - if (d->hasSpans()) { - QSpanCollection::Span span = d->span(current.row(), current.column()); - if (span.top() > d->visualCursor.y() || d->visualCursor.y() > span.bottom() - || span.left() > d->visualCursor.x() || d->visualCursor.x() > span.right()) - d->visualCursor = visualCurrent; - } else { - d->visualCursor = visualCurrent; - } - } - - int visualRow = d->visualCursor.y(); - if (visualRow > bottom) - visualRow = bottom; - Q_ASSERT(visualRow != -1); - int visualColumn = d->visualCursor.x(); - if (visualColumn > right) - visualColumn = right; - Q_ASSERT(visualColumn != -1); - - if (isRightToLeft()) { - if (cursorAction == MoveLeft) - cursorAction = MoveRight; - else if (cursorAction == MoveRight) - cursorAction = MoveLeft; - } - - switch (cursorAction) { - case MoveUp: { - int originalRow = visualRow; -#ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && visualRow == 0) - visualRow = d->visualRow(model()->rowCount() - 1) + 1; - // FIXME? visualRow = bottom + 1; -#endif - int r = d->logicalRow(visualRow); - int c = d->logicalColumn(visualColumn); - if (r != -1 && d->hasSpans()) { - QSpanCollection::Span span = d->span(r, c); - if (span.width() > 1 || span.height() > 1) - visualRow = d->visualRow(span.top()); - } - while (visualRow >= 0) { - --visualRow; - r = d->logicalRow(visualRow); - c = d->logicalColumn(visualColumn); - if (r == -1 || (!isRowHidden(r) && d->isCellEnabled(r, c))) - break; - } - if (visualRow < 0) - visualRow = originalRow; - break; - } - case MoveDown: { - int originalRow = visualRow; - if (d->hasSpans()) { - QSpanCollection::Span span = d->span(current.row(), current.column()); - visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height())); - } -#ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && visualRow >= bottom) - visualRow = -1; -#endif - int r = d->logicalRow(visualRow); - int c = d->logicalColumn(visualColumn); - if (r != -1 && d->hasSpans()) { - QSpanCollection::Span span = d->span(r, c); - if (span.width() > 1 || span.height() > 1) - visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height())); - } - while (visualRow <= bottom) { - ++visualRow; - r = d->logicalRow(visualRow); - c = d->logicalColumn(visualColumn); - if (r == -1 || (!isRowHidden(r) && d->isCellEnabled(r, c))) - break; - } - if (visualRow > bottom) - visualRow = originalRow; - break; - } - case MovePrevious: - case MoveLeft: { - int originalRow = visualRow; - int originalColumn = visualColumn; - bool firstTime = true; - bool looped = false; - bool wrapped = false; - do { - int r = d->logicalRow(visualRow); - int c = d->logicalColumn(visualColumn); - if (firstTime && c != -1 && d->hasSpans()) { - firstTime = false; - QSpanCollection::Span span = d->span(r, c); - if (span.width() > 1 || span.height() > 1) - visualColumn = d->visualColumn(span.left()); - } - while (visualColumn >= 0) { - --visualColumn; - r = d->logicalRow(visualRow); - c = d->logicalColumn(visualColumn); - if (r == -1 || c == -1 || (!isRowHidden(r) && !isColumnHidden(c) && d->isCellEnabled(r, c))) - break; - if (wrapped && (originalRow < visualRow || (originalRow == visualRow && originalColumn <= visualColumn))) { - looped = true; - break; - } - } - if (cursorAction == MoveLeft || visualColumn >= 0) - break; - visualColumn = right + 1; - if (visualRow == 0) { - wrapped = true; - visualRow = bottom; - } else { - --visualRow; - } - } while (!looped); - if (visualColumn < 0) - visualColumn = originalColumn; - break; - } - case MoveNext: - case MoveRight: { - int originalRow = visualRow; - int originalColumn = visualColumn; - bool firstTime = true; - bool looped = false; - bool wrapped = false; - do { - int r = d->logicalRow(visualRow); - int c = d->logicalColumn(visualColumn); - if (firstTime && c != -1 && d->hasSpans()) { - firstTime = false; - QSpanCollection::Span span = d->span(r, c); - if (span.width() > 1 || span.height() > 1) - visualColumn = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width())); - } - while (visualColumn <= right) { - ++visualColumn; - r = d->logicalRow(visualRow); - c = d->logicalColumn(visualColumn); - if (r == -1 || c == -1 || (!isRowHidden(r) && !isColumnHidden(c) && d->isCellEnabled(r, c))) - break; - if (wrapped && (originalRow > visualRow || (originalRow == visualRow && originalColumn >= visualColumn))) { - looped = true; - break; - } - } - if (cursorAction == MoveRight || visualColumn <= right) - break; - visualColumn = -1; - if (visualRow == bottom) { - wrapped = true; - visualRow = 0; - } else { - ++visualRow; - } - } while (!looped); - if (visualColumn > right) - visualColumn = originalColumn; - break; - } - case MoveHome: - visualColumn = 0; - while (visualColumn < right && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn)) - ++visualColumn; - if (modifiers & Qt::ControlModifier) { - visualRow = 0; - while (visualRow < bottom && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn)) - ++visualRow; - } - break; - case MoveEnd: - visualColumn = right; - if (modifiers & Qt::ControlModifier) - visualRow = bottom; - break; - case MovePageUp: { - int newRow = rowAt(visualRect(current).top() - d->viewport->height()); - if (newRow == -1) - newRow = d->logicalRow(0); - return d->model->index(newRow, current.column(), d->root); - } - case MovePageDown: { - int newRow = rowAt(visualRect(current).bottom() + d->viewport->height()); - if (newRow == -1) - newRow = d->logicalRow(bottom); - return d->model->index(newRow, current.column(), d->root); - }} - - d->visualCursor = QPoint(visualColumn, visualRow); - int logicalRow = d->logicalRow(visualRow); - int logicalColumn = d->logicalColumn(visualColumn); - if (!d->model->hasIndex(logicalRow, logicalColumn, d->root)) - return QModelIndex(); - - QModelIndex result = d->model->index(logicalRow, logicalColumn, d->root); - if (!d->isRowHidden(logicalRow) && !d->isColumnHidden(logicalColumn) && d->isIndexEnabled(result)) - return result; - - return QModelIndex(); -} - -/*! - \fn void QTableView::setSelection(const QRect &rect, - QItemSelectionModel::SelectionFlags flags) - - Selects the items within the given \a rect and in accordance with - the specified selection \a flags. -*/ -void QTableView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command) -{ - Q_D(QTableView); - QModelIndex tl = indexAt(QPoint(isRightToLeft() ? qMax(rect.left(), rect.right()) - : qMin(rect.left(), rect.right()), qMin(rect.top(), rect.bottom()))); - QModelIndex br = indexAt(QPoint(isRightToLeft() ? qMin(rect.left(), rect.right()) : - qMax(rect.left(), rect.right()), qMax(rect.top(), rect.bottom()))); - if (!d->selectionModel || !tl.isValid() || !br.isValid() || !d->isIndexEnabled(tl) || !d->isIndexEnabled(br)) - return; - - bool verticalMoved = verticalHeader()->sectionsMoved(); - bool horizontalMoved = horizontalHeader()->sectionsMoved(); - - QItemSelection selection; - - if (d->hasSpans()) { - bool expanded; - int top = qMin(d->visualRow(tl.row()), d->visualRow(br.row())); - int left = qMin(d->visualColumn(tl.column()), d->visualColumn(br.column())); - int bottom = qMax(d->visualRow(tl.row()), d->visualRow(br.row())); - int right = qMax(d->visualColumn(tl.column()), d->visualColumn(br.column())); - do { - expanded = false; - foreach (QSpanCollection::Span *it, d->spans.spans) { - const QSpanCollection::Span &span = *it; - int t = d->visualRow(span.top()); - int l = d->visualColumn(span.left()); - int b = d->visualRow(d->rowSpanEndLogical(span.top(), span.height())); - int r = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width())); - if ((t > bottom) || (l > right) || (top > b) || (left > r)) - continue; // no intersect - if (t < top) { - top = t; - expanded = true; - } - if (l < left) { - left = l; - expanded = true; - } - if (b > bottom) { - bottom = b; - expanded = true; - } - if (r > right) { - right = r; - expanded = true; - } - if (expanded) - break; - } - } while (expanded); - for (int horizontal = left; horizontal <= right; ++horizontal) { - int column = d->logicalColumn(horizontal); - for (int vertical = top; vertical <= bottom; ++vertical) { - int row = d->logicalRow(vertical); - QModelIndex index = d->model->index(row, column, d->root); - selection.append(QItemSelectionRange(index)); - } - } - } else if (verticalMoved && horizontalMoved) { - int top = d->visualRow(tl.row()); - int left = d->visualColumn(tl.column()); - int bottom = d->visualRow(br.row()); - int right = d->visualColumn(br.column()); - for (int horizontal = left; horizontal <= right; ++horizontal) { - int column = d->logicalColumn(horizontal); - for (int vertical = top; vertical <= bottom; ++vertical) { - int row = d->logicalRow(vertical); - QModelIndex index = d->model->index(row, column, d->root); - selection.append(QItemSelectionRange(index)); - } - } - } else if (horizontalMoved) { - int left = d->visualColumn(tl.column()); - int right = d->visualColumn(br.column()); - for (int visual = left; visual <= right; ++visual) { - int column = d->logicalColumn(visual); - QModelIndex topLeft = d->model->index(tl.row(), column, d->root); - QModelIndex bottomRight = d->model->index(br.row(), column, d->root); - selection.append(QItemSelectionRange(topLeft, bottomRight)); - } - } else if (verticalMoved) { - int top = d->visualRow(tl.row()); - int bottom = d->visualRow(br.row()); - for (int visual = top; visual <= bottom; ++visual) { - int row = d->logicalRow(visual); - QModelIndex topLeft = d->model->index(row, tl.column(), d->root); - QModelIndex bottomRight = d->model->index(row, br.column(), d->root); - selection.append(QItemSelectionRange(topLeft, bottomRight)); - } - } else { // nothing moved - QItemSelectionRange range(tl, br); - if (!range.isEmpty()) - selection.append(range); - } - - d->selectionModel->select(selection, command); -} - -/*! - \internal - - Returns the rectangle from the viewport of the items in the given - \a selection. - - Since 4.7, the returned region only contains rectangles intersecting - (or included in) the viewport. -*/ -QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) const -{ - Q_D(const QTableView); - - if (selection.isEmpty()) - return QRegion(); - - QRegion selectionRegion; - const QRect &viewportRect = d->viewport->rect(); - bool verticalMoved = verticalHeader()->sectionsMoved(); - bool horizontalMoved = horizontalHeader()->sectionsMoved(); - - if ((verticalMoved && horizontalMoved) || (d->hasSpans() && (verticalMoved || horizontalMoved))) { - for (int i = 0; i < selection.count(); ++i) { - QItemSelectionRange range = selection.at(i); - if (range.parent() != d->root || !range.isValid()) - continue; - for (int r = range.top(); r <= range.bottom(); ++r) - for (int c = range.left(); c <= range.right(); ++c) { - const QRect &rangeRect = visualRect(d->model->index(r, c, d->root)); - if (viewportRect.intersects(rangeRect)) - selectionRegion += rangeRect; - } - } - } else if (horizontalMoved) { - for (int i = 0; i < selection.count(); ++i) { - QItemSelectionRange range = selection.at(i); - if (range.parent() != d->root || !range.isValid()) - continue; - int top = rowViewportPosition(range.top()); - int bottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom()); - if (top > bottom) - qSwap<int>(top, bottom); - int height = bottom - top; - for (int c = range.left(); c <= range.right(); ++c) { - const QRect rangeRect(columnViewportPosition(c), top, columnWidth(c), height); - if (viewportRect.intersects(rangeRect)) - selectionRegion += rangeRect; - } - } - } else if (verticalMoved) { - for (int i = 0; i < selection.count(); ++i) { - QItemSelectionRange range = selection.at(i); - if (range.parent() != d->root || !range.isValid()) - continue; - int left = columnViewportPosition(range.left()); - int right = columnViewportPosition(range.right()) + columnWidth(range.right()); - if (left > right) - qSwap<int>(left, right); - int width = right - left; - for (int r = range.top(); r <= range.bottom(); ++r) { - const QRect rangeRect(left, rowViewportPosition(r), width, rowHeight(r)); - if (viewportRect.intersects(rangeRect)) - selectionRegion += rangeRect; - } - } - } else { // nothing moved - const int gridAdjust = showGrid() ? 1 : 0; - for (int i = 0; i < selection.count(); ++i) { - QItemSelectionRange range = selection.at(i); - if (range.parent() != d->root || !range.isValid()) - continue; - d->trimHiddenSelections(&range); - - const int rtop = rowViewportPosition(range.top()); - const int rbottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom()); - int rleft; - int rright; - if (isLeftToRight()) { - rleft = columnViewportPosition(range.left()); - rright = columnViewportPosition(range.right()) + columnWidth(range.right()); - } else { - rleft = columnViewportPosition(range.right()); - rright = columnViewportPosition(range.left()) + columnWidth(range.left()); - } - const QRect rangeRect(QPoint(rleft, rtop), QPoint(rright - 1 - gridAdjust, rbottom - 1 - gridAdjust)); - if (viewportRect.intersects(rangeRect)) - selectionRegion += rangeRect; - if (d->hasSpans()) { - foreach (QSpanCollection::Span *s, - d->spans.spansInRect(range.left(), range.top(), range.width(), range.height())) { - if (range.contains(s->top(), s->left(), range.parent())) { - const QRect &visualSpanRect = d->visualSpanRect(*s); - if (viewportRect.intersects(visualSpanRect)) - selectionRegion += visualSpanRect; - } - } - } - } - } - - return selectionRegion; -} - - -/*! - \reimp -*/ -QModelIndexList QTableView::selectedIndexes() const -{ - Q_D(const QTableView); - QModelIndexList viewSelected; - QModelIndexList modelSelected; - if (d->selectionModel) - modelSelected = d->selectionModel->selectedIndexes(); - for (int i = 0; i < modelSelected.count(); ++i) { - QModelIndex index = modelSelected.at(i); - if (!isIndexHidden(index) && index.parent() == d->root) - viewSelected.append(index); - } - return viewSelected; -} - - -/*! - This slot is called whenever rows are added or deleted. The - previous number of rows is specified by \a oldCount, and the new - number of rows is specified by \a newCount. -*/ -void QTableView::rowCountChanged(int /*oldCount*/, int /*newCount*/ ) -{ - Q_D(QTableView); - d->doDelayedItemsLayout(); -} - -/*! - This slot is called whenever columns are added or deleted. The - previous number of columns is specified by \a oldCount, and the new - number of columns is specified by \a newCount. -*/ -void QTableView::columnCountChanged(int, int) -{ - Q_D(QTableView); - updateGeometries(); - if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) - d->horizontalHeader->setOffsetToSectionPosition(horizontalScrollBar()->value()); - else - d->horizontalHeader->setOffset(horizontalScrollBar()->value()); - d->viewport->update(); -} - -/*! - \reimp -*/ -void QTableView::updateGeometries() -{ - Q_D(QTableView); - if (d->geometryRecursionBlock) - return; - d->geometryRecursionBlock = true; - - int width = 0; - if (!d->verticalHeader->isHidden()) { - width = qMax(d->verticalHeader->minimumWidth(), d->verticalHeader->sizeHint().width()); - width = qMin(width, d->verticalHeader->maximumWidth()); - } - int height = 0; - if (!d->horizontalHeader->isHidden()) { - height = qMax(d->horizontalHeader->minimumHeight(), d->horizontalHeader->sizeHint().height()); - height = qMin(height, d->horizontalHeader->maximumHeight()); - } - bool reverse = isRightToLeft(); - if (reverse) - setViewportMargins(0, height, width, 0); - else - setViewportMargins(width, height, 0, 0); - - // update headers - - QRect vg = d->viewport->geometry(); - - int verticalLeft = reverse ? vg.right() + 1 : (vg.left() - width); - d->verticalHeader->setGeometry(verticalLeft, vg.top(), width, vg.height()); - if (d->verticalHeader->isHidden()) - QMetaObject::invokeMethod(d->verticalHeader, "updateGeometries"); - - int horizontalTop = vg.top() - height; - d->horizontalHeader->setGeometry(vg.left(), horizontalTop, vg.width(), height); - if (d->horizontalHeader->isHidden()) - QMetaObject::invokeMethod(d->horizontalHeader, "updateGeometries"); - - // update cornerWidget - if (d->horizontalHeader->isHidden() || d->verticalHeader->isHidden()) { - d->cornerWidget->setHidden(true); - } else { - d->cornerWidget->setHidden(false); - d->cornerWidget->setGeometry(verticalLeft, horizontalTop, width, height); - } - - // update scroll bars - - // ### move this block into the if - QSize vsize = d->viewport->size(); - QSize max = maximumViewportSize(); - uint horizontalLength = d->horizontalHeader->length(); - uint verticalLength = d->verticalHeader->length(); - if ((uint)max.width() >= horizontalLength && (uint)max.height() >= verticalLength) - vsize = max; - - // horizontal scroll bar - const int columnCount = d->horizontalHeader->count(); - const int viewportWidth = vsize.width(); - int columnsInViewport = 0; - for (int width = 0, column = columnCount - 1; column >= 0; --column) { - int logical = d->horizontalHeader->logicalIndex(column); - if (!d->horizontalHeader->isSectionHidden(logical)) { - width += d->horizontalHeader->sectionSize(logical); - if (width > viewportWidth) - break; - ++columnsInViewport; - } - } - columnsInViewport = qMax(columnsInViewport, 1); //there must be always at least 1 column - - if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) { - const int visibleColumns = columnCount - d->horizontalHeader->hiddenSectionCount(); - horizontalScrollBar()->setRange(0, visibleColumns - columnsInViewport); - horizontalScrollBar()->setPageStep(columnsInViewport); - if (columnsInViewport >= visibleColumns) - d->horizontalHeader->setOffset(0); - horizontalScrollBar()->setSingleStep(1); - } else { // ScrollPerPixel - horizontalScrollBar()->setPageStep(vsize.width()); - horizontalScrollBar()->setRange(0, horizontalLength - vsize.width()); - horizontalScrollBar()->setSingleStep(qMax(vsize.width() / (columnsInViewport + 1), 2)); - } - - // vertical scroll bar - const int rowCount = d->verticalHeader->count(); - const int viewportHeight = vsize.height(); - int rowsInViewport = 0; - for (int height = 0, row = rowCount - 1; row >= 0; --row) { - int logical = d->verticalHeader->logicalIndex(row); - if (!d->verticalHeader->isSectionHidden(logical)) { - height += d->verticalHeader->sectionSize(logical); - if (height > viewportHeight) - break; - ++rowsInViewport; - } - } - rowsInViewport = qMax(rowsInViewport, 1); //there must be always at least 1 row - - if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) { - const int visibleRows = rowCount - d->verticalHeader->hiddenSectionCount(); - verticalScrollBar()->setRange(0, visibleRows - rowsInViewport); - verticalScrollBar()->setPageStep(rowsInViewport); - if (rowsInViewport >= visibleRows) - d->verticalHeader->setOffset(0); - verticalScrollBar()->setSingleStep(1); - } else { // ScrollPerPixel - verticalScrollBar()->setPageStep(vsize.height()); - verticalScrollBar()->setRange(0, verticalLength - vsize.height()); - verticalScrollBar()->setSingleStep(qMax(vsize.height() / (rowsInViewport + 1), 2)); - } - - d->geometryRecursionBlock = false; - QAbstractItemView::updateGeometries(); -} - -/*! - Returns the size hint for the given \a row's height or -1 if there - is no model. - - If you need to set the height of a given row to a fixed value, call - QHeaderView::resizeSection() on the table's vertical header. - - If you reimplement this function in a subclass, note that the value you - return is only used when resizeRowToContents() is called. In that case, - if a larger row height is required by either the vertical header or - the item delegate, that width will be used instead. - - \sa QWidget::sizeHint, verticalHeader() -*/ -int QTableView::sizeHintForRow(int row) const -{ - Q_D(const QTableView); - - if (!model()) - return -1; - - ensurePolished(); - - int left = qMax(0, d->horizontalHeader->visualIndexAt(0)); - int right = d->horizontalHeader->visualIndexAt(d->viewport->width()); - if (right == -1) // the table don't have enough columns to fill the viewport - right = d->model->columnCount(d->root) - 1; - - QStyleOptionViewItemV4 option = d->viewOptionsV4(); - - int hint = 0; - QModelIndex index; - for (int column = left; column <= right; ++column) { - int logicalColumn = d->horizontalHeader->logicalIndex(column); - if (d->horizontalHeader->isSectionHidden(logicalColumn)) - continue; - index = d->model->index(row, logicalColumn, d->root); - if (d->wrapItemText) {// for wrapping boundaries - option.rect.setY(rowViewportPosition(index.row())); - option.rect.setHeight(rowHeight(index.row())); - option.rect.setX(columnViewportPosition(index.column())); - option.rect.setWidth(columnWidth(index.column())); - } - - QWidget *editor = d->editorForIndex(index).widget.data(); - if (editor && d->persistent.contains(editor)) { - hint = qMax(hint, editor->sizeHint().height()); - int min = editor->minimumSize().height(); - int max = editor->maximumSize().height(); - hint = qBound(min, hint, max); - } - - hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).height()); - } - - return d->showGrid ? hint + 1 : hint; -} - -/*! - Returns the size hint for the given \a column's width or -1 if - there is no model. - - If you need to set the width of a given column to a fixed value, call - QHeaderView::resizeSection() on the table's horizontal header. - - If you reimplement this function in a subclass, note that the value you - return will be used when resizeColumnToContents() or - QHeaderView::resizeSections() is called. If a larger column width is - required by either the horizontal header or the item delegate, the larger - width will be used instead. - - \sa QWidget::sizeHint, horizontalHeader() -*/ -int QTableView::sizeHintForColumn(int column) const -{ - Q_D(const QTableView); - - if (!model()) - return -1; - - ensurePolished(); - - int top = qMax(0, d->verticalHeader->visualIndexAt(0)); - int bottom = d->verticalHeader->visualIndexAt(d->viewport->height()); - if (!isVisible() || bottom == -1) // the table don't have enough rows to fill the viewport - bottom = d->model->rowCount(d->root) - 1; - - QStyleOptionViewItemV4 option = d->viewOptionsV4(); - - int hint = 0; - QModelIndex index; - for (int row = top; row <= bottom; ++row) { - int logicalRow = d->verticalHeader->logicalIndex(row); - if (d->verticalHeader->isSectionHidden(logicalRow)) - continue; - index = d->model->index(logicalRow, column, d->root); - - QWidget *editor = d->editorForIndex(index).widget.data(); - if (editor && d->persistent.contains(editor)) { - hint = qMax(hint, editor->sizeHint().width()); - int min = editor->minimumSize().width(); - int max = editor->maximumSize().width(); - hint = qBound(min, hint, max); - } - - hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).width()); - } - - return d->showGrid ? hint + 1 : hint; -} - -/*! - Returns the y-coordinate in contents coordinates of the given \a - row. -*/ -int QTableView::rowViewportPosition(int row) const -{ - Q_D(const QTableView); - return d->verticalHeader->sectionViewportPosition(row); -} - -/*! - Returns the row in which the given y-coordinate, \a y, in contents - coordinates is located. - - \note This function returns -1 if the given coordinate is not valid - (has no row). - - \sa columnAt() -*/ -int QTableView::rowAt(int y) const -{ - Q_D(const QTableView); - return d->verticalHeader->logicalIndexAt(y); -} - -/*! - \since 4.1 - - Sets the height of the given \a row to be \a height. -*/ -void QTableView::setRowHeight(int row, int height) -{ - Q_D(const QTableView); - d->verticalHeader->resizeSection(row, height); -} - -/*! - Returns the height of the given \a row. - - \sa resizeRowToContents(), columnWidth() -*/ -int QTableView::rowHeight(int row) const -{ - Q_D(const QTableView); - return d->verticalHeader->sectionSize(row); -} - -/*! - Returns the x-coordinate in contents coordinates of the given \a - column. -*/ -int QTableView::columnViewportPosition(int column) const -{ - Q_D(const QTableView); - return d->horizontalHeader->sectionViewportPosition(column); -} - -/*! - Returns the column in which the given x-coordinate, \a x, in contents - coordinates is located. - - \note This function returns -1 if the given coordinate is not valid - (has no column). - - \sa rowAt() -*/ -int QTableView::columnAt(int x) const -{ - Q_D(const QTableView); - return d->horizontalHeader->logicalIndexAt(x); -} - -/*! - \since 4.1 - - Sets the width of the given \a column to be \a width. -*/ -void QTableView::setColumnWidth(int column, int width) -{ - Q_D(const QTableView); - d->horizontalHeader->resizeSection(column, width); -} - -/*! - Returns the width of the given \a column. - - \sa resizeColumnToContents(), rowHeight() -*/ -int QTableView::columnWidth(int column) const -{ - Q_D(const QTableView); - return d->horizontalHeader->sectionSize(column); -} - -/*! - Returns true if the given \a row is hidden; otherwise returns false. - - \sa isColumnHidden() -*/ -bool QTableView::isRowHidden(int row) const -{ - Q_D(const QTableView); - return d->verticalHeader->isSectionHidden(row); -} - -/*! - If \a hide is true \a row will be hidden, otherwise it will be shown. - - \sa setColumnHidden() -*/ -void QTableView::setRowHidden(int row, bool hide) -{ - Q_D(QTableView); - if (row < 0 || row >= d->verticalHeader->count()) - return; - d->verticalHeader->setSectionHidden(row, hide); -} - -/*! - Returns true if the given \a column is hidden; otherwise returns false. - - \sa isRowHidden() -*/ -bool QTableView::isColumnHidden(int column) const -{ - Q_D(const QTableView); - return d->horizontalHeader->isSectionHidden(column); -} - -/*! - If \a hide is true the given \a column will be hidden; otherwise it - will be shown. - - \sa setRowHidden() -*/ -void QTableView::setColumnHidden(int column, bool hide) -{ - Q_D(QTableView); - if (column < 0 || column >= d->horizontalHeader->count()) - return; - d->horizontalHeader->setSectionHidden(column, hide); -} - -/*! - \since 4.2 - \property QTableView::sortingEnabled - \brief whether sorting is enabled - - If this property is true, sorting is enabled for the table. If - this property is false, sorting is not enabled. The default value - is false. - - \note. Setting the property to true with setSortingEnabled() - immediately triggers a call to sortByColumn() with the current - sort section and order. - - \sa sortByColumn() -*/ - -/*! - If \a enabled true enables sorting for the table and immediately - trigger a call to sortByColumn() with the current sort section and - order - */ -void QTableView::setSortingEnabled(bool enable) -{ - Q_D(QTableView); - d->sortingEnabled = enable; - horizontalHeader()->setSortIndicatorShown(enable); - if (enable) { - disconnect(d->horizontalHeader, SIGNAL(sectionEntered(int)), - this, SLOT(_q_selectColumn(int))); - disconnect(horizontalHeader(), SIGNAL(sectionPressed(int)), - this, SLOT(selectColumn(int))); - connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), - this, SLOT(sortByColumn(int)), Qt::UniqueConnection); - sortByColumn(horizontalHeader()->sortIndicatorSection(), - horizontalHeader()->sortIndicatorOrder()); - } else { - connect(d->horizontalHeader, SIGNAL(sectionEntered(int)), - this, SLOT(_q_selectColumn(int)), Qt::UniqueConnection); - connect(horizontalHeader(), SIGNAL(sectionPressed(int)), - this, SLOT(selectColumn(int)), Qt::UniqueConnection); - disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), - this, SLOT(sortByColumn(int))); - } -} - -bool QTableView::isSortingEnabled() const -{ - Q_D(const QTableView); - return d->sortingEnabled; -} - -/*! - \property QTableView::showGrid - \brief whether the grid is shown - - If this property is true a grid is drawn for the table; if the - property is false, no grid is drawn. The default value is true. -*/ -bool QTableView::showGrid() const -{ - Q_D(const QTableView); - return d->showGrid; -} - -void QTableView::setShowGrid(bool show) -{ - Q_D(QTableView); - if (d->showGrid != show) { - d->showGrid = show; - d->viewport->update(); - } -} - -/*! - \property QTableView::gridStyle - \brief the pen style used to draw the grid. - - This property holds the style used when drawing the grid (see \l{showGrid}). -*/ -Qt::PenStyle QTableView::gridStyle() const -{ - Q_D(const QTableView); - return d->gridStyle; -} - -void QTableView::setGridStyle(Qt::PenStyle style) -{ - Q_D(QTableView); - if (d->gridStyle != style) { - d->gridStyle = style; - d->viewport->update(); - } -} - -/*! - \property QTableView::wordWrap - \brief the item text word-wrapping policy - \since 4.3 - - If this property is true then the item text is wrapped where - necessary at word-breaks; otherwise it is not wrapped at all. - This property is true by default. - - Note that even of wrapping is enabled, the cell will not be - expanded to fit all text. Ellipsis will be inserted according to - the current \l{QAbstractItemView::}{textElideMode}. - -*/ -void QTableView::setWordWrap(bool on) -{ - Q_D(QTableView); - if (d->wrapItemText == on) - return; - d->wrapItemText = on; - QMetaObject::invokeMethod(d->verticalHeader, "resizeSections"); - QMetaObject::invokeMethod(d->horizontalHeader, "resizeSections"); -} - -bool QTableView::wordWrap() const -{ - Q_D(const QTableView); - return d->wrapItemText; -} - -/*! - \property QTableView::cornerButtonEnabled - \brief whether the button in the top-left corner is enabled - \since 4.3 - - If this property is true then button in the top-left corner - of the table view is enabled. Clicking on this button will - select all the cells in the table view. - - This property is true by default. -*/ -void QTableView::setCornerButtonEnabled(bool enable) -{ - Q_D(QTableView); - d->cornerWidget->setEnabled(enable); -} - -bool QTableView::isCornerButtonEnabled() const -{ - Q_D(const QTableView); - return d->cornerWidget->isEnabled(); -} - -/*! - \internal - - Returns the rectangle on the viewport occupied by the given \a - index. - If the index is hidden in the view it will return a null QRect. -*/ -QRect QTableView::visualRect(const QModelIndex &index) const -{ - Q_D(const QTableView); - if (!d->isIndexValid(index) || index.parent() != d->root - || (!d->hasSpans() && isIndexHidden(index))) - return QRect(); - - d->executePostedLayout(); - - if (d->hasSpans()) { - QSpanCollection::Span span = d->span(index.row(), index.column()); - return d->visualSpanRect(span); - } - - int rowp = rowViewportPosition(index.row()); - int rowh = rowHeight(index.row()); - int colp = columnViewportPosition(index.column()); - int colw = columnWidth(index.column()); - - const int i = showGrid() ? 1 : 0; - return QRect(colp, rowp, colw - i, rowh - i); -} - -/*! - \internal - - Makes sure that the given \a item is visible in the table view, - scrolling if necessary. -*/ -void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint) -{ - Q_D(QTableView); - - // check if we really need to do anything - if (!d->isIndexValid(index) - || (d->model->parent(index) != d->root) - || isRowHidden(index.row()) || isColumnHidden(index.column())) - return; - - QSpanCollection::Span span; - if (d->hasSpans()) - span = d->span(index.row(), index.column()); - - // Adjust horizontal position - - int viewportWidth = d->viewport->width(); - int horizontalOffset = d->horizontalHeader->offset(); - int horizontalPosition = d->horizontalHeader->sectionPosition(index.column()); - int horizontalIndex = d->horizontalHeader->visualIndex(index.column()); - int cellWidth = d->hasSpans() - ? d->columnSpanWidth(index.column(), span.width()) - : d->horizontalHeader->sectionSize(index.column()); - - if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) { - - bool positionAtLeft = (horizontalPosition - horizontalOffset < 0); - bool positionAtRight = (horizontalPosition - horizontalOffset + cellWidth > viewportWidth); - - if (hint == PositionAtCenter || positionAtRight) { - int w = (hint == PositionAtCenter ? viewportWidth / 2 : viewportWidth); - int x = cellWidth; - while (horizontalIndex > 0) { - x += columnWidth(d->horizontalHeader->logicalIndex(horizontalIndex-1)); - if (x > w) - break; - --horizontalIndex; - } - } - - if (positionAtRight || hint == PositionAtCenter || positionAtLeft) { - int hiddenSections = 0; - if (d->horizontalHeader->sectionsHidden()) { - for (int s = horizontalIndex - 1; s >= 0; --s) { - int column = d->horizontalHeader->logicalIndex(s); - if (d->horizontalHeader->isSectionHidden(column)) - ++hiddenSections; - } - } - horizontalScrollBar()->setValue(horizontalIndex - hiddenSections); - } - - } else { // ScrollPerPixel - if (hint == PositionAtCenter) { - horizontalScrollBar()->setValue(horizontalPosition - ((viewportWidth - cellWidth) / 2)); - } else { - if (horizontalPosition - horizontalOffset < 0 || cellWidth > viewportWidth) - horizontalScrollBar()->setValue(horizontalPosition); - else if (horizontalPosition - horizontalOffset + cellWidth > viewportWidth) - horizontalScrollBar()->setValue(horizontalPosition - viewportWidth + cellWidth); - } - } - - // Adjust vertical position - - int viewportHeight = d->viewport->height(); - int verticalOffset = d->verticalHeader->offset(); - int verticalPosition = d->verticalHeader->sectionPosition(index.row()); - int verticalIndex = d->verticalHeader->visualIndex(index.row()); - int cellHeight = d->hasSpans() - ? d->rowSpanHeight(index.row(), span.height()) - : d->verticalHeader->sectionSize(index.row()); - - if (verticalPosition - verticalOffset < 0 || cellHeight > viewportHeight) { - if (hint == EnsureVisible) - hint = PositionAtTop; - } else if (verticalPosition - verticalOffset + cellHeight > viewportHeight) { - if (hint == EnsureVisible) - hint = PositionAtBottom; - } - - if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) { - - if (hint == PositionAtBottom || hint == PositionAtCenter) { - int h = (hint == PositionAtCenter ? viewportHeight / 2 : viewportHeight); - int y = cellHeight; - while (verticalIndex > 0) { - int row = d->verticalHeader->logicalIndex(verticalIndex - 1); - y += d->verticalHeader->sectionSize(row); - if (y > h) - break; - --verticalIndex; - } - } - - if (hint == PositionAtBottom || hint == PositionAtCenter || hint == PositionAtTop) { - int hiddenSections = 0; - if (d->verticalHeader->sectionsHidden()) { - for (int s = verticalIndex - 1; s >= 0; --s) { - int row = d->verticalHeader->logicalIndex(s); - if (d->verticalHeader->isSectionHidden(row)) - ++hiddenSections; - } - } - verticalScrollBar()->setValue(verticalIndex - hiddenSections); - } - - } else { // ScrollPerPixel - if (hint == PositionAtTop) { - verticalScrollBar()->setValue(verticalPosition); - } else if (hint == PositionAtBottom) { - verticalScrollBar()->setValue(verticalPosition - viewportHeight + cellHeight); - } else if (hint == PositionAtCenter) { - verticalScrollBar()->setValue(verticalPosition - ((viewportHeight - cellHeight) / 2)); - } - } - - update(index); -} - -/*! - This slot is called to change the height of the given \a row. The - old height is specified by \a oldHeight, and the new height by \a - newHeight. - - \sa columnResized() -*/ -void QTableView::rowResized(int row, int, int) -{ - Q_D(QTableView); - d->rowsToUpdate.append(row); - if (d->rowResizeTimerID == 0) - d->rowResizeTimerID = startTimer(0); -} - -/*! - This slot is called to change the width of the given \a column. - The old width is specified by \a oldWidth, and the new width by \a - newWidth. - - \sa rowResized() -*/ -void QTableView::columnResized(int column, int, int) -{ - Q_D(QTableView); - d->columnsToUpdate.append(column); - if (d->columnResizeTimerID == 0) - d->columnResizeTimerID = startTimer(0); -} - -/*! - \reimp - */ -void QTableView::timerEvent(QTimerEvent *event) -{ - Q_D(QTableView); - - if (event->timerId() == d->columnResizeTimerID) { - updateGeometries(); - killTimer(d->columnResizeTimerID); - d->columnResizeTimerID = 0; - - QRect rect; - int viewportHeight = d->viewport->height(); - int viewportWidth = d->viewport->width(); - if (d->hasSpans()) { - rect = QRect(0, 0, viewportWidth, viewportHeight); - } else { - for (int i = d->columnsToUpdate.size()-1; i >= 0; --i) { - int column = d->columnsToUpdate.at(i); - int x = columnViewportPosition(column); - if (isRightToLeft()) - rect |= QRect(0, 0, x + columnWidth(column), viewportHeight); - else - rect |= QRect(x, 0, viewportWidth - x, viewportHeight); - } - } - - d->viewport->update(rect.normalized()); - d->columnsToUpdate.clear(); - } - - if (event->timerId() == d->rowResizeTimerID) { - updateGeometries(); - killTimer(d->rowResizeTimerID); - d->rowResizeTimerID = 0; - - int viewportHeight = d->viewport->height(); - int viewportWidth = d->viewport->width(); - int top; - if (d->hasSpans()) { - top = 0; - } else { - top = viewportHeight; - for (int i = d->rowsToUpdate.size()-1; i >= 0; --i) { - int y = rowViewportPosition(d->rowsToUpdate.at(i)); - top = qMin(top, y); - } - } - - d->viewport->update(QRect(0, top, viewportWidth, viewportHeight - top)); - d->rowsToUpdate.clear(); - } - - QAbstractItemView::timerEvent(event); -} - -/*! - This slot is called to change the index of the given \a row in the - table view. The old index is specified by \a oldIndex, and the new - index by \a newIndex. - - \sa columnMoved() -*/ -void QTableView::rowMoved(int, int oldIndex, int newIndex) -{ - Q_D(QTableView); - - updateGeometries(); - int logicalOldIndex = d->verticalHeader->logicalIndex(oldIndex); - int logicalNewIndex = d->verticalHeader->logicalIndex(newIndex); - if (d->hasSpans()) { - d->viewport->update(); - } else { - int oldTop = rowViewportPosition(logicalOldIndex); - int newTop = rowViewportPosition(logicalNewIndex); - int oldBottom = oldTop + rowHeight(logicalOldIndex); - int newBottom = newTop + rowHeight(logicalNewIndex); - int top = qMin(oldTop, newTop); - int bottom = qMax(oldBottom, newBottom); - int height = bottom - top; - d->viewport->update(0, top, d->viewport->width(), height); - } -} - -/*! - This slot is called to change the index of the given \a column in - the table view. The old index is specified by \a oldIndex, and - the new index by \a newIndex. - - \sa rowMoved() -*/ -void QTableView::columnMoved(int, int oldIndex, int newIndex) -{ - Q_D(QTableView); - - updateGeometries(); - int logicalOldIndex = d->horizontalHeader->logicalIndex(oldIndex); - int logicalNewIndex = d->horizontalHeader->logicalIndex(newIndex); - if (d->hasSpans()) { - d->viewport->update(); - } else { - int oldLeft = columnViewportPosition(logicalOldIndex); - int newLeft = columnViewportPosition(logicalNewIndex); - int oldRight = oldLeft + columnWidth(logicalOldIndex); - int newRight = newLeft + columnWidth(logicalNewIndex); - int left = qMin(oldLeft, newLeft); - int right = qMax(oldRight, newRight); - int width = right - left; - d->viewport->update(left, 0, width, d->viewport->height()); - } -} - -/*! - Selects the given \a row in the table view if the current - SelectionMode and SelectionBehavior allows rows to be selected. - - \sa selectColumn() -*/ -void QTableView::selectRow(int row) -{ - Q_D(QTableView); - d->selectRow(row, true); -} - -/*! - Selects the given \a column in the table view if the current - SelectionMode and SelectionBehavior allows columns to be selected. - - \sa selectRow() -*/ -void QTableView::selectColumn(int column) -{ - Q_D(QTableView); - d->selectColumn(column, true); -} - -/*! - Hide the given \a row. - - \sa showRow() hideColumn() -*/ -void QTableView::hideRow(int row) -{ - Q_D(QTableView); - d->verticalHeader->hideSection(row); -} - -/*! - Hide the given \a column. - - \sa showColumn() hideRow() -*/ -void QTableView::hideColumn(int column) -{ - Q_D(QTableView); - d->horizontalHeader->hideSection(column); -} - -/*! - Show the given \a row. - - \sa hideRow() showColumn() -*/ -void QTableView::showRow(int row) -{ - Q_D(QTableView); - d->verticalHeader->showSection(row); -} - -/*! - Show the given \a column. - - \sa hideColumn() showRow() -*/ -void QTableView::showColumn(int column) -{ - Q_D(QTableView); - d->horizontalHeader->showSection(column); -} - -/*! - Resizes the given \a row based on the size hints of the delegate - used to render each item in the row. -*/ -void QTableView::resizeRowToContents(int row) -{ - Q_D(QTableView); - int content = sizeHintForRow(row); - int header = d->verticalHeader->sectionSizeHint(row); - d->verticalHeader->resizeSection(row, qMax(content, header)); -} - -/*! - Resizes all rows based on the size hints of the delegate - used to render each item in the rows. -*/ -void QTableView::resizeRowsToContents() -{ - Q_D(QTableView); - d->verticalHeader->resizeSections(QHeaderView::ResizeToContents); -} - -/*! - Resizes the given \a column based on the size hints of the delegate - used to render each item in the column. - - \note Only visible columns will be resized. Reimplement sizeHintForColumn() - to resize hidden columns as well. -*/ -void QTableView::resizeColumnToContents(int column) -{ - Q_D(QTableView); - int content = sizeHintForColumn(column); - int header = d->horizontalHeader->sectionSizeHint(column); - d->horizontalHeader->resizeSection(column, qMax(content, header)); -} - -/*! - Resizes all columns based on the size hints of the delegate - used to render each item in the columns. -*/ -void QTableView::resizeColumnsToContents() -{ - Q_D(QTableView); - d->horizontalHeader->resizeSections(QHeaderView::ResizeToContents); -} - -/*! - \obsolete - \overload - - Sorts the model by the values in the given \a column. -*/ -void QTableView::sortByColumn(int column) -{ - Q_D(QTableView); - if (column == -1) - return; - d->model->sort(column, d->horizontalHeader->sortIndicatorOrder()); -} - -/*! - \since 4.2 - - Sorts the model by the values in the given \a column in the given \a order. - - \sa sortingEnabled - */ -void QTableView::sortByColumn(int column, Qt::SortOrder order) -{ - Q_D(QTableView); - d->horizontalHeader->setSortIndicator(column, order); - sortByColumn(column); -} - -/*! - \internal -*/ -void QTableView::verticalScrollbarAction(int action) -{ - QAbstractItemView::verticalScrollbarAction(action); -} - -/*! - \internal -*/ -void QTableView::horizontalScrollbarAction(int action) -{ - QAbstractItemView::horizontalScrollbarAction(action); -} - -/*! - \reimp -*/ -bool QTableView::isIndexHidden(const QModelIndex &index) const -{ - Q_D(const QTableView); - Q_ASSERT(d->isIndexValid(index)); - if (isRowHidden(index.row()) || isColumnHidden(index.column())) - return true; - if (d->hasSpans()) { - QSpanCollection::Span span = d->span(index.row(), index.column()); - return !((span.top() == index.row()) && (span.left() == index.column())); - } - return false; -} - -/*! - \fn void QTableView::setSpan(int row, int column, int rowSpanCount, int columnSpanCount) - \since 4.2 - - Sets the span of the table element at (\a row, \a column) to the number of - rows and columns specified by (\a rowSpanCount, \a columnSpanCount). - - \sa rowSpan(), columnSpan() -*/ -void QTableView::setSpan(int row, int column, int rowSpan, int columnSpan) -{ - Q_D(QTableView); - if (row < 0 || column < 0 || rowSpan < 0 || columnSpan < 0) - return; - d->setSpan(row, column, rowSpan, columnSpan); - d->viewport->update(); -} - -/*! - \since 4.2 - - Returns the row span of the table element at (\a row, \a column). - The default is 1. - - \sa setSpan(), columnSpan() -*/ -int QTableView::rowSpan(int row, int column) const -{ - Q_D(const QTableView); - return d->rowSpan(row, column); -} - -/*! - \since 4.2 - - Returns the column span of the table element at (\a row, \a - column). The default is 1. - - \sa setSpan(), rowSpan() -*/ -int QTableView::columnSpan(int row, int column) const -{ - Q_D(const QTableView); - return d->columnSpan(row, column); -} - -/*! - \since 4.4 - - Removes all row and column spans in the table view. - - \sa setSpan() -*/ - -void QTableView::clearSpans() -{ - Q_D(QTableView); - d->spans.clear(); - d->viewport->update(); -} - -void QTableViewPrivate::_q_selectRow(int row) -{ - selectRow(row, false); -} - -void QTableViewPrivate::_q_selectColumn(int column) -{ - selectColumn(column, false); -} - -void QTableViewPrivate::selectRow(int row, bool anchor) -{ - Q_Q(QTableView); - - if (q->selectionBehavior() == QTableView::SelectColumns - || (q->selectionMode() == QTableView::SingleSelection - && q->selectionBehavior() == QTableView::SelectItems)) - return; - - if (row >= 0 && row < model->rowCount(root)) { - int column = horizontalHeader->logicalIndexAt(q->isRightToLeft() ? viewport->width() : 0); - QModelIndex index = model->index(row, column, root); - QItemSelectionModel::SelectionFlags command = q->selectionCommand(index); - selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); - if ((anchor && !(command & QItemSelectionModel::Current)) - || (q->selectionMode() == QTableView::SingleSelection)) - rowSectionAnchor = row; - - if (q->selectionMode() != QTableView::SingleSelection - && command.testFlag(QItemSelectionModel::Toggle)) { - if (anchor) - ctrlDragSelectionFlag = verticalHeader->selectionModel()->selectedRows().contains(index) - ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; - command &= ~QItemSelectionModel::Toggle; - command |= ctrlDragSelectionFlag; - if (!anchor) - command |= QItemSelectionModel::Current; - } - - QModelIndex tl = model->index(qMin(rowSectionAnchor, row), 0, root); - QModelIndex br = model->index(qMax(rowSectionAnchor, row), model->columnCount(root) - 1, root); - if (verticalHeader->sectionsMoved() && tl.row() != br.row()) - q->setSelection(q->visualRect(tl)|q->visualRect(br), command); - else - selectionModel->select(QItemSelection(tl, br), command); - } -} - -void QTableViewPrivate::selectColumn(int column, bool anchor) -{ - Q_Q(QTableView); - - if (q->selectionBehavior() == QTableView::SelectRows - || (q->selectionMode() == QTableView::SingleSelection - && q->selectionBehavior() == QTableView::SelectItems)) - return; - - if (column >= 0 && column < model->columnCount(root)) { - int row = verticalHeader->logicalIndexAt(0); - QModelIndex index = model->index(row, column, root); - QItemSelectionModel::SelectionFlags command = q->selectionCommand(index); - selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); - if ((anchor && !(command & QItemSelectionModel::Current)) - || (q->selectionMode() == QTableView::SingleSelection)) - columnSectionAnchor = column; - - if (q->selectionMode() != QTableView::SingleSelection - && command.testFlag(QItemSelectionModel::Toggle)) { - if (anchor) - ctrlDragSelectionFlag = horizontalHeader->selectionModel()->selectedColumns().contains(index) - ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; - command &= ~QItemSelectionModel::Toggle; - command |= ctrlDragSelectionFlag; - if (!anchor) - command |= QItemSelectionModel::Current; - } - - QModelIndex tl = model->index(0, qMin(columnSectionAnchor, column), root); - QModelIndex br = model->index(model->rowCount(root) - 1, - qMax(columnSectionAnchor, column), root); - if (horizontalHeader->sectionsMoved() && tl.column() != br.column()) - q->setSelection(q->visualRect(tl)|q->visualRect(br), command); - else - selectionModel->select(QItemSelection(tl, br), command); - } -} - -/*! - \reimp - */ -void QTableView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) -{ -#ifndef QT_NO_ACCESSIBILITY - if (QAccessible::isActive()) { - if (current.isValid()) { - int entry = visualIndex(current) + 1; - if (horizontalHeader()) - ++entry; - QAccessible::updateAccessibility(viewport(), entry, QAccessible::Focus); - } - } -#endif - QAbstractItemView::currentChanged(current, previous); -} - -/*! - \reimp - */ -void QTableView::selectionChanged(const QItemSelection &selected, - const QItemSelection &deselected) -{ -#ifndef QT_NO_ACCESSIBILITY - if (QAccessible::isActive()) { - // ### does not work properly for selection ranges. - QModelIndex sel = selected.indexes().value(0); - if (sel.isValid()) { - int entry = visualIndex(sel); - if (horizontalHeader()) - ++entry; - QAccessible::updateAccessibility(viewport(), entry, QAccessible::Selection); - } - QModelIndex desel = deselected.indexes().value(0); - if (desel.isValid()) { - int entry = visualIndex(sel); - if (horizontalHeader()) - ++entry; - QAccessible::updateAccessibility(viewport(), entry, QAccessible::SelectionRemove); - } - } -#endif - QAbstractItemView::selectionChanged(selected, deselected); -} - -int QTableView::visualIndex(const QModelIndex &index) const -{ - return index.row(); -} - -QT_END_NAMESPACE - -#include "qtableview.moc" - -#include "moc_qtableview.cpp" - -#endif // QT_NO_TABLEVIEW |