diff options
Diffstat (limited to 'src/gui/itemviews/qheaderview.cpp')
-rw-r--r-- | src/gui/itemviews/qheaderview.cpp | 3615 |
1 files changed, 0 insertions, 3615 deletions
diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp deleted file mode 100644 index 471c199bc2..0000000000 --- a/src/gui/itemviews/qheaderview.cpp +++ /dev/null @@ -1,3615 +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 "qheaderview.h" - -#ifndef QT_NO_ITEMVIEWS -#include <qbitarray.h> -#include <qbrush.h> -#include <qdebug.h> -#include <qevent.h> -#include <qpainter.h> -#include <qscrollbar.h> -#include <qtooltip.h> -#include <qwhatsthis.h> -#include <qstyle.h> -#include <qstyleoption.h> -#include <qvector.h> -#include <qapplication.h> -#include <qvarlengtharray.h> -#include <qabstractitemdelegate.h> -#include <qvariant.h> -#include <private/qheaderview_p.h> -#include <private/qabstractitemmodel_p.h> - -#ifndef QT_NO_DATASTREAM -#include <qdatastream.h> -#endif - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_DATASTREAM -QDataStream &operator<<(QDataStream &out, const QHeaderViewPrivate::SectionSpan &span) -{ - span.write(out); - return out; -} - -QDataStream &operator>>(QDataStream &in, QHeaderViewPrivate::SectionSpan &span) -{ - span.read(in); - return in; -} -#endif // QT_NO_DATASTREAM - - -/*! - \class QHeaderView - - \brief The QHeaderView class provides a header row or header column for - item views. - - \ingroup model-view - - - A QHeaderView displays the headers used in item views such as the - QTableView and QTreeView classes. It takes the place of Qt3's \c QHeader - class previously used for the same purpose, but uses the Qt's model/view - architecture for consistency with the item view classes. - - The QHeaderView class is one of the \l{Model/View Classes} and is part of - Qt's \l{Model/View Programming}{model/view framework}. - - The header gets the data for each section from the model using the - QAbstractItemModel::headerData() function. You can set the data by using - QAbstractItemModel::setHeaderData(). - - Each header has an orientation() and a number of sections, given by the - count() function. A section refers to a part of the header - either a row - or a column, depending on the orientation. - - Sections can be moved and resized using moveSection() and resizeSection(); - they can also be hidden and shown with hideSection() and showSection(). - - Each section of a header is described by a section ID, specified by its - section(), and can be located at a particular visualIndex() in the header. - A section can have a sort indicator set with setSortIndicator(); this - indicates whether the items in the associated item view will be sorted in - the order given by the section. - - For a horizontal header the section is equivalent to a column in the model, - and for a vertical header the section is equivalent to a row in the model. - - \section1 Moving Header Sections - - A header can be fixed in place, or made movable with setMovable(). It can - be made clickable with setClickable(), and has resizing behavior in - accordance with setResizeMode(). - - \note Double-clicking on a header to resize a section only applies for - visible rows. - - A header will emit sectionMoved() if the user moves a section, - sectionResized() if the user resizes a section, and sectionClicked() as - well as sectionHandleDoubleClicked() in response to mouse clicks. A header - will also emit sectionCountChanged() and sectionAutoResize(). - - You can identify a section using the logicalIndex() and logicalIndexAt() - functions, or by its index position, using the visualIndex() and - visualIndexAt() functions. The visual index will change if a section is - moved, but the logical index will not change. - - \section1 Appearance - - QTableWidget and QTableView create default headers. If you want - the headers to be visible, you can use \l{QFrame::}{setVisible()}. - - Not all \l{Qt::}{ItemDataRole}s will have an effect on a - QHeaderView. If you need to draw other roles, you can subclass - QHeaderView and reimplement \l{QHeaderView::}{paintEvent()}. - QHeaderView respects the following item data roles: - \l{Qt::}{TextAlignmentRole}, \l{Qt::}{DisplayRole}, - \l{Qt::}{FontRole}, \l{Qt::}{DecorationRole}, - \l{Qt::}{ForegroundRole}, and \l{Qt::}{BackgroundRole}. - - \note Each header renders the data for each section itself, and does not - rely on a delegate. As a result, calling a header's setItemDelegate() - function will have no effect. - - \sa {Model/View Programming}, QListView, QTableView, QTreeView -*/ - -/*! - \enum QHeaderView::ResizeMode - - The resize mode specifies the behavior of the header sections. It can be - set on the entire header view or on individual sections using - setResizeMode(). - - \value Interactive The user can resize the section. The section can also be - resized programmatically using resizeSection(). The section size - defaults to \l defaultSectionSize. (See also - \l cascadingSectionResizes.) - - \value Fixed The user cannot resize the section. The section can only be - resized programmatically using resizeSection(). The section size - defaults to \l defaultSectionSize. - - \value Stretch QHeaderView will automatically resize the section to fill - the available space. The size cannot be changed by the user or - programmatically. - - \value ResizeToContents QHeaderView will automatically resize the section - to its optimal size based on the contents of the entire column or - row. The size cannot be changed by the user or programmatically. - (This value was introduced in 4.2) - - The following values are obsolete: - \value Custom Use Fixed instead. - - \sa setResizeMode() stretchLastSection minimumSectionSize -*/ - -/*! - \fn void QHeaderView::sectionMoved(int logicalIndex, int oldVisualIndex, - int newVisualIndex) - - This signal is emitted when a section is moved. The section's logical index - is specified by \a logicalIndex, the old index by \a oldVisualIndex, and - the new index position by \a newVisualIndex. - - \sa moveSection() -*/ - -/*! - \fn void QHeaderView::sectionResized(int logicalIndex, int oldSize, - int newSize) - - This signal is emitted when a section is resized. The section's logical - number is specified by \a logicalIndex, the old size by \a oldSize, and the - new size by \a newSize. - - \sa resizeSection() -*/ - -/*! - \fn void QHeaderView::sectionPressed(int logicalIndex) - - This signal is emitted when a section is pressed. The section's logical - index is specified by \a logicalIndex. - - \sa setClickable() -*/ - -/*! - \fn void QHeaderView::sectionClicked(int logicalIndex) - - This signal is emitted when a section is clicked. The section's logical - index is specified by \a logicalIndex. - - Note that the sectionPressed signal will also be emitted. - - \sa setClickable(), sectionPressed() -*/ - -/*! - \fn void QHeaderView::sectionEntered(int logicalIndex) - \since 4.3 - - This signal is emitted when the cursor moves over the section and the left - mouse button is pressed. The section's logical index is specified by - \a logicalIndex. - - \sa setClickable(), sectionPressed() -*/ - -/*! - \fn void QHeaderView::sectionDoubleClicked(int logicalIndex) - - This signal is emitted when a section is double-clicked. The section's - logical index is specified by \a logicalIndex. - - \sa setClickable() -*/ - -/*! - \fn void QHeaderView::sectionCountChanged(int oldCount, int newCount) - - This signal is emitted when the number of sections changes, i.e., when - sections are added or deleted. The original count is specified by - \a oldCount, and the new count by \a newCount. - - \sa count(), length(), headerDataChanged() -*/ - -/*! - \fn void QHeaderView::sectionHandleDoubleClicked(int logicalIndex) - - This signal is emitted when a section is double-clicked. The section's - logical index is specified by \a logicalIndex. - - \sa setClickable() -*/ - -/*! - \fn void QHeaderView::sortIndicatorChanged(int logicalIndex, - Qt::SortOrder order) - \since 4.3 - - This signal is emitted when the section containing the sort indicator or - the order indicated is changed. The section's logical index is specified - by \a logicalIndex and the sort order is specified by \a order. - - \sa setSortIndicator() -*/ - -/*! - \fn void QHeaderView::sectionAutoResize(int logicalIndex, - QHeaderView::ResizeMode mode) - - This signal is emitted when a section is automatically resized. The - section's logical index is specified by \a logicalIndex, and the resize - mode by \a mode. - - \sa setResizeMode(), stretchLastSection() -*/ -// ### Qt 5: change to sectionAutoResized() - -/*! - \fn void QHeaderView::geometriesChanged() - \since 4.2 - - This signal is emitted when the header's geometries have changed. -*/ - -/*! - \property QHeaderView::highlightSections - \brief whether the sections containing selected items are highlighted - - By default, this property is false. -*/ - -/*! - Creates a new generic header with the given \a orientation and \a parent. -*/ -QHeaderView::QHeaderView(Qt::Orientation orientation, QWidget *parent) - : QAbstractItemView(*new QHeaderViewPrivate, parent) -{ - Q_D(QHeaderView); - d->setDefaultValues(orientation); - initialize(); -} - -/*! - \internal -*/ -QHeaderView::QHeaderView(QHeaderViewPrivate &dd, - Qt::Orientation orientation, QWidget *parent) - : QAbstractItemView(dd, parent) -{ - Q_D(QHeaderView); - d->setDefaultValues(orientation); - initialize(); -} - -/*! - Destroys the header. -*/ - -QHeaderView::~QHeaderView() -{ -} - -/*! - \internal -*/ -void QHeaderView::initialize() -{ - Q_D(QHeaderView); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setFrameStyle(NoFrame); - setFocusPolicy(Qt::NoFocus); - d->viewport->setMouseTracking(true); - d->viewport->setBackgroundRole(QPalette::Button); - d->textElideMode = Qt::ElideNone; - delete d->itemDelegate; -} - -/*! - \reimp -*/ -void QHeaderView::setModel(QAbstractItemModel *model) -{ - if (model == this->model()) - return; - Q_D(QHeaderView); - if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) { - if (d->orientation == Qt::Horizontal) { - QObject::disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(sectionsInserted(QModelIndex,int,int))); - QObject::disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(sectionsAboutToBeRemoved(QModelIndex,int,int))); - QObject::disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sectionsRemoved(QModelIndex,int,int))); - } else { - QObject::disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(sectionsInserted(QModelIndex,int,int))); - QObject::disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(sectionsAboutToBeRemoved(QModelIndex,int,int))); - QObject::disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sectionsRemoved(QModelIndex,int,int))); - } - QObject::disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(headerDataChanged(Qt::Orientation,int,int))); - QObject::disconnect(d->model, SIGNAL(layoutAboutToBeChanged()), - this, SLOT(_q_layoutAboutToBeChanged())); - } - - if (model && model != QAbstractItemModelPrivate::staticEmptyModel()) { - if (d->orientation == Qt::Horizontal) { - QObject::connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(sectionsInserted(QModelIndex,int,int))); - QObject::connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(sectionsAboutToBeRemoved(QModelIndex,int,int))); - QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sectionsRemoved(QModelIndex,int,int))); - } else { - QObject::connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(sectionsInserted(QModelIndex,int,int))); - QObject::connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(sectionsAboutToBeRemoved(QModelIndex,int,int))); - QObject::connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_sectionsRemoved(QModelIndex,int,int))); - } - QObject::connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(headerDataChanged(Qt::Orientation,int,int))); - QObject::connect(model, SIGNAL(layoutAboutToBeChanged()), - this, SLOT(_q_layoutAboutToBeChanged())); - } - - d->state = QHeaderViewPrivate::NoClear; - QAbstractItemView::setModel(model); - d->state = QHeaderViewPrivate::NoState; - - // Users want to set sizes and modes before the widget is shown. - // Thus, we have to initialize when the model is set, - // and not lazily like we do in the other views. - initializeSections(); -} - -/*! - Returns the orientation of the header. - - \sa Qt::Orientation -*/ - -Qt::Orientation QHeaderView::orientation() const -{ - Q_D(const QHeaderView); - return d->orientation; -} - -/*! - Returns the offset of the header: this is the header's left-most (or - top-most for vertical headers) visible pixel. - - \sa setOffset() -*/ - -int QHeaderView::offset() const -{ - Q_D(const QHeaderView); - return d->offset; -} - -/*! - \fn void QHeaderView::setOffset(int offset) - - Sets the header's offset to \a offset. - - \sa offset(), length() -*/ - -void QHeaderView::setOffset(int newOffset) -{ - Q_D(QHeaderView); - if (d->offset == (int)newOffset) - return; - int ndelta = d->offset - newOffset; - d->offset = newOffset; - if (d->orientation == Qt::Horizontal) - d->viewport->scroll(isRightToLeft() ? -ndelta : ndelta, 0); - else - d->viewport->scroll(0, ndelta); - if (d->state == QHeaderViewPrivate::ResizeSection) { - QPoint cursorPos = QCursor::pos(); - if (d->orientation == Qt::Horizontal) - QCursor::setPos(cursorPos.x() + ndelta, cursorPos.y()); - else - QCursor::setPos(cursorPos.x(), cursorPos.y() + ndelta); - d->firstPos += ndelta; - d->lastPos += ndelta; - } -} - -/*! - \since 4.2 - Sets the offset to the start of the section at the given \a visualIndex. - - \sa setOffset(), sectionPosition() -*/ -void QHeaderView::setOffsetToSectionPosition(int visualIndex) -{ - Q_D(QHeaderView); - if (visualIndex > -1 && visualIndex < d->sectionCount) { - int position = d->headerSectionPosition(d->adjustedVisualIndex(visualIndex)); - setOffset(position); - } -} - -/*! - \since 4.2 - Sets the offset to make the last section visible. - - \sa setOffset(), sectionPosition(), setOffsetToSectionPosition() -*/ -void QHeaderView::setOffsetToLastSection() -{ - Q_D(const QHeaderView); - int size = (d->orientation == Qt::Horizontal ? viewport()->width() : viewport()->height()); - int position = length() - size; - setOffset(position); -} - -/*! - Returns the length along the orientation of the header. - - \sa sizeHint(), setResizeMode(), offset() -*/ - -int QHeaderView::length() const -{ - Q_D(const QHeaderView); - //Q_ASSERT(d->headerLength() == d->length); - return d->length; -} - -/*! - Returns a suitable size hint for this header. - - \sa sectionSizeHint() -*/ - -QSize QHeaderView::sizeHint() const -{ - Q_D(const QHeaderView); - if (d->cachedSizeHint.isValid()) - return d->cachedSizeHint; - d->cachedSizeHint = QSize(0, 0); //reinitialize the cached size hint - const int sectionCount = count(); - - // get size hint for the first n sections - int i = 0; - for (int checked = 0; checked < 100 && i < sectionCount; ++i) { - if (isSectionHidden(i)) - continue; - checked++; - QSize hint = sectionSizeFromContents(i); - d->cachedSizeHint = d->cachedSizeHint.expandedTo(hint); - } - // get size hint for the last n sections - i = qMax(i, sectionCount - 100 ); - for (int j = sectionCount - 1, checked = 0; j >= i && checked < 100; --j) { - if (isSectionHidden(j)) - continue; - checked++; - QSize hint = sectionSizeFromContents(j); - d->cachedSizeHint = d->cachedSizeHint.expandedTo(hint); - } - return d->cachedSizeHint; -} - -/*! - Returns a suitable size hint for the section specified by \a logicalIndex. - - \sa sizeHint(), defaultSectionSize(), minimumSectionSize(), - Qt::SizeHintRole -*/ - -int QHeaderView::sectionSizeHint(int logicalIndex) const -{ - Q_D(const QHeaderView); - if (isSectionHidden(logicalIndex)) - return 0; - if (logicalIndex < 0 || logicalIndex >= count()) - return -1; - QSize size; - QVariant value = d->model->headerData(logicalIndex, d->orientation, Qt::SizeHintRole); - if (value.isValid()) - size = qvariant_cast<QSize>(value); - else - size = sectionSizeFromContents(logicalIndex); - int hint = d->orientation == Qt::Horizontal ? size.width() : size.height(); - return qMax(minimumSectionSize(), hint); -} - -/*! - Returns the visual index of the section that covers the given \a position - in the viewport. - - \sa logicalIndexAt() -*/ - -int QHeaderView::visualIndexAt(int position) const -{ - Q_D(const QHeaderView); - int vposition = position; - d->executePostedLayout(); - d->executePostedResize(); - const int count = d->sectionCount; - if (count < 1) - return -1; - - if (d->reverse()) - vposition = d->viewport->width() - vposition; - vposition += d->offset; - - if (vposition > d->length) - return -1; - int visual = d->headerVisualIndexAt(vposition); - if (visual < 0) - return -1; - - while (d->isVisualIndexHidden(visual)){ - ++visual; - if (visual >= count) - return -1; - } - return visual; -} - -/*! - Returns the section that covers the given \a position in the viewport. - - \sa visualIndexAt(), isSectionHidden() -*/ - -int QHeaderView::logicalIndexAt(int position) const -{ - const int visual = visualIndexAt(position); - if (visual > -1) - return logicalIndex(visual); - return -1; -} - -/*! - Returns the width (or height for vertical headers) of the given - \a logicalIndex. - - \sa length(), setResizeMode(), defaultSectionSize() -*/ - -int QHeaderView::sectionSize(int logicalIndex) const -{ - Q_D(const QHeaderView); - if (isSectionHidden(logicalIndex)) - return 0; - if (logicalIndex < 0 || logicalIndex >= count()) - return 0; - int visual = visualIndex(logicalIndex); - if (visual == -1) - return 0; - d->executePostedResize(); - return d->headerSectionSize(visual); -} - -/*! - - Returns the section position of the given \a logicalIndex, or -1 - if the section is hidden. The position is measured in pixels from - the first visible item's top-left corner to the top-left corner of - the item with \a logicalIndex. The measurement is along the x-axis - for horizontal headers and along the y-axis for vertical headers. - - \sa sectionViewportPosition() -*/ - -int QHeaderView::sectionPosition(int logicalIndex) const -{ - Q_D(const QHeaderView); - int visual = visualIndex(logicalIndex); - // in some cases users may change the selections - // before we have a chance to do the layout - if (visual == -1) - return -1; - d->executePostedResize(); - return d->headerSectionPosition(visual); -} - -/*! - Returns the section viewport position of the given \a logicalIndex. - - If the section is hidden, the return value is undefined. - - \sa sectionPosition(), isSectionHidden() -*/ - -int QHeaderView::sectionViewportPosition(int logicalIndex) const -{ - Q_D(const QHeaderView); - if (logicalIndex >= count()) - return -1; - int position = sectionPosition(logicalIndex); - if (position < 0) - return position; // the section was hidden - int offsetPosition = position - d->offset; - if (d->reverse()) - return d->viewport->width() - (offsetPosition + sectionSize(logicalIndex)); - return offsetPosition; -} - -/*! - \fn int QHeaderView::logicalIndexAt(int x, int y) const - - Returns the logical index of the section at the given coordinate. If the - header is horizontal \a x will be used, otherwise \a y will be used to - find the logical index. -*/ - -/*! - \fn int QHeaderView::logicalIndexAt(const QPoint &pos) const - - Returns the logical index of the section at the position given in \a pos. - If the header is horizontal the x-coordinate will be used, otherwise the - y-coordinate will be used to find the logical index. - - \sa sectionPosition() -*/ - -/*! - Moves the section at visual index \a from to occupy visual index \a to. - - \sa sectionsMoved() -*/ - -void QHeaderView::moveSection(int from, int to) -{ - Q_D(QHeaderView); - - d->executePostedLayout(); - if (from < 0 || from >= d->sectionCount || to < 0 || to >= d->sectionCount) - return; - - if (from == to) { - int logical = logicalIndex(from); - Q_ASSERT(logical != -1); - updateSection(logical); - return; - } - - if (stretchLastSection() && to == d->lastVisibleVisualIndex()) - d->lastSectionSize = sectionSize(from); - - //int oldHeaderLength = length(); // ### for debugging; remove later - d->initializeIndexMapping(); - - QBitArray sectionHidden = d->sectionHidden; - int *visualIndices = d->visualIndices.data(); - int *logicalIndices = d->logicalIndices.data(); - int logical = logicalIndices[from]; - int visual = from; - - int affected_count = qAbs(to - from) + 1; - QVarLengthArray<int> sizes(affected_count); - QVarLengthArray<ResizeMode> modes(affected_count); - - // move sections and indices - if (to > from) { - sizes[to - from] = d->headerSectionSize(from); - modes[to - from] = d->headerSectionResizeMode(from); - while (visual < to) { - sizes[visual - from] = d->headerSectionSize(visual + 1); - modes[visual - from] = d->headerSectionResizeMode(visual + 1); - if (!sectionHidden.isEmpty()) - sectionHidden.setBit(visual, sectionHidden.testBit(visual + 1)); - visualIndices[logicalIndices[visual + 1]] = visual; - logicalIndices[visual] = logicalIndices[visual + 1]; - ++visual; - } - } else { - sizes[0] = d->headerSectionSize(from); - modes[0] = d->headerSectionResizeMode(from); - while (visual > to) { - sizes[visual - to] = d->headerSectionSize(visual - 1); - modes[visual - to] = d->headerSectionResizeMode(visual - 1); - if (!sectionHidden.isEmpty()) - sectionHidden.setBit(visual, sectionHidden.testBit(visual - 1)); - visualIndices[logicalIndices[visual - 1]] = visual; - logicalIndices[visual] = logicalIndices[visual - 1]; - --visual; - } - } - if (!sectionHidden.isEmpty()) { - sectionHidden.setBit(to, d->sectionHidden.testBit(from)); - d->sectionHidden = sectionHidden; - } - visualIndices[logical] = to; - logicalIndices[to] = logical; - - //Q_ASSERT(oldHeaderLength == length()); - // move sizes - // ### check for spans of section sizes here - if (to > from) { - for (visual = from; visual <= to; ++visual) { - int size = sizes[visual - from]; - ResizeMode mode = modes[visual - from]; - d->createSectionSpan(visual, visual, size, mode); - } - } else { - for (visual = to; visual <= from; ++visual) { - int size = sizes[visual - to]; - ResizeMode mode = modes[visual - to]; - d->createSectionSpan(visual, visual, size, mode); - } - } - //Q_ASSERT(d->headerLength() == length()); - //Q_ASSERT(oldHeaderLength == length()); - //Q_ASSERT(d->logicalIndices.count() == d->sectionCount); - - if (d->hasAutoResizeSections()) - d->doDelayedResizeSections(); - d->viewport->update(); - - emit sectionMoved(logical, from, to); -} - -/*! - \since 4.2 - Swaps the section at visual index \a first with the section at visual - index \a second. - - \sa moveSection() -*/ -void QHeaderView::swapSections(int first, int second) -{ - Q_D(QHeaderView); - - if (first == second) - return; - d->executePostedLayout(); - if (first < 0 || first >= d->sectionCount || second < 0 || second >= d->sectionCount) - return; - - int firstSize = d->headerSectionSize(first); - ResizeMode firstMode = d->headerSectionResizeMode(first); - int firstLogical = d->logicalIndex(first); - - int secondSize = d->headerSectionSize(second); - ResizeMode secondMode = d->headerSectionResizeMode(second); - int secondLogical = d->logicalIndex(second); - - d->createSectionSpan(second, second, firstSize, firstMode); - d->createSectionSpan(first, first, secondSize, secondMode); - - d->initializeIndexMapping(); - - d->visualIndices[firstLogical] = second; - d->logicalIndices[second] = firstLogical; - - d->visualIndices[secondLogical] = first; - d->logicalIndices[first] = secondLogical; - - if (!d->sectionHidden.isEmpty()) { - bool firstHidden = d->sectionHidden.testBit(first); - bool secondHidden = d->sectionHidden.testBit(second); - d->sectionHidden.setBit(first, secondHidden); - d->sectionHidden.setBit(second, firstHidden); - } - - d->viewport->update(); - emit sectionMoved(firstLogical, first, second); - emit sectionMoved(secondLogical, second, first); -} - -/*! - \fn void QHeaderView::resizeSection(int logicalIndex, int size) - - Resizes the section specified by \a logicalIndex to \a size measured in - pixels. - - \sa sectionResized(), resizeMode(), sectionSize() -*/ - -void QHeaderView::resizeSection(int logical, int size) -{ - Q_D(QHeaderView); - if (logical < 0 || logical >= count()) - return; - - if (isSectionHidden(logical)) { - d->hiddenSectionSize.insert(logical, size); - return; - } - - int visual = visualIndex(logical); - if (visual == -1) - return; - - int oldSize = d->headerSectionSize(visual); - if (oldSize == size) - return; - - d->executePostedLayout(); - d->invalidateCachedSizeHint(); - - if (stretchLastSection() && visual == d->lastVisibleVisualIndex()) - d->lastSectionSize = size; - - if (size != oldSize) - d->createSectionSpan(visual, visual, size, d->headerSectionResizeMode(visual)); - - int w = d->viewport->width(); - int h = d->viewport->height(); - int pos = sectionViewportPosition(logical); - QRect r; - if (d->orientation == Qt::Horizontal) - if (isRightToLeft()) - r.setRect(0, 0, pos + size, h); - else - r.setRect(pos, 0, w - pos, h); - else - r.setRect(0, pos, w, h - pos); - - if (d->hasAutoResizeSections()) { - d->doDelayedResizeSections(); - r = d->viewport->rect(); - } - d->viewport->update(r.normalized()); - emit sectionResized(logical, oldSize, size); -} - -/*! - Resizes the sections according to the given \a mode, ignoring the current - resize mode. - - \sa resizeMode(), sectionResized() -*/ - -void QHeaderView::resizeSections(QHeaderView::ResizeMode mode) -{ - Q_D(QHeaderView); - d->resizeSections(mode, true); -} - -/*! - \fn void QHeaderView::hideSection(int logicalIndex) - Hides the section specified by \a logicalIndex. - - \sa showSection(), isSectionHidden(), hiddenSectionCount(), - setSectionHidden() -*/ - -/*! - \fn void QHeaderView::showSection(int logicalIndex) - Shows the section specified by \a logicalIndex. - - \sa hideSection(), isSectionHidden(), hiddenSectionCount(), - setSectionHidden() -*/ - -/*! - Returns true if the section specified by \a logicalIndex is explicitly - hidden from the user; otherwise returns false. - - \sa hideSection(), showSection(), setSectionHidden(), hiddenSectionCount() -*/ - -bool QHeaderView::isSectionHidden(int logicalIndex) const -{ - Q_D(const QHeaderView); - d->executePostedLayout(); - if (logicalIndex >= d->sectionHidden.count() || logicalIndex < 0 || logicalIndex >= d->sectionCount) - return false; - int visual = visualIndex(logicalIndex); - Q_ASSERT(visual != -1); - return d->sectionHidden.testBit(visual); -} - -/*! - \since 4.1 - - Returns the number of sections in the header that has been hidden. - - \sa setSectionHidden(), isSectionHidden() -*/ -int QHeaderView::hiddenSectionCount() const -{ - Q_D(const QHeaderView); - return d->hiddenSectionSize.count(); -} - -/*! - If \a hide is true the section specified by \a logicalIndex is hidden; - otherwise the section is shown. - - \sa isSectionHidden(), hiddenSectionCount() -*/ - -void QHeaderView::setSectionHidden(int logicalIndex, bool hide) -{ - Q_D(QHeaderView); - if (logicalIndex < 0 || logicalIndex >= count()) - return; - - d->executePostedLayout(); - int visual = visualIndex(logicalIndex); - Q_ASSERT(visual != -1); - if (hide == d->isVisualIndexHidden(visual)) - return; - if (hide) { - int size = d->headerSectionSize(visual); - if (!d->hasAutoResizeSections()) - resizeSection(logicalIndex, 0); - d->hiddenSectionSize.insert(logicalIndex, size); - if (d->sectionHidden.count() < count()) - d->sectionHidden.resize(count()); - d->sectionHidden.setBit(visual, true); - if (d->hasAutoResizeSections()) - d->doDelayedResizeSections(); - } else { - int size = d->hiddenSectionSize.value(logicalIndex, d->defaultSectionSize); - d->hiddenSectionSize.remove(logicalIndex); - if (d->hiddenSectionSize.isEmpty()) { - d->sectionHidden.clear(); - } else { - Q_ASSERT(visual <= d->sectionHidden.count()); - d->sectionHidden.setBit(visual, false); - } - resizeSection(logicalIndex, size); - } -} - -/*! - Returns the number of sections in the header. - - \sa sectionCountChanged(), length() -*/ - -int QHeaderView::count() const -{ - Q_D(const QHeaderView); - //Q_ASSERT(d->sectionCount == d->headerSectionCount()); - // ### this may affect the lazy layout - d->executePostedLayout(); - return d->sectionCount; -} - -/*! - Returns the visual index position of the section specified by the given - \a logicalIndex, or -1 otherwise. - - Hidden sections still have valid visual indexes. - - \sa logicalIndex() -*/ - -int QHeaderView::visualIndex(int logicalIndex) const -{ - Q_D(const QHeaderView); - if (logicalIndex < 0) - return -1; - d->executePostedLayout(); - if (d->visualIndices.isEmpty()) { // nothing has been moved, so we have no mapping - if (logicalIndex < d->sectionCount) - return logicalIndex; - } else if (logicalIndex < d->visualIndices.count()) { - int visual = d->visualIndices.at(logicalIndex); - Q_ASSERT(visual < d->sectionCount); - return visual; - } - return -1; -} - -/*! - Returns the logicalIndex for the section at the given \a visualIndex - position, or -1 if visualIndex < 0 or visualIndex >= QHeaderView::count(). - - Note that the visualIndex is not affected by hidden sections. - - \sa visualIndex(), sectionPosition() -*/ - -int QHeaderView::logicalIndex(int visualIndex) const -{ - Q_D(const QHeaderView); - if (visualIndex < 0 || visualIndex >= d->sectionCount) - return -1; - return d->logicalIndex(visualIndex); -} - -/*! - If \a movable is true, the header may be moved by the user; otherwise it - is fixed in place. - - \sa isMovable(), sectionMoved() -*/ - -// ### Qt 5: change to setSectionsMovable() -void QHeaderView::setMovable(bool movable) -{ - Q_D(QHeaderView); - d->movableSections = movable; -} - -/*! - Returns true if the header can be moved by the user; otherwise returns - false. - - \sa setMovable() -*/ - -// ### Qt 5: change to sectionsMovable() -bool QHeaderView::isMovable() const -{ - Q_D(const QHeaderView); - return d->movableSections; -} - -/*! - If \a clickable is true, the header will respond to single clicks. - - \sa isClickable(), sectionClicked(), sectionPressed(), - setSortIndicatorShown() -*/ - -// ### Qt 5: change to setSectionsClickable() -void QHeaderView::setClickable(bool clickable) -{ - Q_D(QHeaderView); - d->clickableSections = clickable; -} - -/*! - Returns true if the header is clickable; otherwise returns false. A - clickable header could be set up to allow the user to change the - representation of the data in the view related to the header. - - \sa setClickable() -*/ - -// ### Qt 5: change to sectionsClickable() -bool QHeaderView::isClickable() const -{ - Q_D(const QHeaderView); - return d->clickableSections; -} - -void QHeaderView::setHighlightSections(bool highlight) -{ - Q_D(QHeaderView); - d->highlightSelected = highlight; -} - -bool QHeaderView::highlightSections() const -{ - Q_D(const QHeaderView); - return d->highlightSelected; -} - -/*! - Sets the constraints on how the header can be resized to those described - by the given \a mode. - - \sa resizeMode(), length(), sectionResized(), sectionAutoResize() -*/ - -void QHeaderView::setResizeMode(ResizeMode mode) -{ - Q_D(QHeaderView); - initializeSections(); - d->stretchSections = (mode == Stretch ? count() : 0); - d->contentsSections = (mode == ResizeToContents ? count() : 0); - d->setGlobalHeaderResizeMode(mode); - if (d->hasAutoResizeSections()) - d->doDelayedResizeSections(); // section sizes may change as a result of the new mode -} - -/*! - \overload - - Sets the constraints on how the section specified by \a logicalIndex in - the header can be resized to those described by the given \a mode. The logical - index should exist at the time this function is called. - - \note This setting will be ignored for the last section if the stretchLastSection - property is set to true. This is the default for the horizontal headers provided - by QTreeView. - - \sa setStretchLastSection() -*/ - -// ### Qt 5: change to setSectionResizeMode() -void QHeaderView::setResizeMode(int logicalIndex, ResizeMode mode) -{ - Q_D(QHeaderView); - int visual = visualIndex(logicalIndex); - Q_ASSERT(visual != -1); - - ResizeMode old = d->headerSectionResizeMode(visual); - d->setHeaderSectionResizeMode(visual, mode); - - if (mode == Stretch && old != Stretch) - ++d->stretchSections; - else if (mode == ResizeToContents && old != ResizeToContents) - ++d->contentsSections; - else if (mode != Stretch && old == Stretch) - --d->stretchSections; - else if (mode != ResizeToContents && old == ResizeToContents) - --d->contentsSections; - - if (d->hasAutoResizeSections() && d->state == QHeaderViewPrivate::NoState) - d->doDelayedResizeSections(); // section sizes may change as a result of the new mode -} - -/*! - Returns the resize mode that applies to the section specified by the given - \a logicalIndex. - - \sa setResizeMode() -*/ - -QHeaderView::ResizeMode QHeaderView::resizeMode(int logicalIndex) const -{ - Q_D(const QHeaderView); - int visual = visualIndex(logicalIndex); - if (visual == -1) - return Fixed; //the default value - return d->headerSectionResizeMode(visual); -} - -/*! - \since 4.1 - - Returns the number of sections that are set to resize mode stretch. In - views, this can be used to see if the headerview needs to resize the - sections when the view's geometry changes. - - \sa stretchLastSection, resizeMode() -*/ - -int QHeaderView::stretchSectionCount() const -{ - Q_D(const QHeaderView); - return d->stretchSections; -} - -/*! - \property QHeaderView::showSortIndicator - \brief whether the sort indicator is shown - - By default, this property is false. - - \sa setClickable() -*/ - -void QHeaderView::setSortIndicatorShown(bool show) -{ - Q_D(QHeaderView); - if (d->sortIndicatorShown == show) - return; - - d->sortIndicatorShown = show; - - if (sortIndicatorSection() < 0 || sortIndicatorSection() > count()) - return; - - if (d->headerSectionResizeMode(sortIndicatorSection()) == ResizeToContents) - resizeSections(); - - d->viewport->update(); -} - -bool QHeaderView::isSortIndicatorShown() const -{ - Q_D(const QHeaderView); - return d->sortIndicatorShown; -} - -/*! - Sets the sort indicator for the section specified by the given - \a logicalIndex in the direction specified by \a order, and removes the - sort indicator from any other section that was showing it. - - \a logicalIndex may be -1, in which case no sort indicator will be shown - and the model will return to its natural, unsorted order. Note that not - all models support this and may even crash in this case. - - \sa sortIndicatorSection() sortIndicatorOrder() -*/ - -void QHeaderView::setSortIndicator(int logicalIndex, Qt::SortOrder order) -{ - Q_D(QHeaderView); - - // This is so that people can set the position of the sort indicator before the fill the model - int old = d->sortIndicatorSection; - d->sortIndicatorSection = logicalIndex; - d->sortIndicatorOrder = order; - - if (logicalIndex >= d->sectionCount) { - emit sortIndicatorChanged(logicalIndex, order); - return; // nothing to do - } - - if (old != logicalIndex - && ((logicalIndex >= 0 && resizeMode(logicalIndex) == ResizeToContents) - || old >= d->sectionCount || (old >= 0 && resizeMode(old) == ResizeToContents))) { - resizeSections(); - d->viewport->update(); - } else { - if (old >= 0 && old != logicalIndex) - updateSection(old); - if (logicalIndex >= 0) - updateSection(logicalIndex); - } - - emit sortIndicatorChanged(logicalIndex, order); -} - -/*! - Returns the logical index of the section that has a sort indicator. - By default this is section 0. - - \sa setSortIndicator() sortIndicatorOrder() setSortIndicatorShown() -*/ - -int QHeaderView::sortIndicatorSection() const -{ - Q_D(const QHeaderView); - return d->sortIndicatorSection; -} - -/*! - Returns the order for the sort indicator. If no section has a sort - indicator the return value of this function is undefined. - - \sa setSortIndicator() sortIndicatorSection() -*/ - -Qt::SortOrder QHeaderView::sortIndicatorOrder() const -{ - Q_D(const QHeaderView); - return d->sortIndicatorOrder; -} - -/*! - \property QHeaderView::stretchLastSection - \brief whether the last visible section in the header takes up all the - available space - - The default value is false. - - \note The horizontal headers provided by QTreeView are configured with this - property set to true, ensuring that the view does not waste any of the - space assigned to it for its header. If this value is set to true, this - property will override the resize mode set on the last section in the - header. - - \sa setResizeMode() -*/ -bool QHeaderView::stretchLastSection() const -{ - Q_D(const QHeaderView); - return d->stretchLastSection; -} - -void QHeaderView::setStretchLastSection(bool stretch) -{ - Q_D(QHeaderView); - d->stretchLastSection = stretch; - if (d->state != QHeaderViewPrivate::NoState) - return; - if (stretch) - resizeSections(); - else if (count()) - resizeSection(count() - 1, d->defaultSectionSize); -} - -/*! - \since 4.2 - \property QHeaderView::cascadingSectionResizes - \brief whether interactive resizing will be cascaded to the following - sections once the section being resized by the user has reached its - minimum size - - This property only affects sections that have \l Interactive as their - resize mode. - - The default value is false. - - \sa setResizeMode() -*/ -bool QHeaderView::cascadingSectionResizes() const -{ - Q_D(const QHeaderView); - return d->cascadingResizing; -} - -void QHeaderView::setCascadingSectionResizes(bool enable) -{ - Q_D(QHeaderView); - d->cascadingResizing = enable; -} - -/*! - \property QHeaderView::defaultSectionSize - \brief the default size of the header sections before resizing. - - This property only affects sections that have \l Interactive or \l Fixed - as their resize mode. - - \sa setResizeMode() minimumSectionSize -*/ -int QHeaderView::defaultSectionSize() const -{ - Q_D(const QHeaderView); - return d->defaultSectionSize; -} - -void QHeaderView::setDefaultSectionSize(int size) -{ - Q_D(QHeaderView); - d->setDefaultSectionSize(size); -} - -/*! - \since 4.2 - \property QHeaderView::minimumSectionSize - \brief the minimum size of the header sections. - - The minimum section size is the smallest section size allowed. If the - minimum section size is set to -1, QHeaderView will use the maximum of - the \l{QApplication::globalStrut()}{global strut} or the - \l{fontMetrics()}{font metrics} size. - - This property is honored by all \l{ResizeMode}{resize modes}. - - \sa setResizeMode() defaultSectionSize -*/ -int QHeaderView::minimumSectionSize() const -{ - Q_D(const QHeaderView); - if (d->minimumSectionSize == -1) { - QSize strut = QApplication::globalStrut(); - int margin = style()->pixelMetric(QStyle::PM_HeaderMargin, 0, this); - if (d->orientation == Qt::Horizontal) - return qMax(strut.width(), (fontMetrics().maxWidth() + margin)); - return qMax(strut.height(), (fontMetrics().height() + margin)); - } - return d->minimumSectionSize; -} - -void QHeaderView::setMinimumSectionSize(int size) -{ - Q_D(QHeaderView); - d->minimumSectionSize = size; -} - -/*! - \since 4.1 - \property QHeaderView::defaultAlignment - \brief the default alignment of the text in each header section -*/ - -Qt::Alignment QHeaderView::defaultAlignment() const -{ - Q_D(const QHeaderView); - return d->defaultAlignment; -} - -void QHeaderView::setDefaultAlignment(Qt::Alignment alignment) -{ - Q_D(QHeaderView); - if (d->defaultAlignment == alignment) - return; - - d->defaultAlignment = alignment; - d->viewport->update(); -} - -/*! - \internal -*/ -void QHeaderView::doItemsLayout() -{ - initializeSections(); - QAbstractItemView::doItemsLayout(); -} - -/*! - Returns true if sections in the header has been moved; otherwise returns - false; - - \sa moveSection() -*/ -bool QHeaderView::sectionsMoved() const -{ - Q_D(const QHeaderView); - return !d->visualIndices.isEmpty(); -} - -/*! - \since 4.1 - - Returns true if sections in the header has been hidden; otherwise returns - false; - - \sa setSectionHidden() -*/ -bool QHeaderView::sectionsHidden() const -{ - Q_D(const QHeaderView); - return !d->hiddenSectionSize.isEmpty(); -} - -#ifndef QT_NO_DATASTREAM -/*! - \since 4.3 - - Saves the current state of this header view. - - To restore the saved state, pass the return value to restoreState(). - - \sa restoreState() -*/ -QByteArray QHeaderView::saveState() const -{ - Q_D(const QHeaderView); - QByteArray data; - QDataStream stream(&data, QIODevice::WriteOnly); - stream << QHeaderViewPrivate::VersionMarker; - stream << 0; // current version is 0 - d->write(stream); - return data; -} - -/*! - \since 4.3 - Restores the \a state of this header view. - This function returns \c true if the state was restored; otherwise returns - false. - - \sa saveState() -*/ -bool QHeaderView::restoreState(const QByteArray &state) -{ - Q_D(QHeaderView); - if (state.isEmpty()) - return false; - QByteArray data = state; - QDataStream stream(&data, QIODevice::ReadOnly); - int marker; - int ver; - stream >> marker; - stream >> ver; - if (stream.status() != QDataStream::Ok - || marker != QHeaderViewPrivate::VersionMarker - || ver != 0) // current version is 0 - return false; - - if (d->read(stream)) { - emit sortIndicatorChanged(d->sortIndicatorSection, d->sortIndicatorOrder ); - d->viewport->update(); - return true; - } - return false; -} -#endif // QT_NO_DATASTREAM - -/*! - \reimp -*/ -void QHeaderView::reset() -{ - QAbstractItemView::reset(); - // it would be correct to call clear, but some apps rely - // on the header keeping the sections, even after calling reset - //d->clear(); - initializeSections(); -} - -/*! - Updates the changed header sections with the given \a orientation, from - \a logicalFirst to \a logicalLast inclusive. -*/ -void QHeaderView::headerDataChanged(Qt::Orientation orientation, int logicalFirst, int logicalLast) -{ - Q_D(QHeaderView); - if (d->orientation != orientation) - return; - - if (logicalFirst < 0 || logicalLast < 0 || logicalFirst >= count() || logicalLast >= count()) - return; - - d->invalidateCachedSizeHint(); - - int firstVisualIndex = INT_MAX, lastVisualIndex = -1; - - for (int section = logicalFirst; section <= logicalLast; ++section) { - const int visual = visualIndex(section); - firstVisualIndex = qMin(firstVisualIndex, visual); - lastVisualIndex = qMax(lastVisualIndex, visual); - } - - d->executePostedResize(); - const int first = d->headerSectionPosition(firstVisualIndex), - last = d->headerSectionPosition(lastVisualIndex) - + d->headerSectionSize(lastVisualIndex); - - if (orientation == Qt::Horizontal) { - d->viewport->update(first, 0, last - first, d->viewport->height()); - } else { - d->viewport->update(0, first, d->viewport->width(), last - first); - } -} - -/*! - \internal - \since 4.2 - - Updates the section specified by the given \a logicalIndex. -*/ - -void QHeaderView::updateSection(int logicalIndex) -{ - Q_D(QHeaderView); - if (d->orientation == Qt::Horizontal) - d->viewport->update(QRect(sectionViewportPosition(logicalIndex), - 0, sectionSize(logicalIndex), d->viewport->height())); - else - d->viewport->update(QRect(0, sectionViewportPosition(logicalIndex), - d->viewport->width(), sectionSize(logicalIndex))); -} - -/*! - Resizes the sections according to their size hints. Normally, you do not - have to call this function. -*/ - -void QHeaderView::resizeSections() -{ - Q_D(QHeaderView); - if (d->hasAutoResizeSections()) - d->resizeSections(Interactive, false); // no global resize mode -} - -/*! - This slot is called when sections are inserted into the \a parent. - \a logicalFirst and \a logicalLast indices signify where the new sections - were inserted. - - If only one section is inserted, \a logicalFirst and \a logicalLast will - be the same. -*/ - -void QHeaderView::sectionsInserted(const QModelIndex &parent, - int logicalFirst, int logicalLast) -{ - Q_D(QHeaderView); - if (parent != d->root) - return; // we only handle changes in the top level - int oldCount = d->sectionCount; - - d->invalidateCachedSizeHint(); - - // add the new sections - int insertAt = 0; - for (int spanStart = 0; insertAt < d->sectionSpans.count() && spanStart < logicalFirst; ++insertAt) - spanStart += d->sectionSpans.at(insertAt).count; - - int insertCount = logicalLast - logicalFirst + 1; - d->sectionCount += insertCount; - - if (d->sectionSpans.isEmpty() || insertAt >= d->sectionSpans.count()) { - int insertLength = d->defaultSectionSize * insertCount; - d->length += insertLength; - QHeaderViewPrivate::SectionSpan span(insertLength, insertCount, d->globalResizeMode); - d->sectionSpans.append(span); - } else if ((d->sectionSpans.at(insertAt).sectionSize() == d->defaultSectionSize) - && d->sectionSpans.at(insertAt).resizeMode == d->globalResizeMode) { - // add the new sections to an existing span - int insertLength = d->sectionSpans.at(insertAt).sectionSize() * insertCount; - d->length += insertLength; - d->sectionSpans[insertAt].size += insertLength; - d->sectionSpans[insertAt].count += insertCount; - } else { - // separate them out into their own span - int insertLength = d->defaultSectionSize * insertCount; - d->length += insertLength; - QHeaderViewPrivate::SectionSpan span(insertLength, insertCount, d->globalResizeMode); - d->sectionSpans.insert(insertAt, span); - } - - // update sorting column - if (d->sortIndicatorSection >= logicalFirst) - d->sortIndicatorSection += insertCount; - - // update resize mode section counts - if (d->globalResizeMode == Stretch) - d->stretchSections = d->sectionCount; - else if (d->globalResizeMode == ResizeToContents) - d->contentsSections = d->sectionCount; - - // clear selection cache - d->sectionSelected.clear(); - - // update mapping - if (!d->visualIndices.isEmpty() && !d->logicalIndices.isEmpty()) { - Q_ASSERT(d->visualIndices.count() == d->logicalIndices.count()); - int mappingCount = d->visualIndices.count(); - for (int i = 0; i < mappingCount; ++i) { - if (d->visualIndices.at(i) >= logicalFirst) - d->visualIndices[i] += insertCount; - if (d->logicalIndices.at(i) >= logicalFirst) - d->logicalIndices[i] += insertCount; - } - for (int j = logicalFirst; j <= logicalLast; ++j) { - d->visualIndices.insert(j, j); - d->logicalIndices.insert(j, j); - } - } - - // insert sections into sectionsHidden - if (!d->sectionHidden.isEmpty()) { - QBitArray sectionHidden(d->sectionHidden); - sectionHidden.resize(sectionHidden.count() + insertCount); - sectionHidden.fill(false, logicalFirst, logicalLast + 1); - for (int j = logicalLast + 1; j < sectionHidden.count(); ++j) - //here we simply copy the old sectionHidden - sectionHidden.setBit(j, d->sectionHidden.testBit(j - insertCount)); - d->sectionHidden = sectionHidden; - } - - // insert sections into hiddenSectionSize - QHash<int, int> newHiddenSectionSize; // from logical index to section size - for (int i = 0; i < logicalFirst; ++i) - if (isSectionHidden(i)) - newHiddenSectionSize[i] = d->hiddenSectionSize[i]; - for (int j = logicalLast + 1; j < d->sectionCount; ++j) - if (isSectionHidden(j)) - newHiddenSectionSize[j] = d->hiddenSectionSize[j - insertCount]; - d->hiddenSectionSize = newHiddenSectionSize; - - d->doDelayedResizeSections(); - emit sectionCountChanged(oldCount, count()); - - // if the new sections were not updated by resizing, we need to update now - if (!d->hasAutoResizeSections()) - d->viewport->update(); -} - -/*! - This slot is called when sections are removed from the \a parent. - \a logicalFirst and \a logicalLast signify where the sections were removed. - - If only one section is removed, \a logicalFirst and \a logicalLast will - be the same. -*/ - -void QHeaderView::sectionsAboutToBeRemoved(const QModelIndex &parent, - int logicalFirst, int logicalLast) -{ - Q_UNUSED(parent); - Q_UNUSED(logicalFirst); - Q_UNUSED(logicalLast); -} - -void QHeaderViewPrivate::updateHiddenSections(int logicalFirst, int logicalLast) -{ - Q_Q(QHeaderView); - const int changeCount = logicalLast - logicalFirst + 1; - - // remove sections from hiddenSectionSize - QHash<int, int> newHiddenSectionSize; // from logical index to section size - for (int i = 0; i < logicalFirst; ++i) - if (q->isSectionHidden(i)) - newHiddenSectionSize[i] = hiddenSectionSize[i]; - for (int j = logicalLast + 1; j < sectionCount; ++j) - if (q->isSectionHidden(j)) - newHiddenSectionSize[j - changeCount] = hiddenSectionSize[j]; - hiddenSectionSize = newHiddenSectionSize; - - // remove sections from sectionsHidden - if (!sectionHidden.isEmpty()) { - const int newsize = qMin(sectionCount - changeCount, sectionHidden.size()); - QBitArray newSectionHidden(newsize); - for (int j = 0, k = 0; j < sectionHidden.size(); ++j) { - const int logical = logicalIndex(j); - if (logical < logicalFirst || logical > logicalLast) { - newSectionHidden[k++] = sectionHidden[j]; - } - } - sectionHidden = newSectionHidden; - } -} - -void QHeaderViewPrivate::_q_sectionsRemoved(const QModelIndex &parent, - int logicalFirst, int logicalLast) -{ - Q_Q(QHeaderView); - if (parent != root) - return; // we only handle changes in the top level - if (qMin(logicalFirst, logicalLast) < 0 - || qMax(logicalLast, logicalFirst) >= sectionCount) - return; - int oldCount = q->count(); - int changeCount = logicalLast - logicalFirst + 1; - - updateHiddenSections(logicalFirst, logicalLast); - - if (visualIndices.isEmpty() && logicalIndices.isEmpty()) { - //Q_ASSERT(headerSectionCount() == sectionCount); - removeSectionsFromSpans(logicalFirst, logicalLast); - } else { - for (int l = logicalLast; l >= logicalFirst; --l) { - int visual = visualIndices.at(l); - for (int v = 0; v < sectionCount; ++v) { - if (v >= logicalIndices.count()) - continue; // the section doesn't exist - if (v > visual) { - int logical = logicalIndices.at(v); - --(visualIndices[logical]); - } - if (logicalIndex(v) > l) // no need to move the positions before l - --(logicalIndices[v]); - } - logicalIndices.remove(visual); - visualIndices.remove(l); - //Q_ASSERT(headerSectionCount() == sectionCount); - removeSectionsFromSpans(visual, visual); - } - // ### handle sectionSelection, sectionHidden - } - sectionCount -= changeCount; - - // update sorting column - if (sortIndicatorSection >= logicalFirst) { - if (sortIndicatorSection <= logicalLast) - sortIndicatorSection = -1; - else - sortIndicatorSection -= changeCount; - } - - // if we only have the last section (the "end" position) left, the header is empty - if (sectionCount <= 0) - clear(); - invalidateCachedSizeHint(); - emit q->sectionCountChanged(oldCount, q->count()); - viewport->update(); -} - -void QHeaderViewPrivate::_q_layoutAboutToBeChanged() -{ - //if there is no row/column we can't have mapping for columns - //because no QModelIndex in the model would be valid - // ### this is far from being bullet-proof and we would need a real system to - // ### map columns or rows persistently - if ((orientation == Qt::Horizontal && model->rowCount(root) == 0) - || model->columnCount(root) == 0) - return; - - for (int i = 0; i < sectionHidden.count(); ++i) - if (sectionHidden.testBit(i)) // ### note that we are using column or row 0 - persistentHiddenSections.append(orientation == Qt::Horizontal - ? model->index(0, logicalIndex(i), root) - : model->index(logicalIndex(i), 0, root)); -} - -void QHeaderViewPrivate::_q_layoutChanged() -{ - Q_Q(QHeaderView); - viewport->update(); - if (persistentHiddenSections.isEmpty() || modelIsEmpty()) { - if (modelSectionCount() != sectionCount) - q->initializeSections(); - persistentHiddenSections.clear(); - return; - } - - QBitArray oldSectionHidden = sectionHidden; - bool sectionCountChanged = false; - - for (int i = 0; i < persistentHiddenSections.count(); ++i) { - QModelIndex index = persistentHiddenSections.at(i); - if (index.isValid()) { - const int logical = (orientation == Qt::Horizontal - ? index.column() - : index.row()); - q->setSectionHidden(logical, true); - oldSectionHidden.setBit(logical, false); - } else if (!sectionCountChanged && (modelSectionCount() != sectionCount)) { - sectionCountChanged = true; - break; - } - } - persistentHiddenSections.clear(); - - for (int i = 0; i < oldSectionHidden.count(); ++i) { - if (oldSectionHidden.testBit(i)) - q->setSectionHidden(i, false); - } - - // the number of sections changed; we need to reread the state of the model - if (sectionCountChanged) - q->initializeSections(); -} - -/*! - \internal -*/ - -void QHeaderView::initializeSections() -{ - Q_D(QHeaderView); - const int oldCount = d->sectionCount; - const int newCount = d->modelSectionCount(); - if (newCount <= 0) { - d->clear(); - emit sectionCountChanged(oldCount, 0); - } else if (newCount != oldCount) { - const int min = qBound(0, oldCount, newCount - 1); - initializeSections(min, newCount - 1); - if (stretchLastSection()) // we've already gotten the size hint - d->lastSectionSize = sectionSize(logicalIndex(d->sectionCount - 1)); - - //make sure we update the hidden sections - if (newCount < oldCount) - d->updateHiddenSections(0, newCount-1); - } -} - -/*! - \internal -*/ - -void QHeaderView::initializeSections(int start, int end) -{ - Q_D(QHeaderView); - - Q_ASSERT(start >= 0); - Q_ASSERT(end >= 0); - - d->invalidateCachedSizeHint(); - - if (end + 1 < d->sectionCount) { - int newCount = end + 1; - d->removeSectionsFromSpans(newCount, d->sectionCount); - if (!d->hiddenSectionSize.isEmpty()) { - if (d->sectionCount - newCount > d->hiddenSectionSize.count()) { - for (int i = end + 1; i < d->sectionCount; ++i) - d->hiddenSectionSize.remove(i); - } else { - QHash<int, int>::iterator it = d->hiddenSectionSize.begin(); - while (it != d->hiddenSectionSize.end()) { - if (it.key() > end) - it = d->hiddenSectionSize.erase(it); - else - ++it; - } - } - } - } - - int oldCount = d->sectionCount; - d->sectionCount = end + 1; - - if (!d->logicalIndices.isEmpty()) { - if (oldCount <= d->sectionCount) { - d->logicalIndices.resize(d->sectionCount); - d->visualIndices.resize(d->sectionCount); - for (int i = oldCount; i < d->sectionCount; ++i) { - d->logicalIndices[i] = i; - d->visualIndices[i] = i; - } - } else { - int j = 0; - for (int i = 0; i < oldCount; ++i) { - int v = d->logicalIndices.at(i); - if (v < d->sectionCount) { - d->logicalIndices[j] = v; - d->visualIndices[v] = j; - j++; - } - } - d->logicalIndices.resize(d->sectionCount); - d->visualIndices.resize(d->sectionCount); - } - } - - if (d->globalResizeMode == Stretch) - d->stretchSections = d->sectionCount; - else if (d->globalResizeMode == ResizeToContents) - d->contentsSections = d->sectionCount; - if (!d->sectionHidden.isEmpty()) - d->sectionHidden.resize(d->sectionCount); - - if (d->sectionCount > oldCount) - d->createSectionSpan(start, end, (end - start + 1) * d->defaultSectionSize, d->globalResizeMode); - //Q_ASSERT(d->headerLength() == d->length); - - if (d->sectionCount != oldCount) - emit sectionCountChanged(oldCount, d->sectionCount); - d->viewport->update(); -} - -/*! - \reimp -*/ - -void QHeaderView::currentChanged(const QModelIndex ¤t, const QModelIndex &old) -{ - Q_D(QHeaderView); - - if (d->orientation == Qt::Horizontal && current.column() != old.column()) { - if (old.isValid() && old.parent() == d->root) - d->viewport->update(QRect(sectionViewportPosition(old.column()), 0, - sectionSize(old.column()), d->viewport->height())); - if (current.isValid() && current.parent() == d->root) - d->viewport->update(QRect(sectionViewportPosition(current.column()), 0, - sectionSize(current.column()), d->viewport->height())); - } else if (d->orientation == Qt::Vertical && current.row() != old.row()) { - if (old.isValid() && old.parent() == d->root) - d->viewport->update(QRect(0, sectionViewportPosition(old.row()), - d->viewport->width(), sectionSize(old.row()))); - if (current.isValid() && current.parent() == d->root) - d->viewport->update(QRect(0, sectionViewportPosition(current.row()), - d->viewport->width(), sectionSize(current.row()))); - } -} - - -/*! - \reimp -*/ - -bool QHeaderView::event(QEvent *e) -{ - Q_D(QHeaderView); - switch (e->type()) { - case QEvent::HoverEnter: { - QHoverEvent *he = static_cast<QHoverEvent*>(e); - d->hover = logicalIndexAt(he->pos()); - if (d->hover != -1) - updateSection(d->hover); - break; } - case QEvent::Leave: - case QEvent::HoverLeave: { - if (d->hover != -1) - updateSection(d->hover); - d->hover = -1; - break; } - case QEvent::HoverMove: { - QHoverEvent *he = static_cast<QHoverEvent*>(e); - int oldHover = d->hover; - d->hover = logicalIndexAt(he->pos()); - if (d->hover != oldHover) { - if (oldHover != -1) - updateSection(oldHover); - if (d->hover != -1) - updateSection(d->hover); - } - break; } - case QEvent::Timer: { - QTimerEvent *te = static_cast<QTimerEvent*>(e); - if (te->timerId() == d->delayedResize.timerId()) { - d->delayedResize.stop(); - resizeSections(); - } - break; } - default: - break; - } - return QAbstractItemView::event(e); -} - -/*! - \reimp -*/ - -void QHeaderView::paintEvent(QPaintEvent *e) -{ - Q_D(QHeaderView); - - if (count() == 0) - return; - - QPainter painter(d->viewport); - const QPoint offset = d->scrollDelayOffset; - QRect translatedEventRect = e->rect(); - translatedEventRect.translate(offset); - - int start = -1; - int end = -1; - if (d->orientation == Qt::Horizontal) { - start = visualIndexAt(translatedEventRect.left()); - end = visualIndexAt(translatedEventRect.right()); - } else { - start = visualIndexAt(translatedEventRect.top()); - end = visualIndexAt(translatedEventRect.bottom()); - } - - if (d->reverse()) { - start = (start == -1 ? count() - 1 : start); - end = (end == -1 ? 0 : end); - } else { - start = (start == -1 ? 0 : start); - end = (end == -1 ? count() - 1 : end); - } - - int tmp = start; - start = qMin(start, end); - end = qMax(tmp, end); - - d->prepareSectionSelected(); // clear and resize the bit array - - QRect currentSectionRect; - int logical; - const int width = d->viewport->width(); - const int height = d->viewport->height(); - for (int i = start; i <= end; ++i) { - if (d->isVisualIndexHidden(i)) - continue; - painter.save(); - logical = logicalIndex(i); - if (d->orientation == Qt::Horizontal) { - currentSectionRect.setRect(sectionViewportPosition(logical), 0, sectionSize(logical), height); - } else { - currentSectionRect.setRect(0, sectionViewportPosition(logical), width, sectionSize(logical)); - } - currentSectionRect.translate(offset); - - QVariant variant = d->model->headerData(logical, d->orientation, - Qt::FontRole); - if (variant.isValid() && variant.canConvert<QFont>()) { - QFont sectionFont = qvariant_cast<QFont>(variant); - painter.setFont(sectionFont); - } - paintSection(&painter, currentSectionRect, logical); - painter.restore(); - } - - QStyleOption opt; - opt.init(this); - // Paint the area beyond where there are indexes - if (d->reverse()) { - opt.state |= QStyle::State_Horizontal; - if (currentSectionRect.left() > translatedEventRect.left()) { - opt.rect = QRect(translatedEventRect.left(), 0, - currentSectionRect.left() - translatedEventRect.left(), height); - style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter, this); - } - } else if (currentSectionRect.right() < translatedEventRect.right()) { - // paint to the right - opt.state |= QStyle::State_Horizontal; - opt.rect = QRect(currentSectionRect.right() + 1, 0, - translatedEventRect.right() - currentSectionRect.right(), height); - style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter, this); - } else if (currentSectionRect.bottom() < translatedEventRect.bottom()) { - // paint the bottom section - opt.state &= ~QStyle::State_Horizontal; - opt.rect = QRect(0, currentSectionRect.bottom() + 1, - width, height - currentSectionRect.bottom() - 1); - style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter, this); - } - -#if 0 - // ### visualize section spans - for (int a = 0, i = 0; i < d->sectionSpans.count(); ++i) { - QColor color((i & 4 ? 255 : 0), (i & 2 ? 255 : 0), (i & 1 ? 255 : 0)); - if (d->orientation == Qt::Horizontal) - painter.fillRect(a - d->offset, 0, d->sectionSpans.at(i).size, 4, color); - else - painter.fillRect(0, a - d->offset, 4, d->sectionSpans.at(i).size, color); - a += d->sectionSpans.at(i).size; - } - -#endif -} - -/*! - \reimp -*/ - -void QHeaderView::mousePressEvent(QMouseEvent *e) -{ - Q_D(QHeaderView); - if (d->state != QHeaderViewPrivate::NoState || e->button() != Qt::LeftButton) - return; - int pos = d->orientation == Qt::Horizontal ? e->x() : e->y(); - int handle = d->sectionHandleAt(pos); - d->originalSize = -1; // clear the stored original size - if (handle == -1) { - d->pressed = logicalIndexAt(pos); - if (d->clickableSections) - emit sectionPressed(d->pressed); - if (d->movableSections) { - d->section = d->target = d->pressed; - if (d->section == -1) - return; - d->state = QHeaderViewPrivate::MoveSection; - d->setupSectionIndicator(d->section, pos); - } else if (d->clickableSections && d->pressed != -1) { - updateSection(d->pressed); - d->state = QHeaderViewPrivate::SelectSections; - } - } else if (resizeMode(handle) == Interactive) { - d->originalSize = sectionSize(handle); - d->state = QHeaderViewPrivate::ResizeSection; - d->section = handle; - } - - d->firstPos = pos; - d->lastPos = pos; - - d->clearCascadingSections(); -} - -/*! - \reimp -*/ - -void QHeaderView::mouseMoveEvent(QMouseEvent *e) -{ - Q_D(QHeaderView); - int pos = d->orientation == Qt::Horizontal ? e->x() : e->y(); - if (pos < 0) - return; - if (e->buttons() == Qt::NoButton) { - d->state = QHeaderViewPrivate::NoState; - d->pressed = -1; - } - switch (d->state) { - case QHeaderViewPrivate::ResizeSection: { - Q_ASSERT(d->originalSize != -1); - if (d->cascadingResizing) { - int delta = d->reverse() ? d->lastPos - pos : pos - d->lastPos; - int visual = visualIndex(d->section); - d->cascadingResize(visual, d->headerSectionSize(visual) + delta); - } else { - int delta = d->reverse() ? d->firstPos - pos : pos - d->firstPos; - resizeSection(d->section, qMax(d->originalSize + delta, minimumSectionSize())); - } - d->lastPos = pos; - return; - } - case QHeaderViewPrivate::MoveSection: { - if (qAbs(pos - d->firstPos) >= QApplication::startDragDistance() - || !d->sectionIndicator->isHidden()) { - int visual = visualIndexAt(pos); - if (visual == -1) - return; - int posThreshold = d->headerSectionPosition(visual) + d->headerSectionSize(visual) / 2; - int moving = visualIndex(d->section); - if (visual < moving) { - if (pos < posThreshold) - d->target = d->logicalIndex(visual); - else - d->target = d->logicalIndex(visual + 1); - } else if (visual > moving) { - if (pos > posThreshold) - d->target = d->logicalIndex(visual); - else - d->target = d->logicalIndex(visual - 1); - } else { - d->target = d->section; - } - d->updateSectionIndicator(d->section, pos); - } - return; - } - case QHeaderViewPrivate::SelectSections: { - int logical = logicalIndexAt(pos); - if (logical == d->pressed) - return; // nothing to do - else if (d->pressed != -1) - updateSection(d->pressed); - d->pressed = logical; - if (d->clickableSections && logical != -1) { - emit sectionEntered(d->pressed); - updateSection(d->pressed); - } - return; - } - case QHeaderViewPrivate::NoState: { -#ifndef QT_NO_CURSOR - int handle = d->sectionHandleAt(pos); - bool hasCursor = testAttribute(Qt::WA_SetCursor); - if (handle != -1 && (resizeMode(handle) == Interactive)) { - if (!hasCursor) - setCursor(d->orientation == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor); - } else if (hasCursor) { - unsetCursor(); - } -#endif - return; - } - default: - break; - } -} - -/*! - \reimp -*/ - -void QHeaderView::mouseReleaseEvent(QMouseEvent *e) -{ - Q_D(QHeaderView); - int pos = d->orientation == Qt::Horizontal ? e->x() : e->y(); - switch (d->state) { - case QHeaderViewPrivate::MoveSection: - if (!d->sectionIndicator->isHidden()) { // moving - int from = visualIndex(d->section); - Q_ASSERT(from != -1); - int to = visualIndex(d->target); - Q_ASSERT(to != -1); - moveSection(from, to); - d->section = d->target = -1; - d->updateSectionIndicator(d->section, pos); - break; - } // not moving - case QHeaderViewPrivate::SelectSections: - if (!d->clickableSections) { - int section = logicalIndexAt(pos); - updateSection(section); - } - // fall through - case QHeaderViewPrivate::NoState: - if (d->clickableSections) { - int section = logicalIndexAt(pos); - if (section != -1 && section == d->pressed) { - d->flipSortIndicator(section); - emit sectionClicked(section); - } - if (d->pressed != -1) - updateSection(d->pressed); - } - break; - case QHeaderViewPrivate::ResizeSection: - d->originalSize = -1; - d->clearCascadingSections(); - break; - default: - break; - } - d->state = QHeaderViewPrivate::NoState; - d->pressed = -1; -} - -/*! - \reimp -*/ - -void QHeaderView::mouseDoubleClickEvent(QMouseEvent *e) -{ - Q_D(QHeaderView); - int pos = d->orientation == Qt::Horizontal ? e->x() : e->y(); - int handle = d->sectionHandleAt(pos); - if (handle > -1 && resizeMode(handle) == Interactive) { - emit sectionHandleDoubleClicked(handle); -#ifndef QT_NO_CURSOR - Qt::CursorShape splitCursor = (d->orientation == Qt::Horizontal) - ? Qt::SplitHCursor : Qt::SplitVCursor; - if (cursor().shape() == splitCursor) { - // signal handlers may have changed the section size - handle = d->sectionHandleAt(pos); - if (!(handle > -1 && resizeMode(handle) == Interactive)) - setCursor(Qt::ArrowCursor); - } -#endif - } else { - emit sectionDoubleClicked(logicalIndexAt(e->pos())); - } -} - -/*! - \reimp -*/ - -bool QHeaderView::viewportEvent(QEvent *e) -{ - Q_D(QHeaderView); - switch (e->type()) { -#ifndef QT_NO_TOOLTIP - case QEvent::ToolTip: { - QHelpEvent *he = static_cast<QHelpEvent*>(e); - int logical = logicalIndexAt(he->pos()); - if (logical != -1) { - QVariant variant = d->model->headerData(logical, d->orientation, Qt::ToolTipRole); - if (variant.isValid()) { - QToolTip::showText(he->globalPos(), variant.toString(), this); - return true; - } - } - break; } -#endif -#ifndef QT_NO_WHATSTHIS - case QEvent::QueryWhatsThis: { - QHelpEvent *he = static_cast<QHelpEvent*>(e); - int logical = logicalIndexAt(he->pos()); - if (logical != -1 - && d->model->headerData(logical, d->orientation, Qt::WhatsThisRole).isValid()) - return true; - break; } - case QEvent::WhatsThis: { - QHelpEvent *he = static_cast<QHelpEvent*>(e); - int logical = logicalIndexAt(he->pos()); - if (logical != -1) { - QVariant whatsthis = d->model->headerData(logical, d->orientation, - Qt::WhatsThisRole); - if (whatsthis.isValid()) { - QWhatsThis::showText(he->globalPos(), whatsthis.toString(), this); - return true; - } - } - break; } -#endif // QT_NO_WHATSTHIS -#ifndef QT_NO_STATUSTIP - case QEvent::StatusTip: { - QHelpEvent *he = static_cast<QHelpEvent*>(e); - int logical = logicalIndexAt(he->pos()); - if (logical != -1) { - QString statustip = d->model->headerData(logical, d->orientation, - Qt::StatusTipRole).toString(); - if (!statustip.isEmpty()) - setStatusTip(statustip); - } - return true; } -#endif // QT_NO_STATUSTIP - case QEvent::Hide: - case QEvent::Show: - case QEvent::FontChange: - case QEvent::StyleChange: - d->invalidateCachedSizeHint(); - resizeSections(); - emit geometriesChanged(); - break; - case QEvent::ContextMenu: { - d->state = QHeaderViewPrivate::NoState; - d->pressed = d->section = d->target = -1; - d->updateSectionIndicator(d->section, -1); - break; } - case QEvent::Wheel: { - QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea *>(parentWidget()); - if (asa) - return QApplication::sendEvent(asa->viewport(), e); - break; } - default: - break; - } - return QAbstractItemView::viewportEvent(e); -} - -/*! - Paints the section specified by the given \a logicalIndex, using the given - \a painter and \a rect. - - Normally, you do not have to call this function. -*/ - -void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const -{ - Q_D(const QHeaderView); - if (!rect.isValid()) - return; - // get the state of the section - QStyleOptionHeader opt; - initStyleOption(&opt); - QStyle::State state = QStyle::State_None; - if (isEnabled()) - state |= QStyle::State_Enabled; - if (window()->isActiveWindow()) - state |= QStyle::State_Active; - if (d->clickableSections) { - if (logicalIndex == d->hover) - state |= QStyle::State_MouseOver; - if (logicalIndex == d->pressed) - state |= QStyle::State_Sunken; - else if (d->highlightSelected) { - if (d->sectionIntersectsSelection(logicalIndex)) - state |= QStyle::State_On; - if (d->isSectionSelected(logicalIndex)) - state |= QStyle::State_Sunken; - } - - } - if (isSortIndicatorShown() && sortIndicatorSection() == logicalIndex) - opt.sortIndicator = (sortIndicatorOrder() == Qt::AscendingOrder) - ? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp; - - // setup the style options structure - QVariant textAlignment = d->model->headerData(logicalIndex, d->orientation, - Qt::TextAlignmentRole); - opt.rect = rect; - opt.section = logicalIndex; - opt.state |= state; - opt.textAlignment = Qt::Alignment(textAlignment.isValid() - ? Qt::Alignment(textAlignment.toInt()) - : d->defaultAlignment); - - opt.iconAlignment = Qt::AlignVCenter; - opt.text = d->model->headerData(logicalIndex, d->orientation, - Qt::DisplayRole).toString(); - if (d->textElideMode != Qt::ElideNone) - opt.text = opt.fontMetrics.elidedText(opt.text, d->textElideMode , rect.width() - 4); - - QVariant variant = d->model->headerData(logicalIndex, d->orientation, - Qt::DecorationRole); - opt.icon = qvariant_cast<QIcon>(variant); - if (opt.icon.isNull()) - opt.icon = qvariant_cast<QPixmap>(variant); - QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation, - Qt::ForegroundRole); - if (foregroundBrush.canConvert<QBrush>()) - opt.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(foregroundBrush)); - - QPointF oldBO = painter->brushOrigin(); - QVariant backgroundBrush = d->model->headerData(logicalIndex, d->orientation, - Qt::BackgroundRole); - if (backgroundBrush.canConvert<QBrush>()) { - opt.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(backgroundBrush)); - opt.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(backgroundBrush)); - painter->setBrushOrigin(opt.rect.topLeft()); - } - - // the section position - int visual = visualIndex(logicalIndex); - Q_ASSERT(visual != -1); - if (count() == 1) - opt.position = QStyleOptionHeader::OnlyOneSection; - else if (visual == 0) - opt.position = QStyleOptionHeader::Beginning; - else if (visual == count() - 1) - opt.position = QStyleOptionHeader::End; - else - opt.position = QStyleOptionHeader::Middle; - opt.orientation = d->orientation; - // the selected position - bool previousSelected = d->isSectionSelected(this->logicalIndex(visual - 1)); - bool nextSelected = d->isSectionSelected(this->logicalIndex(visual + 1)); - if (previousSelected && nextSelected) - opt.selectedPosition = QStyleOptionHeader::NextAndPreviousAreSelected; - else if (previousSelected) - opt.selectedPosition = QStyleOptionHeader::PreviousIsSelected; - else if (nextSelected) - opt.selectedPosition = QStyleOptionHeader::NextIsSelected; - else - opt.selectedPosition = QStyleOptionHeader::NotAdjacent; - // draw the section - style()->drawControl(QStyle::CE_Header, &opt, painter, this); - - painter->setBrushOrigin(oldBO); -} - -/*! - Returns the size of the contents of the section specified by the given - \a logicalIndex. - - \sa defaultSectionSize() -*/ - -QSize QHeaderView::sectionSizeFromContents(int logicalIndex) const -{ - Q_D(const QHeaderView); - Q_ASSERT(logicalIndex >= 0); - - ensurePolished(); - - // use SizeHintRole - QVariant variant = d->model->headerData(logicalIndex, d->orientation, Qt::SizeHintRole); - if (variant.isValid()) - return qvariant_cast<QSize>(variant); - - // otherwise use the contents - QStyleOptionHeader opt; - initStyleOption(&opt); - opt.section = logicalIndex; - QVariant var = d->model->headerData(logicalIndex, d->orientation, - Qt::FontRole); - QFont fnt; - if (var.isValid() && var.canConvert<QFont>()) - fnt = qvariant_cast<QFont>(var); - else - fnt = font(); - fnt.setBold(true); - opt.fontMetrics = QFontMetrics(fnt); - opt.text = d->model->headerData(logicalIndex, d->orientation, - Qt::DisplayRole).toString(); - variant = d->model->headerData(logicalIndex, d->orientation, Qt::DecorationRole); - opt.icon = qvariant_cast<QIcon>(variant); - if (opt.icon.isNull()) - opt.icon = qvariant_cast<QPixmap>(variant); - QSize size = style()->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize(), this); - if (isSortIndicatorShown()) { - int margin = style()->pixelMetric(QStyle::PM_HeaderMargin, &opt, this); - if (d->orientation == Qt::Horizontal) - size.rwidth() += size.height() + margin; - else - size.rheight() += size.width() + margin; - } - return size; -} - -/*! - Returns the horizontal offset of the header. This is 0 for vertical - headers. - - \sa offset() -*/ - -int QHeaderView::horizontalOffset() const -{ - Q_D(const QHeaderView); - if (d->orientation == Qt::Horizontal) - return d->offset; - return 0; -} - -/*! - Returns the vertical offset of the header. This is 0 for horizontal - headers. - - \sa offset() -*/ - -int QHeaderView::verticalOffset() const -{ - Q_D(const QHeaderView); - if (d->orientation == Qt::Vertical) - return d->offset; - return 0; -} - -/*! - \reimp - \internal -*/ - -void QHeaderView::updateGeometries() -{ - Q_D(QHeaderView); - d->layoutChildren(); - if (d->hasAutoResizeSections()) - d->doDelayedResizeSections(); -} - -/*! - \reimp - \internal -*/ - -void QHeaderView::scrollContentsBy(int dx, int dy) -{ - Q_D(QHeaderView); - d->scrollDirtyRegion(dx, dy); -} - -/*! - \reimp - \internal -*/ -void QHeaderView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - Q_D(QHeaderView); - d->invalidateCachedSizeHint(); - if (d->hasAutoResizeSections()) { - bool resizeRequired = d->globalResizeMode == ResizeToContents; - int first = orientation() == Qt::Horizontal ? topLeft.column() : topLeft.row(); - int last = orientation() == Qt::Horizontal ? bottomRight.column() : bottomRight.row(); - for (int i = first; i <= last && !resizeRequired; ++i) - resizeRequired = (resizeMode(i) == ResizeToContents); - if (resizeRequired) - d->doDelayedResizeSections(); - } -} - -/*! - \reimp - \internal - - Empty implementation because the header doesn't show QModelIndex items. -*/ -void QHeaderView::rowsInserted(const QModelIndex &, int, int) -{ - // do nothing -} - -/*! - \reimp - \internal - - Empty implementation because the header doesn't show QModelIndex items. -*/ - -QRect QHeaderView::visualRect(const QModelIndex &) const -{ - return QRect(); -} - -/*! - \reimp - \internal - - Empty implementation because the header doesn't show QModelIndex items. -*/ - -void QHeaderView::scrollTo(const QModelIndex &, ScrollHint) -{ - // do nothing - the header only displays sections -} - -/*! - \reimp - \internal - - Empty implementation because the header doesn't show QModelIndex items. -*/ - -QModelIndex QHeaderView::indexAt(const QPoint &) const -{ - return QModelIndex(); -} - -/*! - \reimp - \internal - - Empty implementation because the header doesn't show QModelIndex items. -*/ - -bool QHeaderView::isIndexHidden(const QModelIndex &) const -{ - return true; // the header view has no items, just sections -} - -/*! - \reimp - \internal - - Empty implementation because the header doesn't show QModelIndex items. -*/ - -QModelIndex QHeaderView::moveCursor(CursorAction, Qt::KeyboardModifiers) -{ - return QModelIndex(); -} - -/*! - \reimp - - Selects the items in the given \a rect according to the specified - \a flags. - - The base class implementation does nothing. -*/ - -void QHeaderView::setSelection(const QRect&, QItemSelectionModel::SelectionFlags) -{ - // do nothing -} - -/*! - \internal -*/ - -QRegion QHeaderView::visualRegionForSelection(const QItemSelection &selection) const -{ - Q_D(const QHeaderView); - const int max = d->modelSectionCount(); - if (d->orientation == Qt::Horizontal) { - int left = max; - int right = 0; - int rangeLeft, rangeRight; - - for (int i = 0; i < selection.count(); ++i) { - QItemSelectionRange r = selection.at(i); - if (r.parent().isValid() || !r.isValid()) - continue; // we only know about toplevel items and we don't want invalid ranges - // FIXME an item inside the range may be the leftmost or rightmost - rangeLeft = visualIndex(r.left()); - if (rangeLeft == -1) // in some cases users may change the selections - continue; // before we have a chance to do the layout - rangeRight = visualIndex(r.right()); - if (rangeRight == -1) // in some cases users may change the selections - continue; // before we have a chance to do the layout - if (rangeLeft < left) - left = rangeLeft; - if (rangeRight > right) - right = rangeRight; - } - - int logicalLeft = logicalIndex(left); - int logicalRight = logicalIndex(right); - - if (logicalLeft < 0 || logicalLeft >= count() || - logicalRight < 0 || logicalRight >= count()) - return QRegion(); - - int leftPos = sectionViewportPosition(logicalLeft); - int rightPos = sectionViewportPosition(logicalRight); - rightPos += sectionSize(logicalRight); - return QRect(leftPos, 0, rightPos - leftPos, height()); - } - // orientation() == Qt::Vertical - int top = max; - int bottom = 0; - int rangeTop, rangeBottom; - - for (int i = 0; i < selection.count(); ++i) { - QItemSelectionRange r = selection.at(i); - if (r.parent().isValid() || !r.isValid()) - continue; // we only know about toplevel items - // FIXME an item inside the range may be the leftmost or rightmost - rangeTop = visualIndex(r.top()); - if (rangeTop == -1) // in some cases users may change the selections - continue; // before we have a chance to do the layout - rangeBottom = visualIndex(r.bottom()); - if (rangeBottom == -1) // in some cases users may change the selections - continue; // before we have a chance to do the layout - if (rangeTop < top) - top = rangeTop; - if (rangeBottom > bottom) - bottom = rangeBottom; - } - - int logicalTop = logicalIndex(top); - int logicalBottom = logicalIndex(bottom); - - if (logicalTop == -1 || logicalBottom == -1) - return QRect(); - - int topPos = sectionViewportPosition(logicalTop); - int bottomPos = sectionViewportPosition(logicalBottom) + sectionSize(logicalBottom); - - return QRect(0, topPos, width(), bottomPos - topPos); -} - - -// private implementation - -int QHeaderViewPrivate::sectionHandleAt(int position) -{ - Q_Q(QHeaderView); - int visual = q->visualIndexAt(position); - if (visual == -1) - return -1; - int log = logicalIndex(visual); - int pos = q->sectionViewportPosition(log); - int grip = q->style()->pixelMetric(QStyle::PM_HeaderGripMargin, 0, q); - - bool atLeft = position < pos + grip; - bool atRight = (position > pos + q->sectionSize(log) - grip); - if (reverse()) - qSwap(atLeft, atRight); - - if (atLeft) { - //grip at the beginning of the section - while(visual > -1) { - int logical = q->logicalIndex(--visual); - if (!q->isSectionHidden(logical)) - return logical; - } - } else if (atRight) { - //grip at the end of the section - return log; - } - return -1; -} - -void QHeaderViewPrivate::setupSectionIndicator(int section, int position) -{ - Q_Q(QHeaderView); - if (!sectionIndicator) { - sectionIndicator = new QLabel(viewport); - } - - int w, h; - int p = q->sectionViewportPosition(section); - if (orientation == Qt::Horizontal) { - w = q->sectionSize(section); - h = viewport->height(); - } else { - w = viewport->width(); - h = q->sectionSize(section); - } - sectionIndicator->resize(w, h); - - QPixmap pm(w, h); - pm.fill(QColor(0, 0, 0, 45)); - QRect rect(0, 0, w, h); - - QPainter painter(&pm); - painter.setOpacity(0.75); - q->paintSection(&painter, rect, section); - painter.end(); - - sectionIndicator->setPixmap(pm); - sectionIndicatorOffset = position - qMax(p, 0); -} - -void QHeaderViewPrivate::updateSectionIndicator(int section, int position) -{ - if (!sectionIndicator) - return; - - if (section == -1 || target == -1) { - sectionIndicator->hide(); - return; - } - - if (orientation == Qt::Horizontal) - sectionIndicator->move(position - sectionIndicatorOffset, 0); - else - sectionIndicator->move(0, position - sectionIndicatorOffset); - - sectionIndicator->show(); -} - -/*! - Initialize \a option with the values from this QHeaderView. This method is - useful for subclasses when they need a QStyleOptionHeader, but do not want - to fill in all the information themselves. - - \sa QStyleOption::initFrom() -*/ -void QHeaderView::initStyleOption(QStyleOptionHeader *option) const -{ - Q_D(const QHeaderView); - option->initFrom(this); - option->state = QStyle::State_None | QStyle::State_Raised; - option->orientation = d->orientation; - if (d->orientation == Qt::Horizontal) - option->state |= QStyle::State_Horizontal; - if (isEnabled()) - option->state |= QStyle::State_Enabled; - option->section = 0; -} - -bool QHeaderViewPrivate::isSectionSelected(int section) const -{ - int i = section * 2; - if (i < 0 || i >= sectionSelected.count()) - return false; - if (sectionSelected.testBit(i)) // if the value was cached - return sectionSelected.testBit(i + 1); - bool s = false; - if (orientation == Qt::Horizontal) - s = isColumnSelected(section); - else - s = isRowSelected(section); - sectionSelected.setBit(i + 1, s); // selection state - sectionSelected.setBit(i, true); // cache state - return s; -} - -/*! - \internal - Returns the last visible (ie. not hidden) visual index -*/ -int QHeaderViewPrivate::lastVisibleVisualIndex() const -{ - Q_Q(const QHeaderView); - for (int visual = q->count()-1; visual >= 0; --visual) { - if (!q->isSectionHidden(q->logicalIndex(visual))) - return visual; - } - - //default value if no section is actually visible - return -1; -} - -/*! - \internal - Go through and resize all of the sections applying stretchLastSection, - manualy stretches, sizes, and useGlobalMode. - - The different resize modes are: - Interactive - the user decides the size - Stretch - take up whatever space is left - Fixed - the size is set programmatically outside the header - ResizeToContentes - the size is set based on the contents of the row or column in the parent view - - The resize mode will not affect the last section if stretchLastSection is true. -*/ -void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool useGlobalMode) -{ - Q_Q(QHeaderView); - //stop the timer in case it is delayed - delayedResize.stop(); - - executePostedLayout(); - if (sectionCount == 0) - return; - - if (resizeRecursionBlock) - return; - resizeRecursionBlock = true; - - invalidateCachedSizeHint(); - - const int lastVisibleSection = lastVisibleVisualIndex(); - - // find stretchLastSection if we have it - int stretchSection = -1; - if (stretchLastSection && !useGlobalMode) - stretchSection = lastVisibleVisualIndex(); - - // count up the number of strected sections and how much space left for them - int lengthToStrech = (orientation == Qt::Horizontal ? viewport->width() : viewport->height()); - int numberOfStretchedSections = 0; - QList<int> section_sizes; - for (int i = 0; i < sectionCount; ++i) { - if (isVisualIndexHidden(i)) - continue; - - QHeaderView::ResizeMode resizeMode; - if (useGlobalMode && (i != stretchSection)) - resizeMode = globalMode; - else - resizeMode = (i == stretchSection ? QHeaderView::Stretch : headerSectionResizeMode(i)); - - if (resizeMode == QHeaderView::Stretch) { - ++numberOfStretchedSections; - section_sizes.append(headerSectionSize(i)); - continue; - } - - // because it isn't stretch, determine its width and remove that from lengthToStrech - int sectionSize = 0; - if (resizeMode == QHeaderView::Interactive || resizeMode == QHeaderView::Fixed) { - sectionSize = headerSectionSize(i); - } else { // resizeMode == QHeaderView::ResizeToContents - int logicalIndex = q->logicalIndex(i); - sectionSize = qMax(viewSectionSizeHint(logicalIndex), - q->sectionSizeHint(logicalIndex)); - } - section_sizes.append(sectionSize); - lengthToStrech -= sectionSize; - } - - // calculate the new length for all of the stretched sections - int stretchSectionLength = -1; - int pixelReminder = 0; - if (numberOfStretchedSections > 0 && lengthToStrech > 0) { // we have room to stretch in - int hintLengthForEveryStretchedSection = lengthToStrech / numberOfStretchedSections; - stretchSectionLength = qMax(hintLengthForEveryStretchedSection, q->minimumSectionSize()); - pixelReminder = lengthToStrech % numberOfStretchedSections; - } - - int spanStartSection = 0; - int previousSectionLength = 0; - - QHeaderView::ResizeMode previousSectionResizeMode = QHeaderView::Interactive; - - // resize each section along the total length - for (int i = 0; i < sectionCount; ++i) { - int oldSectionLength = headerSectionSize(i); - int newSectionLength = -1; - QHeaderView::ResizeMode newSectionResizeMode = headerSectionResizeMode(i); - - if (isVisualIndexHidden(i)) { - newSectionLength = 0; - } else { - QHeaderView::ResizeMode resizeMode; - if (useGlobalMode) - resizeMode = globalMode; - else - resizeMode = (i == stretchSection - ? QHeaderView::Stretch - : newSectionResizeMode); - if (resizeMode == QHeaderView::Stretch && stretchSectionLength != -1) { - if (i == lastVisibleSection) - newSectionLength = qMax(stretchSectionLength, lastSectionSize); - else - newSectionLength = stretchSectionLength; - if (pixelReminder > 0) { - newSectionLength += 1; - --pixelReminder; - } - section_sizes.removeFirst(); - } else { - newSectionLength = section_sizes.front(); - section_sizes.removeFirst(); - } - } - - //Q_ASSERT(newSectionLength > 0); - if ((previousSectionResizeMode != newSectionResizeMode - || previousSectionLength != newSectionLength) && i > 0) { - int spanLength = (i - spanStartSection) * previousSectionLength; - createSectionSpan(spanStartSection, i - 1, spanLength, previousSectionResizeMode); - //Q_ASSERT(headerLength() == length); - spanStartSection = i; - } - - if (newSectionLength != oldSectionLength) - emit q->sectionResized(logicalIndex(i), oldSectionLength, newSectionLength); - - previousSectionLength = newSectionLength; - previousSectionResizeMode = newSectionResizeMode; - } - - createSectionSpan(spanStartSection, sectionCount - 1, - (sectionCount - spanStartSection) * previousSectionLength, - previousSectionResizeMode); - //Q_ASSERT(headerLength() == length); - resizeRecursionBlock = false; - viewport->update(); -} - -void QHeaderViewPrivate::createSectionSpan(int start, int end, int size, QHeaderView::ResizeMode mode) -{ - // ### the code for merging spans does not merge at all opertuneties - // ### what if the number of sections is reduced ? - - SectionSpan span(size, (end - start) + 1, mode); - int start_section = 0; -#ifndef QT_NO_DEBUG - int initial_section_count = headerSectionCount(); // ### debug code -#endif - - QList<int> spansToRemove; - for (int i = 0; i < sectionSpans.count(); ++i) { - int end_section = start_section + sectionSpans.at(i).count - 1; - int section_count = sectionSpans.at(i).count; - if (start <= start_section && end > end_section) { - // the existing span is entirely coveded by the new span - spansToRemove.append(i); - } else if (start < start_section && end >= end_section) { - // the existing span is entirely coveded by the new span - spansToRemove.append(i); - } else if (start == start_section && end == end_section) { - // the new span is covered by an existin span - length -= sectionSpans.at(i).size; - length += size; - sectionSpans[i].size = size; - sectionSpans[i].resizeMode = mode; - // ### check if we can merge the section with any of its neighbours - removeSpans(spansToRemove); - Q_ASSERT(initial_section_count == headerSectionCount()); - return; - } else if (start > start_section && end < end_section) { - if (sectionSpans.at(i).sectionSize() == span.sectionSize() - && sectionSpans.at(i).resizeMode == span.resizeMode) { - Q_ASSERT(initial_section_count == headerSectionCount()); - return; - } - // the new span is in the middle of the old span, so we have to split it - length -= sectionSpans.at(i).size; - int section_size = sectionSpans.at(i).sectionSize(); -#ifndef QT_NO_DEBUG - int span_count = sectionSpans.at(i).count; -#endif - QHeaderView::ResizeMode span_mode = sectionSpans.at(i).resizeMode; - // first span - int first_span_count = start - start_section; - int first_span_size = section_size * first_span_count; - sectionSpans[i].count = first_span_count; - sectionSpans[i].size = first_span_size; - sectionSpans[i].resizeMode = span_mode; - length += first_span_size; - // middle span (the new span) -#ifndef QT_NO_DEBUG - int mid_span_count = span.count; -#endif - int mid_span_size = span.size; - sectionSpans.insert(i + 1, span); - length += mid_span_size; - // last span - int last_span_count = end_section - end; - int last_span_size = section_size * last_span_count; - sectionSpans.insert(i + 2, SectionSpan(last_span_size, last_span_count, span_mode)); - length += last_span_size; - Q_ASSERT(span_count == first_span_count + mid_span_count + last_span_count); - removeSpans(spansToRemove); - Q_ASSERT(initial_section_count == headerSectionCount()); - return; - } else if (start > start_section && start <= end_section && end >= end_section) { - // the new span covers the last part of the existing span - length -= sectionSpans.at(i).size; - int removed_count = (end_section - start + 1); - int span_count = sectionSpans.at(i).count - removed_count; - int section_size = sectionSpans.at(i).sectionSize(); - int span_size = section_size * span_count; - sectionSpans[i].count = span_count; - sectionSpans[i].size = span_size; - length += span_size; - if (end == end_section) { - sectionSpans.insert(i + 1, span); // insert after - length += span.size; - removeSpans(spansToRemove); - Q_ASSERT(initial_section_count == headerSectionCount()); - return; - } - } else if (end < end_section && end >= start_section && start <= start_section) { - // the new span covers the first part of the existing span - length -= sectionSpans.at(i).size; - int removed_count = (end - start_section + 1); - int section_size = sectionSpans.at(i).sectionSize(); - int span_count = sectionSpans.at(i).count - removed_count; - int span_size = section_size * span_count; - sectionSpans[i].count = span_count; - sectionSpans[i].size = span_size; - length += span_size; - sectionSpans.insert(i, span); // insert before - length += span.size; - removeSpans(spansToRemove); - Q_ASSERT(initial_section_count == headerSectionCount()); - return; - } - start_section += section_count; - } - - // ### adding and removing _ sections_ in addition to spans - // ### add some more checks here - - if (spansToRemove.isEmpty()) { - if (!sectionSpans.isEmpty() - && sectionSpans.last().sectionSize() == span.sectionSize() - && sectionSpans.last().resizeMode == span.resizeMode) { - length += span.size; - int last = sectionSpans.count() - 1; - sectionSpans[last].count += span.count; - sectionSpans[last].size += span.size; - sectionSpans[last].resizeMode = span.resizeMode; - } else { - length += span.size; - sectionSpans.append(span); - } - } else { - removeSpans(spansToRemove); - length += span.size; - sectionSpans.insert(spansToRemove.first(), span); - //Q_ASSERT(initial_section_count == headerSectionCount()); - } -} - -void QHeaderViewPrivate::removeSectionsFromSpans(int start, int end) -{ - // remove sections - int start_section = 0; - QList<int> spansToRemove; - for (int i = 0; i < sectionSpans.count(); ++i) { - int end_section = start_section + sectionSpans.at(i).count - 1; - int section_size = sectionSpans.at(i).sectionSize(); - int section_count = sectionSpans.at(i).count; - if (start <= start_section && end >= end_section) { - // the change covers the entire span - spansToRemove.append(i); - if (end == end_section) - break; - } else if (start > start_section && end < end_section) { - // all the removed sections are inside the span - int change = (end - start + 1); - sectionSpans[i].count -= change; - sectionSpans[i].size = section_size * sectionSpans.at(i).count; - length -= (change * section_size); - break; - } else if (start >= start_section && start <= end_section) { - // the some of the removed sections are inside the span,at the end - int change = qMin(end_section - start + 1, end - start + 1); - sectionSpans[i].count -= change; - sectionSpans[i].size = section_size * sectionSpans.at(i).count; - start += change; - length -= (change * section_size); - // the change affects several spans - } else if (end >= start_section && end <= end_section) { - // the some of the removed sections are inside the span, at the beginning - int change = qMin((end - start_section + 1), end - start + 1); - sectionSpans[i].count -= change; - sectionSpans[i].size = section_size * sectionSpans.at(i).count; - length -= (change * section_size); - break; - } - start_section += section_count; - } - - for (int i = spansToRemove.count() - 1; i >= 0; --i) { - int s = spansToRemove.at(i); - length -= sectionSpans.at(s).size; - sectionSpans.remove(s); - // ### merge remaining spans - } -} - -void QHeaderViewPrivate::clear() -{ - if (state != NoClear) { - length = 0; - sectionCount = 0; - visualIndices.clear(); - logicalIndices.clear(); - sectionSelected.clear(); - sectionHidden.clear(); - hiddenSectionSize.clear(); - sectionSpans.clear(); - } -} - -void QHeaderViewPrivate::flipSortIndicator(int section) -{ - Q_Q(QHeaderView); - Qt::SortOrder sortOrder; - if (sortIndicatorSection == section) { - sortOrder = (sortIndicatorOrder == Qt::DescendingOrder) ? Qt::AscendingOrder : Qt::DescendingOrder; - } else { - const QVariant value = model->headerData(section, orientation, Qt::InitialSortOrderRole); - if (value.canConvert(QVariant::Int)) - sortOrder = static_cast<Qt::SortOrder>(value.toInt()); - else - sortOrder = Qt::AscendingOrder; - } - q->setSortIndicator(section, sortOrder); -} - -void QHeaderViewPrivate::cascadingResize(int visual, int newSize) -{ - Q_Q(QHeaderView); - const int minimumSize = q->minimumSectionSize(); - const int oldSize = headerSectionSize(visual); - int delta = newSize - oldSize; - - if (delta > 0) { // larger - bool sectionResized = false; - - // restore old section sizes - for (int i = firstCascadingSection; i < visual; ++i) { - if (cascadingSectionSize.contains(i)) { - int currentSectionSize = headerSectionSize(i); - int originalSectionSize = cascadingSectionSize.value(i); - if (currentSectionSize < originalSectionSize) { - int newSectionSize = currentSectionSize + delta; - resizeSectionSpan(i, currentSectionSize, newSectionSize); - if (newSectionSize >= originalSectionSize && false) - cascadingSectionSize.remove(i); // the section is now restored - sectionResized = true; - break; - } - } - - } - - // resize the section - if (!sectionResized) { - newSize = qMax(newSize, minimumSize); - if (oldSize != newSize) - resizeSectionSpan(visual, oldSize, newSize); - } - - // cascade the section size change - for (int i = visual + 1; i < sectionCount; ++i) { - if (!sectionIsCascadable(i)) - continue; - int currentSectionSize = headerSectionSize(i); - if (currentSectionSize <= minimumSize) - continue; - int newSectionSize = qMax(currentSectionSize - delta, minimumSize); - //qDebug() << "### cascading to" << i << newSectionSize - currentSectionSize << delta; - resizeSectionSpan(i, currentSectionSize, newSectionSize); - saveCascadingSectionSize(i, currentSectionSize); - delta = delta - (currentSectionSize - newSectionSize); - //qDebug() << "new delta" << delta; - //if (newSectionSize != minimumSize) - if (delta <= 0) - break; - } - } else { // smaller - bool sectionResized = false; - - // restore old section sizes - for (int i = lastCascadingSection; i > visual; --i) { - if (!cascadingSectionSize.contains(i)) - continue; - int currentSectionSize = headerSectionSize(i); - int originalSectionSize = cascadingSectionSize.value(i); - if (currentSectionSize >= originalSectionSize) - continue; - int newSectionSize = currentSectionSize - delta; - resizeSectionSpan(i, currentSectionSize, newSectionSize); - if (newSectionSize >= originalSectionSize && false) { - //qDebug() << "section" << i << "restored to" << originalSectionSize; - cascadingSectionSize.remove(i); // the section is now restored - } - sectionResized = true; - break; - } - - // resize the section - resizeSectionSpan(visual, oldSize, qMax(newSize, minimumSize)); - - // cascade the section size change - if (delta < 0 && newSize < minimumSize) { - for (int i = visual - 1; i >= 0; --i) { - if (!sectionIsCascadable(i)) - continue; - int sectionSize = headerSectionSize(i); - if (sectionSize <= minimumSize) - continue; - resizeSectionSpan(i, sectionSize, qMax(sectionSize + delta, minimumSize)); - saveCascadingSectionSize(i, sectionSize); - break; - } - } - - // let the next section get the space from the resized section - if (!sectionResized) { - for (int i = visual + 1; i < sectionCount; ++i) { - if (!sectionIsCascadable(i)) - continue; - int currentSectionSize = headerSectionSize(i); - int newSectionSize = qMax(currentSectionSize - delta, minimumSize); - resizeSectionSpan(i, currentSectionSize, newSectionSize); - break; - } - } - } - - if (hasAutoResizeSections()) - doDelayedResizeSections(); - - viewport->update(); -} - -void QHeaderViewPrivate::setDefaultSectionSize(int size) -{ - Q_Q(QHeaderView); - defaultSectionSize = size; - int currentVisualIndex = 0; - for (int i = 0; i < sectionSpans.count(); ++i) { - QHeaderViewPrivate::SectionSpan &span = sectionSpans[i]; - if (span.size > 0) { - //we resize it if it is not hidden (ie size > 0) - const int newSize = span.count * size; - if (newSize != span.size) { - length += newSize - span.size; //the whole length is changed - const int oldSectionSize = span.sectionSize(); - span.size = span.count * size; - for (int i = currentVisualIndex; i < currentVisualIndex + span.count; ++i) { - emit q->sectionResized(logicalIndex(i), oldSectionSize, size); - } - } - } - currentVisualIndex += span.count; - } -} - -void QHeaderViewPrivate::resizeSectionSpan(int visualIndex, int oldSize, int newSize) -{ - Q_Q(QHeaderView); - QHeaderView::ResizeMode mode = headerSectionResizeMode(visualIndex); - createSectionSpan(visualIndex, visualIndex, newSize, mode); - emit q->sectionResized(logicalIndex(visualIndex), oldSize, newSize); -} - -int QHeaderViewPrivate::headerSectionSize(int visual) const -{ - // ### stupid iteration - int section_start = 0; - const int sectionSpansCount = sectionSpans.count(); - for (int i = 0; i < sectionSpansCount; ++i) { - const QHeaderViewPrivate::SectionSpan ¤tSection = sectionSpans.at(i); - int section_end = section_start + currentSection.count - 1; - if (visual >= section_start && visual <= section_end) - return currentSection.sectionSize(); - section_start = section_end + 1; - } - return -1; -} - -int QHeaderViewPrivate::headerSectionPosition(int visual) const -{ - // ### stupid iteration - int section_start = 0; - int span_position = 0; - const int sectionSpansCount = sectionSpans.count(); - for (int i = 0; i < sectionSpansCount; ++i) { - const QHeaderViewPrivate::SectionSpan ¤tSection = sectionSpans.at(i); - int section_end = section_start + currentSection.count - 1; - if (visual >= section_start && visual <= section_end) - return span_position + (visual - section_start) * currentSection.sectionSize(); - section_start = section_end + 1; - span_position += currentSection.size; - } - return -1; -} - -int QHeaderViewPrivate::headerVisualIndexAt(int position) const -{ - // ### stupid iteration - int span_start_section = 0; - int span_position = 0; - const int sectionSpansCount = sectionSpans.count(); - for (int i = 0; i < sectionSpansCount; ++i) { - const QHeaderViewPrivate::SectionSpan ¤tSection = sectionSpans.at(i); - int next_span_start_section = span_start_section + currentSection.count; - int next_span_position = span_position + currentSection.size; - if (position == span_position) - return span_start_section; // spans with no size - if (position > span_position && position < next_span_position) { - int position_in_span = position - span_position; - return span_start_section + (position_in_span / currentSection.sectionSize()); - } - span_start_section = next_span_start_section; - span_position = next_span_position; - } - return -1; -} - -void QHeaderViewPrivate::setHeaderSectionResizeMode(int visual, QHeaderView::ResizeMode mode) -{ - int size = headerSectionSize(visual); - createSectionSpan(visual, visual, size, mode); -} - -QHeaderView::ResizeMode QHeaderViewPrivate::headerSectionResizeMode(int visual) const -{ - int span = sectionSpanIndex(visual); - if (span == -1) - return globalResizeMode; - return sectionSpans.at(span).resizeMode; -} - -void QHeaderViewPrivate::setGlobalHeaderResizeMode(QHeaderView::ResizeMode mode) -{ - globalResizeMode = mode; - for (int i = 0; i < sectionSpans.count(); ++i) - sectionSpans[i].resizeMode = mode; -} - -int QHeaderViewPrivate::viewSectionSizeHint(int logical) const -{ - if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(parent)) { - return (orientation == Qt::Horizontal - ? view->sizeHintForColumn(logical) - : view->sizeHintForRow(logical)); - } - return 0; -} - -int QHeaderViewPrivate::adjustedVisualIndex(int visualIndex) const -{ - if (hiddenSectionSize.count() > 0) { - int adjustedVisualIndex = visualIndex; - int currentVisualIndex = 0; - for (int i = 0; i < sectionSpans.count(); ++i) { - if (sectionSpans.at(i).size == 0) - adjustedVisualIndex += sectionSpans.at(i).count; - else - currentVisualIndex += sectionSpans.at(i).count; - if (currentVisualIndex >= visualIndex) - break; - } - visualIndex = adjustedVisualIndex; - } - return visualIndex; -} - -#ifndef QT_NO_DATASTREAM -void QHeaderViewPrivate::write(QDataStream &out) const -{ - out << int(orientation); - out << int(sortIndicatorOrder); - out << sortIndicatorSection; - out << sortIndicatorShown; - - out << visualIndices; - out << logicalIndices; - - out << sectionHidden; - out << hiddenSectionSize; - - out << length; - out << sectionCount; - out << movableSections; - out << clickableSections; - out << highlightSelected; - out << stretchLastSection; - out << cascadingResizing; - out << stretchSections; - out << contentsSections; - out << defaultSectionSize; - out << minimumSectionSize; - - out << int(defaultAlignment); - out << int(globalResizeMode); - - out << sectionSpans; -} - -bool QHeaderViewPrivate::read(QDataStream &in) -{ - int orient, order, align, global; - in >> orient; - orientation = (Qt::Orientation)orient; - - in >> order; - sortIndicatorOrder = (Qt::SortOrder)order; - - in >> sortIndicatorSection; - in >> sortIndicatorShown; - - in >> visualIndices; - in >> logicalIndices; - - in >> sectionHidden; - in >> hiddenSectionSize; - - in >> length; - in >> sectionCount; - in >> movableSections; - in >> clickableSections; - in >> highlightSelected; - in >> stretchLastSection; - in >> cascadingResizing; - in >> stretchSections; - in >> contentsSections; - in >> defaultSectionSize; - in >> minimumSectionSize; - - in >> align; - defaultAlignment = Qt::Alignment(align); - - in >> global; - globalResizeMode = (QHeaderView::ResizeMode)global; - - in >> sectionSpans; - - return true; -} - -#endif // QT_NO_DATASTREAM - -QT_END_NAMESPACE - -#endif // QT_NO_ITEMVIEWS - -#include "moc_qheaderview.cpp" |