util/src/gui/itemviews/qheaderview.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qheaderview.h"
       
    43 
       
    44 #ifndef QT_NO_ITEMVIEWS
       
    45 #include <qbitarray.h>
       
    46 #include <qbrush.h>
       
    47 #include <qdebug.h>
       
    48 #include <qevent.h>
       
    49 #include <qpainter.h>
       
    50 #include <qscrollbar.h>
       
    51 #include <qtooltip.h>
       
    52 #include <qwhatsthis.h>
       
    53 #include <qstyle.h>
       
    54 #include <qstyleoption.h>
       
    55 #include <qvector.h>
       
    56 #include <qapplication.h>
       
    57 #include <qvarlengtharray.h>
       
    58 #include <qabstractitemdelegate.h>
       
    59 #include <qvariant.h>
       
    60 #include <private/qheaderview_p.h>
       
    61 #include <private/qabstractitemmodel_p.h>
       
    62 
       
    63 #ifndef QT_NO_DATASTREAM
       
    64 #include <qdatastream.h>
       
    65 #endif
       
    66 
       
    67 QT_BEGIN_NAMESPACE
       
    68 
       
    69 #ifndef QT_NO_DATASTREAM
       
    70 QDataStream &operator<<(QDataStream &out, const QHeaderViewPrivate::SectionSpan &span)
       
    71 {
       
    72     span.write(out);
       
    73     return out;
       
    74 }
       
    75 
       
    76 QDataStream &operator>>(QDataStream &in, QHeaderViewPrivate::SectionSpan &span)
       
    77 {
       
    78     span.read(in);
       
    79     return in;
       
    80 }
       
    81 #endif // QT_NO_DATASTREAM
       
    82 
       
    83 
       
    84 /*!
       
    85     \class QHeaderView
       
    86 
       
    87     \brief The QHeaderView class provides a header row or header column for
       
    88     item views.
       
    89 
       
    90     \ingroup model-view
       
    91 
       
    92 
       
    93     A QHeaderView displays the headers used in item views such as the
       
    94     QTableView and QTreeView classes. It takes the place of Qt3's \c QHeader
       
    95     class previously used for the same purpose, but uses the Qt's model/view
       
    96     architecture for consistency with the item view classes.
       
    97 
       
    98     The QHeaderView class is one of the \l{Model/View Classes} and is part of
       
    99     Qt's \l{Model/View Programming}{model/view framework}.
       
   100 
       
   101     The header gets the data for each section from the model using the
       
   102     QAbstractItemModel::headerData() function. You can set the data by using
       
   103     QAbstractItemModel::setHeaderData().
       
   104 
       
   105     Each header has an orientation() and a number of sections, given by the
       
   106     count() function. A section refers to a part of the header - either a row
       
   107     or a column, depending on the orientation.
       
   108 
       
   109     Sections can be moved and resized using moveSection() and resizeSection();
       
   110     they can also be hidden and shown with hideSection() and showSection().
       
   111 
       
   112     Each section of a header is described by a section ID, specified by its
       
   113     section(), and can be located at a particular visualIndex() in the header.
       
   114     A section can have a sort indicator set with setSortIndicator(); this
       
   115     indicates whether the items in the associated item view will be sorted in
       
   116     the order given by the section.
       
   117 
       
   118     For a horizontal header the section is equivalent to a column in the model,
       
   119     and for a vertical header the section is equivalent to a row in the model.
       
   120 
       
   121     \section1 Moving Header Sections
       
   122 
       
   123     A header can be fixed in place, or made movable with setMovable(). It can
       
   124     be made clickable with setClickable(), and has resizing behavior in
       
   125     accordance with setResizeMode().
       
   126 
       
   127     \note Double-clicking on a header to resize a section only applies for
       
   128     visible rows.
       
   129 
       
   130     A header will emit sectionMoved() if the user moves a section,
       
   131     sectionResized() if the user resizes a section, and sectionClicked() as
       
   132     well as sectionHandleDoubleClicked() in response to mouse clicks. A header
       
   133     will also emit sectionCountChanged() and sectionAutoResize().
       
   134 
       
   135     You can identify a section using the logicalIndex() and logicalIndexAt()
       
   136     functions, or by its index position, using the visualIndex() and
       
   137     visualIndexAt() functions. The visual index will change if a section is
       
   138     moved, but the logical index will not change.
       
   139 
       
   140     \section1 Appearance
       
   141 
       
   142     QTableWidget and QTableView create default headers. If you want
       
   143     the headers to be visible, you can use \l{QFrame::}{setVisible()}.
       
   144 
       
   145     Not all \l{Qt::}{ItemDataRole}s will have an effect on a
       
   146     QHeaderView. If you need to draw other roles, you can subclass
       
   147     QHeaderView and reimplement \l{QHeaderView::}{paintEvent()}.
       
   148     QHeaderView respects the following item data roles:
       
   149     \l{Qt::}{TextAlignmentRole}, \l{Qt::}{DisplayRole},
       
   150     \l{Qt::}{FontRole}, \l{Qt::}{DecorationRole},
       
   151     \l{Qt::}{ForegroundRole}, and \l{Qt::}{BackgroundRole}.
       
   152 
       
   153     \note Each header renders the data for each section itself, and does not
       
   154     rely on a delegate. As a result, calling a header's setItemDelegate()
       
   155     function will have no effect.
       
   156 
       
   157     \sa {Model/View Programming}, QListView, QTableView, QTreeView
       
   158 */
       
   159 
       
   160 /*!
       
   161     \enum QHeaderView::ResizeMode
       
   162 
       
   163     The resize mode specifies the behavior of the header sections. It can be
       
   164     set on the entire header view or on individual sections using
       
   165     setResizeMode().
       
   166 
       
   167     \value Interactive The user can resize the section. The section can also be
       
   168            resized programmatically using resizeSection().  The section size
       
   169            defaults to \l defaultSectionSize. (See also
       
   170            \l cascadingSectionResizes.)
       
   171 
       
   172     \value Fixed The user cannot resize the section. The section can only be
       
   173            resized programmatically using resizeSection(). The section size
       
   174            defaults to \l defaultSectionSize.
       
   175 
       
   176     \value Stretch QHeaderView will automatically resize the section to fill
       
   177            the available space. The size cannot be changed by the user or
       
   178            programmatically.
       
   179 
       
   180     \value ResizeToContents QHeaderView will automatically resize the section
       
   181            to its optimal size based on the contents of the entire column or
       
   182            row. The size cannot be changed by the user or programmatically.
       
   183            (This value was introduced in 4.2)
       
   184 
       
   185     The following values are obsolete:
       
   186     \value Custom Use Fixed instead.
       
   187 
       
   188     \sa setResizeMode() stretchLastSection minimumSectionSize
       
   189 */
       
   190 
       
   191 /*!
       
   192     \fn void QHeaderView::sectionMoved(int logicalIndex, int oldVisualIndex,
       
   193     int newVisualIndex)
       
   194 
       
   195     This signal is emitted when a section is moved. The section's logical index
       
   196     is specified by \a logicalIndex, the old index by \a oldVisualIndex, and
       
   197     the new index position by \a newVisualIndex.
       
   198 
       
   199     \sa moveSection()
       
   200 */
       
   201 
       
   202 /*!
       
   203     \fn void QHeaderView::sectionResized(int logicalIndex, int oldSize,
       
   204     int newSize)
       
   205 
       
   206     This signal is emitted when a section is resized. The section's logical
       
   207     number is specified by \a logicalIndex, the old size by \a oldSize, and the
       
   208     new size by \a newSize.
       
   209 
       
   210     \sa resizeSection()
       
   211 */
       
   212 
       
   213 /*!
       
   214     \fn void QHeaderView::sectionPressed(int logicalIndex)
       
   215 
       
   216     This signal is emitted when a section is pressed. The section's logical
       
   217     index is specified by \a logicalIndex.
       
   218 
       
   219     \sa setClickable()
       
   220 */
       
   221 
       
   222 /*!
       
   223     \fn void QHeaderView::sectionClicked(int logicalIndex)
       
   224 
       
   225     This signal is emitted when a section is clicked. The section's logical
       
   226     index is specified by \a logicalIndex.
       
   227 
       
   228     Note that the sectionPressed signal will also be emitted.
       
   229 
       
   230     \sa setClickable(), sectionPressed()
       
   231 */
       
   232 
       
   233 /*!
       
   234     \fn void QHeaderView::sectionEntered(int logicalIndex)
       
   235     \since 4.3
       
   236 
       
   237     This signal is emitted when the cursor moves over the section and the left
       
   238     mouse button is pressed. The section's logical index is specified by
       
   239     \a logicalIndex.
       
   240 
       
   241     \sa setClickable(), sectionPressed()
       
   242 */
       
   243 
       
   244 /*!
       
   245     \fn void QHeaderView::sectionDoubleClicked(int logicalIndex)
       
   246 
       
   247     This signal is emitted when a section is double-clicked. The section's
       
   248     logical index is specified by \a logicalIndex.
       
   249 
       
   250     \sa setClickable()
       
   251 */
       
   252 
       
   253 /*!
       
   254     \fn void QHeaderView::sectionCountChanged(int oldCount, int newCount)
       
   255 
       
   256     This signal is emitted when the number of sections changes, i.e., when
       
   257     sections are added or deleted. The original count is specified by
       
   258     \a oldCount, and the new count by \a newCount.
       
   259 
       
   260     \sa count(), length(), headerDataChanged()
       
   261 */
       
   262 
       
   263 /*!
       
   264     \fn void QHeaderView::sectionHandleDoubleClicked(int logicalIndex)
       
   265 
       
   266     This signal is emitted when a section is double-clicked. The section's
       
   267     logical index is specified by \a logicalIndex.
       
   268 
       
   269     \sa setClickable()
       
   270 */
       
   271 
       
   272 /*!
       
   273     \fn void QHeaderView::sortIndicatorChanged(int logicalIndex,
       
   274     Qt::SortOrder order)
       
   275     \since 4.3
       
   276 
       
   277     This signal is emitted when the section containing the sort indicator or
       
   278     the order indicated is changed. The section's logical index is specified
       
   279     by \a logicalIndex and the sort order is specified by \a order.
       
   280 
       
   281     \sa setSortIndicator()
       
   282 */
       
   283 
       
   284 /*!
       
   285     \fn void QHeaderView::sectionAutoResize(int logicalIndex,
       
   286     QHeaderView::ResizeMode mode)
       
   287 
       
   288     This signal is emitted when a section is automatically resized. The
       
   289     section's logical index is specified by \a logicalIndex, and the resize
       
   290     mode by \a mode.
       
   291 
       
   292     \sa setResizeMode(), stretchLastSection()
       
   293 */
       
   294 // ### Qt 5: change to sectionAutoResized()
       
   295 
       
   296 /*!
       
   297     \fn void QHeaderView::geometriesChanged()
       
   298     \since 4.2
       
   299 
       
   300     This signal is emitted when the header's geometries have changed.
       
   301 */
       
   302 
       
   303 /*!
       
   304     \property QHeaderView::highlightSections
       
   305     \brief whether the sections containing selected items are highlighted
       
   306 
       
   307     By default, this property is false.
       
   308 */
       
   309 
       
   310 /*!
       
   311     Creates a new generic header with the given \a orientation and \a parent.
       
   312 */
       
   313 QHeaderView::QHeaderView(Qt::Orientation orientation, QWidget *parent)
       
   314     : QAbstractItemView(*new QHeaderViewPrivate, parent)
       
   315 {
       
   316     Q_D(QHeaderView);
       
   317     d->setDefaultValues(orientation);
       
   318     initialize();
       
   319 }
       
   320 
       
   321 /*!
       
   322   \internal
       
   323 */
       
   324 QHeaderView::QHeaderView(QHeaderViewPrivate &dd,
       
   325                          Qt::Orientation orientation, QWidget *parent)
       
   326     : QAbstractItemView(dd, parent)
       
   327 {
       
   328     Q_D(QHeaderView);
       
   329     d->setDefaultValues(orientation);
       
   330     initialize();
       
   331 }
       
   332 
       
   333 /*!
       
   334   Destroys the header.
       
   335 */
       
   336 
       
   337 QHeaderView::~QHeaderView()
       
   338 {
       
   339 }
       
   340 
       
   341 /*!
       
   342   \internal
       
   343 */
       
   344 void QHeaderView::initialize()
       
   345 {
       
   346     Q_D(QHeaderView);
       
   347     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
       
   348     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
       
   349     setFrameStyle(NoFrame);
       
   350     setFocusPolicy(Qt::NoFocus);
       
   351     d->viewport->setMouseTracking(true);
       
   352     d->viewport->setBackgroundRole(QPalette::Button);
       
   353     d->textElideMode = Qt::ElideNone;
       
   354     delete d->itemDelegate;
       
   355 }
       
   356 
       
   357 /*!
       
   358   \reimp
       
   359 */
       
   360 void QHeaderView::setModel(QAbstractItemModel *model)
       
   361 {
       
   362     if (model == this->model())
       
   363         return;
       
   364     Q_D(QHeaderView);
       
   365     if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
       
   366     if (d->orientation == Qt::Horizontal) {
       
   367         QObject::disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)),
       
   368                             this, SLOT(sectionsInserted(QModelIndex,int,int)));
       
   369         QObject::disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
       
   370                             this, SLOT(sectionsAboutToBeRemoved(QModelIndex,int,int)));
       
   371         QObject::disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
       
   372                             this, SLOT(_q_sectionsRemoved(QModelIndex,int,int)));
       
   373     } else {
       
   374         QObject::disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
       
   375                             this, SLOT(sectionsInserted(QModelIndex,int,int)));
       
   376         QObject::disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
       
   377                             this, SLOT(sectionsAboutToBeRemoved(QModelIndex,int,int)));
       
   378         QObject::disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
       
   379                             this, SLOT(_q_sectionsRemoved(QModelIndex,int,int)));
       
   380     }
       
   381     QObject::disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
       
   382                         this, SLOT(headerDataChanged(Qt::Orientation,int,int)));
       
   383         QObject::disconnect(d->model, SIGNAL(layoutAboutToBeChanged()),
       
   384                             this, SLOT(_q_layoutAboutToBeChanged()));
       
   385     }
       
   386 
       
   387     if (model && model != QAbstractItemModelPrivate::staticEmptyModel()) {
       
   388         if (d->orientation == Qt::Horizontal) {
       
   389             QObject::connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
       
   390                              this, SLOT(sectionsInserted(QModelIndex,int,int)));
       
   391             QObject::connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
       
   392                 this, SLOT(sectionsAboutToBeRemoved(QModelIndex,int,int)));
       
   393             QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
       
   394                 this, SLOT(_q_sectionsRemoved(QModelIndex,int,int)));
       
   395         } else {
       
   396             QObject::connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
       
   397                              this, SLOT(sectionsInserted(QModelIndex,int,int)));
       
   398             QObject::connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
       
   399                              this, SLOT(sectionsAboutToBeRemoved(QModelIndex,int,int)));
       
   400             QObject::connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
       
   401                              this, SLOT(_q_sectionsRemoved(QModelIndex,int,int)));
       
   402         }
       
   403         QObject::connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
       
   404                          this, SLOT(headerDataChanged(Qt::Orientation,int,int)));
       
   405         QObject::connect(model, SIGNAL(layoutAboutToBeChanged()),
       
   406                          this, SLOT(_q_layoutAboutToBeChanged()));
       
   407     }
       
   408 
       
   409     d->state = QHeaderViewPrivate::NoClear;
       
   410     QAbstractItemView::setModel(model);
       
   411     d->state = QHeaderViewPrivate::NoState;
       
   412 
       
   413     // Users want to set sizes and modes before the widget is shown.
       
   414     // Thus, we have to initialize when the model is set,
       
   415     // and not lazily like we do in the other views.
       
   416     initializeSections();
       
   417 }
       
   418 
       
   419 /*!
       
   420     Returns the orientation of the header.
       
   421 
       
   422     \sa Qt::Orientation
       
   423 */
       
   424 
       
   425 Qt::Orientation QHeaderView::orientation() const
       
   426 {
       
   427     Q_D(const QHeaderView);
       
   428     return d->orientation;
       
   429 }
       
   430 
       
   431 /*!
       
   432     Returns the offset of the header: this is the header's left-most (or
       
   433     top-most for vertical headers) visible pixel.
       
   434 
       
   435     \sa setOffset()
       
   436 */
       
   437 
       
   438 int QHeaderView::offset() const
       
   439 {
       
   440     Q_D(const QHeaderView);
       
   441     return d->offset;
       
   442 }
       
   443 
       
   444 /*!
       
   445     \fn void QHeaderView::setOffset(int offset)
       
   446 
       
   447     Sets the header's offset to \a offset.
       
   448 
       
   449     \sa offset(), length()
       
   450 */
       
   451 
       
   452 void QHeaderView::setOffset(int newOffset)
       
   453 {
       
   454     Q_D(QHeaderView);
       
   455     if (d->offset == (int)newOffset)
       
   456         return;
       
   457     int ndelta = d->offset - newOffset;
       
   458     d->offset = newOffset;
       
   459     if (d->orientation == Qt::Horizontal)
       
   460         d->viewport->scroll(isRightToLeft() ? -ndelta : ndelta, 0);
       
   461     else
       
   462         d->viewport->scroll(0, ndelta);
       
   463     if (d->state == QHeaderViewPrivate::ResizeSection) {
       
   464         QPoint cursorPos = QCursor::pos();
       
   465         if (d->orientation == Qt::Horizontal)
       
   466             QCursor::setPos(cursorPos.x() + ndelta, cursorPos.y());
       
   467         else
       
   468             QCursor::setPos(cursorPos.x(), cursorPos.y() + ndelta);
       
   469         d->firstPos += ndelta;
       
   470         d->lastPos += ndelta;
       
   471     }
       
   472 }
       
   473 
       
   474 /*!
       
   475     \since 4.2
       
   476     Sets the offset to the start of the section at the given \a visualIndex.
       
   477 
       
   478     \sa setOffset(), sectionPosition()
       
   479 */
       
   480 void QHeaderView::setOffsetToSectionPosition(int visualIndex)
       
   481 {
       
   482     Q_D(QHeaderView);
       
   483     if (visualIndex > -1 && visualIndex < d->sectionCount) {
       
   484         int position = d->headerSectionPosition(d->adjustedVisualIndex(visualIndex));
       
   485         setOffset(position);
       
   486     }
       
   487 }
       
   488 
       
   489 /*!
       
   490     \since 4.2
       
   491     Sets the offset to make the last section visible.
       
   492 
       
   493     \sa setOffset(), sectionPosition(), setOffsetToSectionPosition()
       
   494 */
       
   495 void QHeaderView::setOffsetToLastSection()
       
   496 {
       
   497     Q_D(const QHeaderView);
       
   498     int size = (d->orientation == Qt::Horizontal ? viewport()->width() : viewport()->height());
       
   499     int position = length() - size;
       
   500     setOffset(position);
       
   501 }
       
   502 
       
   503 /*!
       
   504     Returns the length along the orientation of the header.
       
   505 
       
   506     \sa sizeHint(), setResizeMode(), offset()
       
   507 */
       
   508 
       
   509 int QHeaderView::length() const
       
   510 {
       
   511     Q_D(const QHeaderView);
       
   512     //Q_ASSERT(d->headerLength() == d->length);
       
   513     return d->length;
       
   514 }
       
   515 
       
   516 /*!
       
   517     Returns a suitable size hint for this header.
       
   518 
       
   519     \sa sectionSizeHint()
       
   520 */
       
   521 
       
   522 QSize QHeaderView::sizeHint() const
       
   523 {
       
   524     Q_D(const QHeaderView);
       
   525     if (d->cachedSizeHint.isValid())
       
   526         return d->cachedSizeHint;
       
   527     d->cachedSizeHint = QSize(0, 0); //reinitialize the cached size hint
       
   528     const int sectionCount = count();
       
   529 
       
   530     // get size hint for the first n sections
       
   531     int i = 0;
       
   532     for (int checked = 0; checked < 100 && i < sectionCount; ++i) {
       
   533         if (isSectionHidden(i))
       
   534             continue;
       
   535         checked++;
       
   536         QSize hint = sectionSizeFromContents(i);
       
   537         d->cachedSizeHint = d->cachedSizeHint.expandedTo(hint);
       
   538     }
       
   539     // get size hint for the last n sections
       
   540     i = qMax(i, sectionCount - 100 );
       
   541     for (int j = sectionCount - 1, checked = 0; j >= i && checked < 100; --j) {
       
   542         if (isSectionHidden(j))
       
   543             continue;
       
   544         checked++;
       
   545         QSize hint = sectionSizeFromContents(j);
       
   546         d->cachedSizeHint = d->cachedSizeHint.expandedTo(hint);
       
   547     }
       
   548     return d->cachedSizeHint;
       
   549 }
       
   550 
       
   551 /*!
       
   552     Returns a suitable size hint for the section specified by \a logicalIndex.
       
   553 
       
   554     \sa sizeHint(), defaultSectionSize(), minimumSectionSize(),
       
   555     Qt::SizeHintRole
       
   556 */
       
   557 
       
   558 int QHeaderView::sectionSizeHint(int logicalIndex) const
       
   559 {
       
   560     Q_D(const QHeaderView);
       
   561     if (isSectionHidden(logicalIndex))
       
   562         return 0;
       
   563     if (logicalIndex < 0 || logicalIndex >= count())
       
   564         return -1;
       
   565     QSize size;
       
   566     QVariant value = d->model->headerData(logicalIndex, d->orientation, Qt::SizeHintRole);
       
   567     if (value.isValid())
       
   568         size = qvariant_cast<QSize>(value);
       
   569     else
       
   570         size = sectionSizeFromContents(logicalIndex);
       
   571     int hint = d->orientation == Qt::Horizontal ? size.width() : size.height();
       
   572     return qMax(minimumSectionSize(), hint);
       
   573 }
       
   574 
       
   575 /*!
       
   576     Returns the visual index of the section that covers the given \a position
       
   577     in the viewport.
       
   578 
       
   579     \sa logicalIndexAt()
       
   580 */
       
   581 
       
   582 int QHeaderView::visualIndexAt(int position) const
       
   583 {
       
   584     Q_D(const QHeaderView);
       
   585     int vposition = position;
       
   586     d->executePostedLayout();
       
   587     d->executePostedResize();
       
   588     const int count = d->sectionCount;
       
   589     if (count < 1)
       
   590         return -1;
       
   591 
       
   592     if (d->reverse())
       
   593         vposition = d->viewport->width() - vposition;
       
   594     vposition += d->offset;
       
   595 
       
   596     if (vposition > d->length)
       
   597         return -1;
       
   598     int visual = d->headerVisualIndexAt(vposition);
       
   599     if (visual < 0)
       
   600         return -1;
       
   601 
       
   602     while (d->isVisualIndexHidden(visual)){
       
   603         ++visual;
       
   604         if (visual >= count)
       
   605             return -1;
       
   606     }
       
   607     return visual;
       
   608 }
       
   609 
       
   610 /*!
       
   611     Returns the section that covers the given \a position in the viewport.
       
   612 
       
   613     \sa visualIndexAt(), isSectionHidden()
       
   614 */
       
   615 
       
   616 int QHeaderView::logicalIndexAt(int position) const
       
   617 {
       
   618     const int visual = visualIndexAt(position);
       
   619     if (visual > -1)
       
   620         return logicalIndex(visual);
       
   621     return -1;
       
   622 }
       
   623 
       
   624 /*!
       
   625     Returns the width (or height for vertical headers) of the given
       
   626     \a logicalIndex.
       
   627 
       
   628     \sa length(), setResizeMode(), defaultSectionSize()
       
   629 */
       
   630 
       
   631 int QHeaderView::sectionSize(int logicalIndex) const
       
   632 {
       
   633     Q_D(const QHeaderView);
       
   634     if (isSectionHidden(logicalIndex))
       
   635         return 0;
       
   636     if (logicalIndex < 0 || logicalIndex >= count())
       
   637         return 0;
       
   638     int visual = visualIndex(logicalIndex);
       
   639     if (visual == -1)
       
   640         return 0;
       
   641     d->executePostedResize();
       
   642     return d->headerSectionSize(visual);
       
   643 }
       
   644 
       
   645 /*!
       
   646     Returns the section position of the given \a logicalIndex, or -1 if the
       
   647     section is hidden.
       
   648 
       
   649     \sa sectionViewportPosition()
       
   650 */
       
   651 
       
   652 int QHeaderView::sectionPosition(int logicalIndex) const
       
   653 {
       
   654     Q_D(const QHeaderView);
       
   655     int visual = visualIndex(logicalIndex);
       
   656     // in some cases users may change the selections
       
   657     // before we have a chance to do the layout
       
   658     if (visual == -1)
       
   659         return -1;
       
   660     d->executePostedResize();
       
   661     return d->headerSectionPosition(visual);
       
   662 }
       
   663 
       
   664 /*!
       
   665     Returns the section viewport position of the given \a logicalIndex.
       
   666 
       
   667     If the section is hidden, the return value is undefined.
       
   668 
       
   669     \sa sectionPosition(), isSectionHidden()
       
   670 */
       
   671 
       
   672 int QHeaderView::sectionViewportPosition(int logicalIndex) const
       
   673 {
       
   674     Q_D(const QHeaderView);
       
   675     if (logicalIndex >= count())
       
   676         return -1;
       
   677     int position = sectionPosition(logicalIndex);
       
   678     if (position < 0)
       
   679         return position; // the section was hidden
       
   680     int offsetPosition = position - d->offset;
       
   681     if (d->reverse())
       
   682         return d->viewport->width() - (offsetPosition + sectionSize(logicalIndex));
       
   683     return offsetPosition;
       
   684 }
       
   685 
       
   686 /*!
       
   687     \fn int QHeaderView::logicalIndexAt(int x, int y) const
       
   688 
       
   689     Returns the logical index of the section at the given coordinate. If the
       
   690     header is horizontal \a x will be used, otherwise \a y will be used to
       
   691     find the logical index.
       
   692 */
       
   693 
       
   694 /*!
       
   695     \fn int QHeaderView::logicalIndexAt(const QPoint &pos) const
       
   696 
       
   697     Returns the logical index of the section at the position given in \a pos.
       
   698     If the header is horizontal the x-coordinate will be used, otherwise the
       
   699     y-coordinate will be used to find the logical index.
       
   700 
       
   701     \sa sectionPosition()
       
   702 */
       
   703 
       
   704 /*!
       
   705     Moves the section at visual index \a from to occupy visual index \a to.
       
   706 
       
   707     \sa sectionsMoved()
       
   708 */
       
   709 
       
   710 void QHeaderView::moveSection(int from, int to)
       
   711 {
       
   712     Q_D(QHeaderView);
       
   713 
       
   714     d->executePostedLayout();
       
   715     if (from < 0 || from >= d->sectionCount || to < 0 || to >= d->sectionCount)
       
   716         return;
       
   717 
       
   718     if (from == to) {
       
   719         int logical = logicalIndex(from);
       
   720         Q_ASSERT(logical != -1);
       
   721         updateSection(logical);
       
   722         return;
       
   723     }
       
   724 
       
   725     if (stretchLastSection() &&  to == d->lastVisibleVisualIndex())
       
   726         d->lastSectionSize = sectionSize(from);
       
   727 
       
   728     //int oldHeaderLength = length(); // ### for debugging; remove later
       
   729     d->initializeIndexMapping();
       
   730 
       
   731     QBitArray sectionHidden = d->sectionHidden;
       
   732     int *visualIndices = d->visualIndices.data();
       
   733     int *logicalIndices = d->logicalIndices.data();
       
   734     int logical = logicalIndices[from];
       
   735     int visual = from;
       
   736 
       
   737     int affected_count = qAbs(to - from) + 1;
       
   738     QVarLengthArray<int> sizes(affected_count);
       
   739     QVarLengthArray<ResizeMode> modes(affected_count);
       
   740 
       
   741     // move sections and indices
       
   742     if (to > from) {
       
   743         sizes[to - from] = d->headerSectionSize(from);
       
   744         modes[to - from] = d->headerSectionResizeMode(from);
       
   745         while (visual < to) {
       
   746             sizes[visual - from] = d->headerSectionSize(visual + 1);
       
   747             modes[visual - from] = d->headerSectionResizeMode(visual + 1);
       
   748             if (!sectionHidden.isEmpty())
       
   749                 sectionHidden.setBit(visual, sectionHidden.testBit(visual + 1));
       
   750             visualIndices[logicalIndices[visual + 1]] = visual;
       
   751             logicalIndices[visual] = logicalIndices[visual + 1];
       
   752             ++visual;
       
   753         }
       
   754     } else {
       
   755         sizes[0] = d->headerSectionSize(from);
       
   756         modes[0] = d->headerSectionResizeMode(from);
       
   757         while (visual > to) {
       
   758             sizes[visual - to] = d->headerSectionSize(visual - 1);
       
   759             modes[visual - to] = d->headerSectionResizeMode(visual - 1);
       
   760             if (!sectionHidden.isEmpty())
       
   761                 sectionHidden.setBit(visual, sectionHidden.testBit(visual - 1));
       
   762             visualIndices[logicalIndices[visual - 1]] = visual;
       
   763             logicalIndices[visual] = logicalIndices[visual - 1];
       
   764             --visual;
       
   765         }
       
   766     }
       
   767     if (!sectionHidden.isEmpty()) {
       
   768         sectionHidden.setBit(to, d->sectionHidden.testBit(from));
       
   769         d->sectionHidden = sectionHidden;
       
   770     }
       
   771     visualIndices[logical] = to;
       
   772     logicalIndices[to] = logical;
       
   773 
       
   774     //Q_ASSERT(oldHeaderLength == length());
       
   775     // move sizes
       
   776     // ### check for spans of section sizes here
       
   777     if (to > from) {
       
   778         for (visual = from; visual <= to; ++visual) {
       
   779             int size = sizes[visual - from];
       
   780             ResizeMode mode = modes[visual - from];
       
   781             d->createSectionSpan(visual, visual, size, mode);
       
   782         }
       
   783     } else {
       
   784         for (visual = to; visual <= from; ++visual) {
       
   785             int size = sizes[visual - to];
       
   786             ResizeMode mode = modes[visual - to];
       
   787             d->createSectionSpan(visual, visual, size, mode);
       
   788         }
       
   789     }
       
   790     //Q_ASSERT(d->headerLength() == length());
       
   791     //Q_ASSERT(oldHeaderLength == length());
       
   792     //Q_ASSERT(d->logicalIndices.count() == d->sectionCount);
       
   793 
       
   794     if (d->hasAutoResizeSections())
       
   795         d->doDelayedResizeSections();
       
   796     d->viewport->update();
       
   797 
       
   798     emit sectionMoved(logical, from, to);
       
   799 }
       
   800 
       
   801 /*!
       
   802     \since 4.2
       
   803     Swaps the section at visual index \a first with the section at visual
       
   804     index \a second.
       
   805 
       
   806     \sa moveSection()
       
   807 */
       
   808 void QHeaderView::swapSections(int first, int second)
       
   809 {
       
   810     Q_D(QHeaderView);
       
   811 
       
   812     if (first == second)
       
   813         return;
       
   814     d->executePostedLayout();
       
   815     if (first < 0 || first >= d->sectionCount || second < 0 || second >= d->sectionCount)
       
   816         return;
       
   817 
       
   818     int firstSize = d->headerSectionSize(first);
       
   819     ResizeMode firstMode = d->headerSectionResizeMode(first);
       
   820     int firstLogical = d->logicalIndex(first);
       
   821 
       
   822     int secondSize = d->headerSectionSize(second);
       
   823     ResizeMode secondMode = d->headerSectionResizeMode(second);
       
   824     int secondLogical = d->logicalIndex(second);
       
   825 
       
   826     d->createSectionSpan(second, second, firstSize, firstMode);
       
   827     d->createSectionSpan(first, first, secondSize, secondMode);
       
   828 
       
   829     d->initializeIndexMapping();
       
   830 
       
   831     d->visualIndices[firstLogical] = second;
       
   832     d->logicalIndices[second] = firstLogical;
       
   833 
       
   834     d->visualIndices[secondLogical] = first;
       
   835     d->logicalIndices[first] = secondLogical;
       
   836 
       
   837     if (!d->sectionHidden.isEmpty()) {
       
   838         bool firstHidden = d->sectionHidden.testBit(first);
       
   839         bool secondHidden = d->sectionHidden.testBit(second);
       
   840         d->sectionHidden.setBit(first, secondHidden);
       
   841         d->sectionHidden.setBit(second, firstHidden);
       
   842     }
       
   843 
       
   844     d->viewport->update();
       
   845     emit sectionMoved(firstLogical, first, second);
       
   846     emit sectionMoved(secondLogical, second, first);
       
   847 }
       
   848 
       
   849 /*!
       
   850     \fn void QHeaderView::resizeSection(int logicalIndex, int size)
       
   851 
       
   852     Resizes the section specified by \a logicalIndex to \a size measured in
       
   853     pixels.
       
   854 
       
   855     \sa sectionResized(), resizeMode(), sectionSize()
       
   856 */
       
   857 
       
   858 void QHeaderView::resizeSection(int logical, int size)
       
   859 {
       
   860     Q_D(QHeaderView);
       
   861     if (logical < 0 || logical >= count())
       
   862         return;
       
   863 
       
   864     if (isSectionHidden(logical)) {
       
   865         d->hiddenSectionSize.insert(logical, size);
       
   866         return;
       
   867     }
       
   868 
       
   869     int visual = visualIndex(logical);
       
   870     if (visual == -1)
       
   871         return;
       
   872 
       
   873     int oldSize = d->headerSectionSize(visual);
       
   874     if (oldSize == size)
       
   875         return;
       
   876 
       
   877     d->executePostedLayout();
       
   878     d->invalidateCachedSizeHint();
       
   879 
       
   880     if (stretchLastSection() && visual == d->lastVisibleVisualIndex())
       
   881         d->lastSectionSize = size;
       
   882 
       
   883     if (size != oldSize)
       
   884         d->createSectionSpan(visual, visual, size, d->headerSectionResizeMode(visual));
       
   885 
       
   886     int w = d->viewport->width();
       
   887     int h = d->viewport->height();
       
   888     int pos = sectionViewportPosition(logical);
       
   889     QRect r;
       
   890     if (d->orientation == Qt::Horizontal)
       
   891         if (isRightToLeft())
       
   892             r.setRect(0, 0, pos + size, h);
       
   893         else
       
   894             r.setRect(pos, 0, w - pos, h);
       
   895     else
       
   896         r.setRect(0, pos, w, h - pos);
       
   897 
       
   898     if (d->hasAutoResizeSections()) {
       
   899         d->doDelayedResizeSections();
       
   900         r = d->viewport->rect();
       
   901     }
       
   902     d->viewport->update(r.normalized());
       
   903     emit sectionResized(logical, oldSize, size);
       
   904 }
       
   905 
       
   906 /*!
       
   907     Resizes the sections according to the given \a mode, ignoring the current
       
   908     resize mode.
       
   909 
       
   910     \sa resizeMode(), sectionResized()
       
   911 */
       
   912 
       
   913 void QHeaderView::resizeSections(QHeaderView::ResizeMode mode)
       
   914 {
       
   915     Q_D(QHeaderView);
       
   916     d->resizeSections(mode, true);
       
   917 }
       
   918 
       
   919 /*!
       
   920     \fn void QHeaderView::hideSection(int logicalIndex)
       
   921     Hides the section specified by \a logicalIndex.
       
   922 
       
   923     \sa showSection(), isSectionHidden(), hiddenSectionCount(),
       
   924     setSectionHidden()
       
   925 */
       
   926 
       
   927 /*!
       
   928     \fn void QHeaderView::showSection(int logicalIndex)
       
   929     Shows the section specified by \a logicalIndex.
       
   930 
       
   931     \sa hideSection(), isSectionHidden(), hiddenSectionCount(),
       
   932     setSectionHidden()
       
   933 */
       
   934 
       
   935 /*!
       
   936     Returns true if the section specified by \a logicalIndex is explicitly
       
   937     hidden from the user; otherwise returns false.
       
   938 
       
   939     \sa hideSection(), showSection(), setSectionHidden(), hiddenSectionCount()
       
   940 */
       
   941 
       
   942 bool QHeaderView::isSectionHidden(int logicalIndex) const
       
   943 {
       
   944     Q_D(const QHeaderView);
       
   945     d->executePostedLayout();
       
   946     if (logicalIndex >= d->sectionHidden.count() || logicalIndex < 0 || logicalIndex >= d->sectionCount)
       
   947         return false;
       
   948     int visual = visualIndex(logicalIndex);
       
   949     Q_ASSERT(visual != -1);
       
   950     return d->sectionHidden.testBit(visual);
       
   951 }
       
   952 
       
   953 /*!
       
   954     \since 4.1
       
   955 
       
   956     Returns the number of sections in the header that has been hidden.
       
   957 
       
   958     \sa setSectionHidden(), isSectionHidden()
       
   959 */
       
   960 int QHeaderView::hiddenSectionCount() const
       
   961 {
       
   962     Q_D(const QHeaderView);
       
   963     return d->hiddenSectionSize.count();
       
   964 }
       
   965 
       
   966 /*!
       
   967   If \a hide is true the section specified by \a logicalIndex is hidden;
       
   968   otherwise the section is shown.
       
   969 
       
   970   \sa isSectionHidden(), hiddenSectionCount()
       
   971 */
       
   972 
       
   973 void QHeaderView::setSectionHidden(int logicalIndex, bool hide)
       
   974 {
       
   975     Q_D(QHeaderView);
       
   976     if (logicalIndex < 0 || logicalIndex >= count())
       
   977         return;
       
   978 
       
   979     d->executePostedLayout();
       
   980     int visual = visualIndex(logicalIndex);
       
   981     Q_ASSERT(visual != -1);
       
   982     if (hide == d->isVisualIndexHidden(visual))
       
   983         return;
       
   984     if (hide) {
       
   985         int size = d->headerSectionSize(visual);
       
   986         if (!d->hasAutoResizeSections())
       
   987             resizeSection(logicalIndex, 0);
       
   988         d->hiddenSectionSize.insert(logicalIndex, size);
       
   989         if (d->sectionHidden.count() < count())
       
   990             d->sectionHidden.resize(count());
       
   991         d->sectionHidden.setBit(visual, true);
       
   992         if (d->hasAutoResizeSections())
       
   993             d->doDelayedResizeSections();
       
   994     } else {
       
   995         int size = d->hiddenSectionSize.value(logicalIndex, d->defaultSectionSize);
       
   996         d->hiddenSectionSize.remove(logicalIndex);
       
   997         if (d->hiddenSectionSize.isEmpty()) {
       
   998             d->sectionHidden.clear();
       
   999         } else {
       
  1000             Q_ASSERT(visual <= d->sectionHidden.count());
       
  1001             d->sectionHidden.setBit(visual, false);
       
  1002         }
       
  1003         resizeSection(logicalIndex, size);
       
  1004     }
       
  1005 }
       
  1006 
       
  1007 /*!
       
  1008     Returns the number of sections in the header.
       
  1009 
       
  1010     \sa  sectionCountChanged(), length()
       
  1011 */
       
  1012 
       
  1013 int QHeaderView::count() const
       
  1014 {
       
  1015     Q_D(const QHeaderView);
       
  1016     //Q_ASSERT(d->sectionCount == d->headerSectionCount());
       
  1017     // ### this may affect the lazy layout
       
  1018     d->executePostedLayout();
       
  1019     return d->sectionCount;
       
  1020 }
       
  1021 
       
  1022 /*!
       
  1023     Returns the visual index position of the section specified by the given
       
  1024     \a logicalIndex, or -1 otherwise.
       
  1025 
       
  1026     Hidden sections still have valid visual indexes.
       
  1027 
       
  1028     \sa logicalIndex()
       
  1029 */
       
  1030 
       
  1031 int QHeaderView::visualIndex(int logicalIndex) const
       
  1032 {
       
  1033     Q_D(const QHeaderView);
       
  1034     if (logicalIndex < 0)
       
  1035         return -1;
       
  1036     d->executePostedLayout();
       
  1037     if (d->visualIndices.isEmpty()) { // nothing has been moved, so we have no mapping
       
  1038         if (logicalIndex < d->sectionCount)
       
  1039             return logicalIndex;
       
  1040     } else if (logicalIndex < d->visualIndices.count()) {
       
  1041         int visual = d->visualIndices.at(logicalIndex);
       
  1042         Q_ASSERT(visual < d->sectionCount);
       
  1043         return visual;
       
  1044     }
       
  1045     return -1;
       
  1046 }
       
  1047 
       
  1048 /*!
       
  1049     Returns the logicalIndex for the section at the given \a visualIndex
       
  1050     position, or -1 if visualIndex < 0 or visualIndex >= QHeaderView::count().
       
  1051 
       
  1052     Note that the visualIndex is not affected by hidden sections.
       
  1053 
       
  1054     \sa visualIndex(), sectionPosition()
       
  1055 */
       
  1056 
       
  1057 int QHeaderView::logicalIndex(int visualIndex) const
       
  1058 {
       
  1059     Q_D(const QHeaderView);
       
  1060     if (visualIndex < 0 || visualIndex >= d->sectionCount)
       
  1061         return -1;
       
  1062     return d->logicalIndex(visualIndex);
       
  1063 }
       
  1064 
       
  1065 /*!
       
  1066     If \a movable is true, the header may be moved by the user; otherwise it
       
  1067     is fixed in place.
       
  1068 
       
  1069     \sa isMovable(), sectionMoved()
       
  1070 */
       
  1071 
       
  1072 // ### Qt 5: change to setSectionsMovable()
       
  1073 void QHeaderView::setMovable(bool movable)
       
  1074 {
       
  1075     Q_D(QHeaderView);
       
  1076     d->movableSections = movable;
       
  1077 }
       
  1078 
       
  1079 /*!
       
  1080     Returns true if the header can be moved by the user; otherwise returns
       
  1081     false.
       
  1082 
       
  1083     \sa setMovable()
       
  1084 */
       
  1085 
       
  1086 // ### Qt 5: change to sectionsMovable()
       
  1087 bool QHeaderView::isMovable() const
       
  1088 {
       
  1089     Q_D(const QHeaderView);
       
  1090     return d->movableSections;
       
  1091 }
       
  1092 
       
  1093 /*!
       
  1094     If \a clickable is true, the header will respond to single clicks.
       
  1095 
       
  1096     \sa isClickable(), sectionClicked(), sectionPressed(),
       
  1097     setSortIndicatorShown()
       
  1098 */
       
  1099 
       
  1100 // ### Qt 5: change to setSectionsClickable()
       
  1101 void QHeaderView::setClickable(bool clickable)
       
  1102 {
       
  1103     Q_D(QHeaderView);
       
  1104     d->clickableSections = clickable;
       
  1105 }
       
  1106 
       
  1107 /*!
       
  1108     Returns true if the header is clickable; otherwise returns false. A
       
  1109     clickable header could be set up to allow the user to change the
       
  1110     representation of the data in the view related to the header.
       
  1111 
       
  1112     \sa setClickable()
       
  1113 */
       
  1114 
       
  1115 // ### Qt 5: change to sectionsClickable()
       
  1116 bool QHeaderView::isClickable() const
       
  1117 {
       
  1118     Q_D(const QHeaderView);
       
  1119     return d->clickableSections;
       
  1120 }
       
  1121 
       
  1122 void QHeaderView::setHighlightSections(bool highlight)
       
  1123 {
       
  1124     Q_D(QHeaderView);
       
  1125     d->highlightSelected = highlight;
       
  1126 }
       
  1127 
       
  1128 bool QHeaderView::highlightSections() const
       
  1129 {
       
  1130     Q_D(const QHeaderView);
       
  1131     return d->highlightSelected;
       
  1132 }
       
  1133 
       
  1134 /*!
       
  1135     Sets the constraints on how the header can be resized to those described
       
  1136     by the given \a mode.
       
  1137 
       
  1138     \sa resizeMode(), length(), sectionResized(), sectionAutoResize()
       
  1139 */
       
  1140 
       
  1141 void QHeaderView::setResizeMode(ResizeMode mode)
       
  1142 {
       
  1143     Q_D(QHeaderView);
       
  1144     initializeSections();
       
  1145     d->stretchSections = (mode == Stretch ? count() : 0);
       
  1146     d->contentsSections =  (mode == ResizeToContents ? count() : 0);
       
  1147     d->setGlobalHeaderResizeMode(mode);
       
  1148     if (d->hasAutoResizeSections())
       
  1149         d->doDelayedResizeSections(); // section sizes may change as a result of the new mode
       
  1150 }
       
  1151 
       
  1152 /*!
       
  1153     \overload
       
  1154 
       
  1155     Sets the constraints on how the section specified by \a logicalIndex in
       
  1156     the header can be resized to those described by the given \a mode. The logical
       
  1157     index should exist at the time this function is called.
       
  1158 
       
  1159     \note This setting will be ignored for the last section if the stretchLastSection
       
  1160     property is set to true. This is the default for the horizontal headers provided
       
  1161     by QTreeView.
       
  1162 
       
  1163     \sa setStretchLastSection()
       
  1164 */
       
  1165 
       
  1166 // ### Qt 5: change to setSectionResizeMode()
       
  1167 void QHeaderView::setResizeMode(int logicalIndex, ResizeMode mode)
       
  1168 {
       
  1169     Q_D(QHeaderView);
       
  1170     int visual = visualIndex(logicalIndex);
       
  1171     Q_ASSERT(visual != -1);
       
  1172 
       
  1173     ResizeMode old = d->headerSectionResizeMode(visual);
       
  1174     d->setHeaderSectionResizeMode(visual, mode);
       
  1175 
       
  1176     if (mode == Stretch && old != Stretch)
       
  1177         ++d->stretchSections;
       
  1178     else if (mode == ResizeToContents && old != ResizeToContents)
       
  1179         ++d->contentsSections;
       
  1180     else if (mode != Stretch && old == Stretch)
       
  1181         --d->stretchSections;
       
  1182     else if (mode != ResizeToContents && old == ResizeToContents)
       
  1183         --d->contentsSections;
       
  1184 
       
  1185     if (d->hasAutoResizeSections() && d->state == QHeaderViewPrivate::NoState)
       
  1186         d->doDelayedResizeSections(); // section sizes may change as a result of the new mode
       
  1187 }
       
  1188 
       
  1189 /*!
       
  1190     Returns the resize mode that applies to the section specified by the given
       
  1191     \a logicalIndex.
       
  1192 
       
  1193     \sa setResizeMode()
       
  1194 */
       
  1195 
       
  1196 QHeaderView::ResizeMode QHeaderView::resizeMode(int logicalIndex) const
       
  1197 {
       
  1198     Q_D(const QHeaderView);
       
  1199     int visual = visualIndex(logicalIndex);
       
  1200     if (visual == -1)
       
  1201         return Fixed; //the default value
       
  1202     return d->headerSectionResizeMode(visual);
       
  1203 }
       
  1204 
       
  1205 /*!
       
  1206     \since 4.1
       
  1207 
       
  1208     Returns the number of sections that are set to resize mode stretch. In
       
  1209     views, this can be used to see if the headerview needs to resize the
       
  1210     sections when the view's geometry changes.
       
  1211 
       
  1212     \sa stretchLastSection, resizeMode()
       
  1213 */
       
  1214 
       
  1215 int QHeaderView::stretchSectionCount() const
       
  1216 {
       
  1217     Q_D(const QHeaderView);
       
  1218     return d->stretchSections;
       
  1219 }
       
  1220 
       
  1221 /*!
       
  1222   \property QHeaderView::showSortIndicator
       
  1223   \brief whether the sort indicator is shown
       
  1224 
       
  1225   By default, this property is false.
       
  1226 
       
  1227   \sa setClickable()
       
  1228 */
       
  1229 
       
  1230 void QHeaderView::setSortIndicatorShown(bool show)
       
  1231 {
       
  1232     Q_D(QHeaderView);
       
  1233     if (d->sortIndicatorShown == show)
       
  1234         return;
       
  1235 
       
  1236     d->sortIndicatorShown = show;
       
  1237 
       
  1238     if (sortIndicatorSection() < 0 || sortIndicatorSection() > count())
       
  1239         return;
       
  1240 
       
  1241     if (d->headerSectionResizeMode(sortIndicatorSection()) == ResizeToContents)
       
  1242         resizeSections();
       
  1243 
       
  1244     d->viewport->update();
       
  1245 }
       
  1246 
       
  1247 bool QHeaderView::isSortIndicatorShown() const
       
  1248 {
       
  1249     Q_D(const QHeaderView);
       
  1250     return d->sortIndicatorShown;
       
  1251 }
       
  1252 
       
  1253 /*!
       
  1254     Sets the sort indicator for the section specified by the given
       
  1255     \a logicalIndex in the direction specified by \a order, and removes the
       
  1256     sort indicator from any other section that was showing it.
       
  1257 
       
  1258     \a logicalIndex may be -1, in which case no sort indicator will be shown
       
  1259     and the model will return to its natural, unsorted order. Note that not
       
  1260     all models support this and may even crash in this case.
       
  1261 
       
  1262     \sa sortIndicatorSection() sortIndicatorOrder()
       
  1263 */
       
  1264 
       
  1265 void QHeaderView::setSortIndicator(int logicalIndex, Qt::SortOrder order)
       
  1266 {
       
  1267     Q_D(QHeaderView);
       
  1268 
       
  1269     // This is so that people can set the position of the sort indicator before the fill the model
       
  1270     int old = d->sortIndicatorSection;
       
  1271     d->sortIndicatorSection = logicalIndex;
       
  1272     d->sortIndicatorOrder = order;
       
  1273 
       
  1274     if (logicalIndex >= d->sectionCount) {
       
  1275         emit sortIndicatorChanged(logicalIndex, order);
       
  1276         return; // nothing to do
       
  1277     }
       
  1278 
       
  1279     if (old != logicalIndex
       
  1280         && ((logicalIndex >= 0 && resizeMode(logicalIndex) == ResizeToContents)
       
  1281             || old >= d->sectionCount || (old >= 0 && resizeMode(old) == ResizeToContents))) {
       
  1282         resizeSections();
       
  1283         d->viewport->update();
       
  1284     } else {
       
  1285         if (old >= 0 && old != logicalIndex)
       
  1286             updateSection(old);
       
  1287         if (logicalIndex >= 0)
       
  1288             updateSection(logicalIndex);
       
  1289     }
       
  1290 
       
  1291     emit sortIndicatorChanged(logicalIndex, order);
       
  1292 }
       
  1293 
       
  1294 /*!
       
  1295     Returns the logical index of the section that has a sort indicator.
       
  1296     By default this is section 0.
       
  1297 
       
  1298     \sa setSortIndicator() sortIndicatorOrder() setSortIndicatorShown()
       
  1299 */
       
  1300 
       
  1301 int QHeaderView::sortIndicatorSection() const
       
  1302 {
       
  1303     Q_D(const QHeaderView);
       
  1304     return d->sortIndicatorSection;
       
  1305 }
       
  1306 
       
  1307 /*!
       
  1308     Returns the order for the sort indicator. If no section has a sort
       
  1309     indicator the return value of this function is undefined.
       
  1310 
       
  1311     \sa setSortIndicator() sortIndicatorSection()
       
  1312 */
       
  1313 
       
  1314 Qt::SortOrder QHeaderView::sortIndicatorOrder() const
       
  1315 {
       
  1316     Q_D(const QHeaderView);
       
  1317     return d->sortIndicatorOrder;
       
  1318 }
       
  1319 
       
  1320 /*!
       
  1321     \property QHeaderView::stretchLastSection
       
  1322     \brief whether the last visible section in the header takes up all the
       
  1323     available space
       
  1324 
       
  1325     The default value is false.
       
  1326 
       
  1327     \note The horizontal headers provided by QTreeView are configured with this
       
  1328     property set to true, ensuring that the view does not waste any of the
       
  1329     space assigned to it for its header. If this value is set to true, this
       
  1330     property will override the resize mode set on the last section in the
       
  1331     header.
       
  1332 
       
  1333     \sa setResizeMode()
       
  1334 */
       
  1335 bool QHeaderView::stretchLastSection() const
       
  1336 {
       
  1337     Q_D(const QHeaderView);
       
  1338     return d->stretchLastSection;
       
  1339 }
       
  1340 
       
  1341 void QHeaderView::setStretchLastSection(bool stretch)
       
  1342 {
       
  1343     Q_D(QHeaderView);
       
  1344     d->stretchLastSection = stretch;
       
  1345     if (d->state != QHeaderViewPrivate::NoState)
       
  1346         return;
       
  1347     if (stretch)
       
  1348         resizeSections();
       
  1349     else if (count())
       
  1350         resizeSection(count() - 1, d->defaultSectionSize);
       
  1351 }
       
  1352 
       
  1353 /*!
       
  1354     \since 4.2
       
  1355     \property QHeaderView::cascadingSectionResizes
       
  1356     \brief whether interactive resizing will be cascaded to the following
       
  1357     sections once the section being resized by the user has reached its
       
  1358     minimum size
       
  1359 
       
  1360     This property only affects sections that have \l Interactive as their
       
  1361     resize mode.
       
  1362 
       
  1363     The default value is false.
       
  1364 
       
  1365     \sa setResizeMode()
       
  1366 */
       
  1367 bool QHeaderView::cascadingSectionResizes() const
       
  1368 {
       
  1369     Q_D(const QHeaderView);
       
  1370     return d->cascadingResizing;
       
  1371 }
       
  1372 
       
  1373 void QHeaderView::setCascadingSectionResizes(bool enable)
       
  1374 {
       
  1375     Q_D(QHeaderView);
       
  1376     d->cascadingResizing = enable;
       
  1377 }
       
  1378 
       
  1379 /*!
       
  1380     \property QHeaderView::defaultSectionSize
       
  1381     \brief the default size of the header sections before resizing.
       
  1382 
       
  1383     This property only affects sections that have \l Interactive or \l Fixed
       
  1384     as their resize mode.
       
  1385 
       
  1386     \sa setResizeMode() minimumSectionSize
       
  1387 */
       
  1388 int QHeaderView::defaultSectionSize() const
       
  1389 {
       
  1390     Q_D(const QHeaderView);
       
  1391     return d->defaultSectionSize;
       
  1392 }
       
  1393 
       
  1394 void QHeaderView::setDefaultSectionSize(int size)
       
  1395 {
       
  1396     Q_D(QHeaderView);
       
  1397     d->setDefaultSectionSize(size);
       
  1398 }
       
  1399 
       
  1400 /*!
       
  1401     \since 4.2
       
  1402     \property QHeaderView::minimumSectionSize
       
  1403     \brief the minimum size of the header sections.
       
  1404 
       
  1405     The minimum section size is the smallest section size allowed. If the
       
  1406     minimum section size is set to -1, QHeaderView will use the maximum of
       
  1407     the \l{QApplication::globalStrut()}{global strut} or the
       
  1408     \l{fontMetrics()}{font metrics} size.
       
  1409 
       
  1410     This property is honored by all \l{ResizeMode}{resize modes}.
       
  1411 
       
  1412     \sa setResizeMode() defaultSectionSize
       
  1413 */
       
  1414 int QHeaderView::minimumSectionSize() const
       
  1415 {
       
  1416     Q_D(const QHeaderView);
       
  1417     if (d->minimumSectionSize == -1) {
       
  1418         QSize strut = QApplication::globalStrut();
       
  1419         int margin = style()->pixelMetric(QStyle::PM_HeaderMargin, 0, this);
       
  1420         if (d->orientation == Qt::Horizontal)
       
  1421             return qMax(strut.width(), (fontMetrics().maxWidth() + margin));
       
  1422         return qMax(strut.height(), (fontMetrics().height() + margin));
       
  1423     }
       
  1424     return d->minimumSectionSize;
       
  1425 }
       
  1426 
       
  1427 void QHeaderView::setMinimumSectionSize(int size)
       
  1428 {
       
  1429     Q_D(QHeaderView);
       
  1430     d->minimumSectionSize = size;
       
  1431 }
       
  1432 
       
  1433 /*!
       
  1434     \since 4.1
       
  1435     \property QHeaderView::defaultAlignment
       
  1436     \brief the default alignment of the text in each header section
       
  1437 */
       
  1438 
       
  1439 Qt::Alignment QHeaderView::defaultAlignment() const
       
  1440 {
       
  1441     Q_D(const QHeaderView);
       
  1442     return d->defaultAlignment;
       
  1443 }
       
  1444 
       
  1445 void QHeaderView::setDefaultAlignment(Qt::Alignment alignment)
       
  1446 {
       
  1447     Q_D(QHeaderView);
       
  1448     if (d->defaultAlignment == alignment)
       
  1449         return;
       
  1450 
       
  1451     d->defaultAlignment = alignment;
       
  1452     d->viewport->update();
       
  1453 }
       
  1454 
       
  1455 /*!
       
  1456     \internal
       
  1457 */
       
  1458 void QHeaderView::doItemsLayout()
       
  1459 {
       
  1460     initializeSections();
       
  1461     QAbstractItemView::doItemsLayout();
       
  1462 }
       
  1463 
       
  1464 /*!
       
  1465     Returns true if sections in the header has been moved; otherwise returns
       
  1466     false;
       
  1467 
       
  1468     \sa moveSection()
       
  1469 */
       
  1470 bool QHeaderView::sectionsMoved() const
       
  1471 {
       
  1472     Q_D(const QHeaderView);
       
  1473     return !d->visualIndices.isEmpty();
       
  1474 }
       
  1475 
       
  1476 /*!
       
  1477     \since 4.1
       
  1478 
       
  1479     Returns true if sections in the header has been hidden; otherwise returns
       
  1480     false;
       
  1481 
       
  1482     \sa setSectionHidden()
       
  1483 */
       
  1484 bool QHeaderView::sectionsHidden() const
       
  1485 {
       
  1486     Q_D(const QHeaderView);
       
  1487     return !d->hiddenSectionSize.isEmpty();
       
  1488 }
       
  1489 
       
  1490 #ifndef QT_NO_DATASTREAM
       
  1491 /*!
       
  1492     \since 4.3
       
  1493 
       
  1494     Saves the current state of this header view.
       
  1495 
       
  1496     To restore the saved state, pass the return value to restoreState().
       
  1497 
       
  1498     \sa restoreState()
       
  1499 */
       
  1500 QByteArray QHeaderView::saveState() const
       
  1501 {
       
  1502     Q_D(const QHeaderView);
       
  1503     QByteArray data;
       
  1504     QDataStream stream(&data, QIODevice::WriteOnly);
       
  1505     stream << QHeaderViewPrivate::VersionMarker;
       
  1506     stream << 0; // current version is 0
       
  1507     d->write(stream);
       
  1508     return data;
       
  1509 }
       
  1510 
       
  1511 /*!
       
  1512     \since 4.3
       
  1513     Restores the \a state of this header view.
       
  1514     This function returns \c true if the state was restored; otherwise returns
       
  1515     false.
       
  1516 
       
  1517     \sa saveState()
       
  1518 */
       
  1519 bool QHeaderView::restoreState(const QByteArray &state)
       
  1520 {
       
  1521     Q_D(QHeaderView);
       
  1522     if (state.isEmpty())
       
  1523         return false;
       
  1524     QByteArray data = state;
       
  1525     QDataStream stream(&data, QIODevice::ReadOnly);
       
  1526     int marker;
       
  1527     int ver;
       
  1528     stream >> marker;
       
  1529     stream >> ver;
       
  1530     if (stream.status() != QDataStream::Ok
       
  1531         || marker != QHeaderViewPrivate::VersionMarker
       
  1532         || ver != 0) // current version is 0
       
  1533         return false;
       
  1534 
       
  1535     if (d->read(stream)) {
       
  1536         emit sortIndicatorChanged(d->sortIndicatorSection, d->sortIndicatorOrder );
       
  1537         d->viewport->update();
       
  1538         return true;
       
  1539     }
       
  1540     return false;
       
  1541 }
       
  1542 #endif // QT_NO_DATASTREAM
       
  1543 
       
  1544 /*!
       
  1545   \reimp
       
  1546 */
       
  1547 void QHeaderView::reset()
       
  1548 {
       
  1549     QAbstractItemView::reset();
       
  1550     // it would be correct to call clear, but some apps rely
       
  1551     // on the header keeping the sections, even after calling reset
       
  1552     //d->clear();
       
  1553     initializeSections();
       
  1554 }
       
  1555 
       
  1556 /*!
       
  1557     Updates the changed header sections with the given \a orientation, from
       
  1558     \a logicalFirst to \a logicalLast inclusive.
       
  1559 */
       
  1560 void QHeaderView::headerDataChanged(Qt::Orientation orientation, int logicalFirst, int logicalLast)
       
  1561 {
       
  1562     Q_D(QHeaderView);
       
  1563     if (d->orientation != orientation)
       
  1564         return;
       
  1565 
       
  1566     if (logicalFirst < 0 || logicalLast < 0 || logicalFirst >= count() || logicalLast >= count())
       
  1567         return;
       
  1568 
       
  1569     d->invalidateCachedSizeHint();
       
  1570 
       
  1571     int firstVisualIndex = INT_MAX, lastVisualIndex = -1;
       
  1572 
       
  1573     for (int section = logicalFirst; section <= logicalLast; ++section) {
       
  1574         const int visual = visualIndex(section);
       
  1575         firstVisualIndex = qMin(firstVisualIndex, visual);
       
  1576         lastVisualIndex =  qMax(lastVisualIndex,  visual);
       
  1577     }
       
  1578 
       
  1579     d->executePostedResize();
       
  1580     const int first = d->headerSectionPosition(firstVisualIndex),
       
  1581               last = d->headerSectionPosition(lastVisualIndex)
       
  1582                         + d->headerSectionSize(lastVisualIndex);
       
  1583 
       
  1584     if (orientation == Qt::Horizontal) {
       
  1585         d->viewport->update(first, 0, last - first, d->viewport->height());
       
  1586     } else {
       
  1587         d->viewport->update(0, first, d->viewport->width(), last - first);
       
  1588     }
       
  1589 }
       
  1590 
       
  1591 /*!
       
  1592     \internal
       
  1593     \since 4.2
       
  1594 
       
  1595     Updates the section specified by the given \a logicalIndex.
       
  1596 */
       
  1597 
       
  1598 void QHeaderView::updateSection(int logicalIndex)
       
  1599 {
       
  1600     Q_D(QHeaderView);
       
  1601     if (d->orientation == Qt::Horizontal)
       
  1602         d->viewport->update(QRect(sectionViewportPosition(logicalIndex),
       
  1603                                   0, sectionSize(logicalIndex), d->viewport->height()));
       
  1604     else
       
  1605         d->viewport->update(QRect(0, sectionViewportPosition(logicalIndex),
       
  1606                                   d->viewport->width(), sectionSize(logicalIndex)));
       
  1607 }
       
  1608 
       
  1609 /*!
       
  1610     Resizes the sections according to their size hints. Normally, you do not
       
  1611     have to call this function.
       
  1612 */
       
  1613 
       
  1614 void QHeaderView::resizeSections()
       
  1615 {
       
  1616     Q_D(QHeaderView);
       
  1617     if (d->hasAutoResizeSections())
       
  1618         d->resizeSections(Interactive, false); // no global resize mode
       
  1619 }
       
  1620 
       
  1621 /*!
       
  1622     This slot is called when sections are inserted into the \a parent.
       
  1623     \a logicalFirst and \a logicalLast indices signify where the new sections
       
  1624     were inserted.
       
  1625 
       
  1626     If only one section is inserted, \a logicalFirst and \a logicalLast will
       
  1627     be the same.
       
  1628 */
       
  1629 
       
  1630 void QHeaderView::sectionsInserted(const QModelIndex &parent,
       
  1631                                    int logicalFirst, int logicalLast)
       
  1632 {
       
  1633     Q_D(QHeaderView);
       
  1634     if (parent != d->root)
       
  1635         return; // we only handle changes in the top level
       
  1636     int oldCount = d->sectionCount;
       
  1637 
       
  1638     d->invalidateCachedSizeHint();
       
  1639 
       
  1640     // add the new sections
       
  1641     int insertAt = 0;
       
  1642     for (int spanStart = 0; insertAt < d->sectionSpans.count() && spanStart < logicalFirst; ++insertAt)
       
  1643         spanStart += d->sectionSpans.at(insertAt).count;
       
  1644 
       
  1645     int insertCount = logicalLast - logicalFirst + 1;
       
  1646     d->sectionCount += insertCount;
       
  1647 
       
  1648     if (d->sectionSpans.isEmpty() || insertAt >= d->sectionSpans.count()) {
       
  1649         int insertLength = d->defaultSectionSize * insertCount;
       
  1650         d->length += insertLength;
       
  1651         QHeaderViewPrivate::SectionSpan span(insertLength, insertCount, d->globalResizeMode);
       
  1652         d->sectionSpans.append(span);
       
  1653     } else if ((d->sectionSpans.at(insertAt).sectionSize() == d->defaultSectionSize)
       
  1654                && d->sectionSpans.at(insertAt).resizeMode == d->globalResizeMode) {
       
  1655         // add the new sections to an existing span
       
  1656         int insertLength = d->sectionSpans.at(insertAt).sectionSize() * insertCount;
       
  1657         d->length += insertLength;
       
  1658         d->sectionSpans[insertAt].size += insertLength;
       
  1659         d->sectionSpans[insertAt].count += insertCount;
       
  1660     } else {
       
  1661         // separate them out into their own span
       
  1662         int insertLength = d->defaultSectionSize * insertCount;
       
  1663         d->length += insertLength;
       
  1664         QHeaderViewPrivate::SectionSpan span(insertLength, insertCount, d->globalResizeMode);
       
  1665         d->sectionSpans.insert(insertAt, span);
       
  1666     }
       
  1667 
       
  1668     // update sorting column
       
  1669     if (d->sortIndicatorSection >= logicalFirst)
       
  1670         d->sortIndicatorSection += insertCount;
       
  1671 
       
  1672     // update resize mode section counts
       
  1673     if (d->globalResizeMode == Stretch)
       
  1674         d->stretchSections = d->sectionCount;
       
  1675     else if (d->globalResizeMode == ResizeToContents)
       
  1676         d->contentsSections = d->sectionCount;
       
  1677 
       
  1678     // clear selection cache
       
  1679     d->sectionSelected.clear();
       
  1680 
       
  1681     // update mapping
       
  1682     if (!d->visualIndices.isEmpty() && !d->logicalIndices.isEmpty()) {
       
  1683         Q_ASSERT(d->visualIndices.count() == d->logicalIndices.count());
       
  1684         int mappingCount = d->visualIndices.count();
       
  1685         for (int i = 0; i < mappingCount; ++i) {
       
  1686             if (d->visualIndices.at(i) >= logicalFirst)
       
  1687                d->visualIndices[i] += insertCount;
       
  1688             if (d->logicalIndices.at(i) >= logicalFirst)
       
  1689                 d->logicalIndices[i] += insertCount;
       
  1690         }
       
  1691         for (int j = logicalFirst; j <= logicalLast; ++j) {
       
  1692             d->visualIndices.insert(j, j);
       
  1693             d->logicalIndices.insert(j, j);
       
  1694         }
       
  1695     }
       
  1696 
       
  1697     // insert sections into sectionsHidden
       
  1698     if (!d->sectionHidden.isEmpty()) {
       
  1699         QBitArray sectionHidden(d->sectionHidden);
       
  1700         sectionHidden.resize(sectionHidden.count() + insertCount);
       
  1701         //sectionHidden.fill(false, logicalFirst, logicalLast + 1);
       
  1702         for (int i = logicalFirst; i <= logicalLast; ++i)
       
  1703             // visual == logical in this range (see previous block)
       
  1704             sectionHidden.setBit(i, false);
       
  1705         for (int j = logicalLast + 1; j < sectionHidden.count(); ++j)
       
  1706             sectionHidden.setBit(d->visualIndex(j),
       
  1707                     d->sectionHidden.testBit(d->visualIndex(j - insertCount)));
       
  1708         d->sectionHidden = sectionHidden;
       
  1709     }
       
  1710 
       
  1711     // insert sections into hiddenSectionSize
       
  1712     QHash<int, int> newHiddenSectionSize; // from logical index to section size
       
  1713     for (int i = 0; i < logicalFirst; ++i)
       
  1714         if (isSectionHidden(i))
       
  1715             newHiddenSectionSize[i] = d->hiddenSectionSize[i];
       
  1716     for (int j = logicalLast + 1; j < d->sectionCount; ++j)
       
  1717         if (isSectionHidden(j))
       
  1718             newHiddenSectionSize[j] = d->hiddenSectionSize[j - insertCount];
       
  1719     d->hiddenSectionSize = newHiddenSectionSize;
       
  1720 
       
  1721     d->doDelayedResizeSections();
       
  1722     emit sectionCountChanged(oldCount, count());
       
  1723 
       
  1724     // if the new sections were not updated by resizing, we need to update now
       
  1725     if (!d->hasAutoResizeSections())
       
  1726         d->viewport->update();
       
  1727 }
       
  1728 
       
  1729 /*!
       
  1730     This slot is called when sections are removed from the \a parent.
       
  1731     \a logicalFirst and \a logicalLast signify where the sections were removed.
       
  1732 
       
  1733     If only one section is removed, \a logicalFirst and \a logicalLast will
       
  1734     be the same.
       
  1735 */
       
  1736 
       
  1737 void QHeaderView::sectionsAboutToBeRemoved(const QModelIndex &parent,
       
  1738                                            int logicalFirst, int logicalLast)
       
  1739 {
       
  1740     Q_UNUSED(parent);
       
  1741     Q_UNUSED(logicalFirst);
       
  1742     Q_UNUSED(logicalLast);
       
  1743 }
       
  1744 
       
  1745 void QHeaderViewPrivate::updateHiddenSections(int logicalFirst, int logicalLast)
       
  1746 {
       
  1747     Q_Q(QHeaderView);
       
  1748     const int changeCount = logicalLast - logicalFirst + 1;
       
  1749 
       
  1750     // remove sections from hiddenSectionSize
       
  1751     QHash<int, int> newHiddenSectionSize; // from logical index to section size
       
  1752     for (int i = 0; i < logicalFirst; ++i)
       
  1753         if (q->isSectionHidden(i))
       
  1754             newHiddenSectionSize[i] = hiddenSectionSize[i];
       
  1755     for (int j = logicalLast + 1; j < sectionCount; ++j)
       
  1756         if (q->isSectionHidden(j))
       
  1757             newHiddenSectionSize[j - changeCount] = hiddenSectionSize[j];
       
  1758     hiddenSectionSize = newHiddenSectionSize;
       
  1759 
       
  1760     // remove sections from sectionsHidden
       
  1761     if (!sectionHidden.isEmpty()) {
       
  1762         const int newsize = qMin(sectionCount - changeCount, sectionHidden.size());
       
  1763         QBitArray newSectionHidden(newsize);
       
  1764         for (int j = 0, k = 0; j < sectionHidden.size(); ++j) {
       
  1765             const int logical = logicalIndex(j);
       
  1766             if (logical < logicalFirst || logical > logicalLast) {
       
  1767                 newSectionHidden[k++] = sectionHidden[j];
       
  1768             }
       
  1769         }
       
  1770         sectionHidden = newSectionHidden;
       
  1771     }
       
  1772 }
       
  1773 
       
  1774 void QHeaderViewPrivate::_q_sectionsRemoved(const QModelIndex &parent,
       
  1775                                             int logicalFirst, int logicalLast)
       
  1776 {
       
  1777     Q_Q(QHeaderView);
       
  1778     if (parent != root)
       
  1779         return; // we only handle changes in the top level
       
  1780     if (qMin(logicalFirst, logicalLast) < 0
       
  1781         || qMax(logicalLast, logicalFirst) >= sectionCount)
       
  1782         return;
       
  1783     int oldCount = q->count();
       
  1784     int changeCount = logicalLast - logicalFirst + 1;
       
  1785 
       
  1786     updateHiddenSections(logicalFirst, logicalLast);
       
  1787 
       
  1788     if (visualIndices.isEmpty() && logicalIndices.isEmpty()) {
       
  1789         //Q_ASSERT(headerSectionCount() == sectionCount);
       
  1790         removeSectionsFromSpans(logicalFirst, logicalLast);
       
  1791     } else {
       
  1792         for (int l = logicalLast; l >= logicalFirst; --l) {
       
  1793             int visual = visualIndices.at(l);
       
  1794             for (int v = 0; v < sectionCount; ++v) {
       
  1795                 if (v >= logicalIndices.count())
       
  1796                     continue; // the section doesn't exist
       
  1797                 if (v > visual) {
       
  1798                     int logical = logicalIndices.at(v);
       
  1799                     --(visualIndices[logical]);
       
  1800                 }
       
  1801                 if (logicalIndex(v) > l) // no need to move the positions before l
       
  1802                     --(logicalIndices[v]);
       
  1803             }
       
  1804             logicalIndices.remove(visual);
       
  1805             visualIndices.remove(l);
       
  1806             //Q_ASSERT(headerSectionCount() == sectionCount);
       
  1807             removeSectionsFromSpans(visual, visual);
       
  1808         }
       
  1809         // ### handle sectionSelection, sectionHidden
       
  1810     }
       
  1811     sectionCount -= changeCount;
       
  1812 
       
  1813     // update sorting column
       
  1814     if (sortIndicatorSection >= logicalFirst) {
       
  1815         if (sortIndicatorSection <= logicalLast)
       
  1816             sortIndicatorSection = -1;
       
  1817         else
       
  1818             sortIndicatorSection -= changeCount;
       
  1819     }
       
  1820 
       
  1821     // if we only have the last section (the "end" position) left, the header is empty
       
  1822     if (sectionCount <= 0)
       
  1823         clear();
       
  1824     invalidateCachedSizeHint();
       
  1825     emit q->sectionCountChanged(oldCount, q->count());
       
  1826     viewport->update();
       
  1827 }
       
  1828 
       
  1829 void QHeaderViewPrivate::_q_layoutAboutToBeChanged()
       
  1830 {
       
  1831     //if there is no row/column we can't have mapping for columns
       
  1832     //because no QModelIndex in the model would be valid
       
  1833     // ### this is far from being bullet-proof and we would need a real system to 
       
  1834     // ### map columns or rows persistently
       
  1835     if ((orientation == Qt::Horizontal && model->rowCount(root) == 0)
       
  1836         || model->columnCount(root) == 0)
       
  1837         return;
       
  1838 
       
  1839     for (int i = 0; i < sectionHidden.count(); ++i)
       
  1840         if (sectionHidden.testBit(i)) // ### note that we are using column or row 0
       
  1841             persistentHiddenSections.append(orientation == Qt::Horizontal
       
  1842                                             ? model->index(0, logicalIndex(i), root)
       
  1843                                             : model->index(logicalIndex(i), 0, root));
       
  1844 }
       
  1845 
       
  1846 void QHeaderViewPrivate::_q_layoutChanged()
       
  1847 {
       
  1848     Q_Q(QHeaderView);
       
  1849     viewport->update();
       
  1850     if (persistentHiddenSections.isEmpty() || modelIsEmpty()) {
       
  1851         if (modelSectionCount() != sectionCount)
       
  1852             q->initializeSections();
       
  1853         persistentHiddenSections.clear();
       
  1854         return;
       
  1855     }
       
  1856     bool sectionCountChanged = false;
       
  1857     for (int i = 0; i < sectionHidden.count(); ++i) {
       
  1858         if (sectionHidden.testBit(i))
       
  1859             q->setSectionHidden(logicalIndex(i), false);
       
  1860     }
       
  1861 
       
  1862     for (int i = 0; i < persistentHiddenSections.count(); ++i) {
       
  1863         QModelIndex index = persistentHiddenSections.at(i);
       
  1864         if (index.isValid()) {
       
  1865             const int logical = (orientation == Qt::Horizontal
       
  1866                                  ? index.column()
       
  1867                                  : index.row());
       
  1868             q->setSectionHidden(logical, true);
       
  1869         } else if (!sectionCountChanged && (modelSectionCount() != sectionCount)) {
       
  1870             sectionCountChanged = true;
       
  1871             break;
       
  1872         }
       
  1873     }
       
  1874     persistentHiddenSections.clear();
       
  1875 
       
  1876     // the number of sections changed; we need to reread the state of the model
       
  1877     if (sectionCountChanged)
       
  1878         q->initializeSections();
       
  1879 }
       
  1880 
       
  1881 /*!
       
  1882   \internal
       
  1883 */
       
  1884 
       
  1885 void QHeaderView::initializeSections()
       
  1886 {
       
  1887     Q_D(QHeaderView);
       
  1888     const int oldCount = d->sectionCount;
       
  1889     const int newCount = d->modelSectionCount();
       
  1890     if (newCount <= 0) {
       
  1891             d->clear();
       
  1892             emit sectionCountChanged(oldCount, 0);
       
  1893     } else if (newCount != oldCount) {
       
  1894         const int min = qBound(0, oldCount, newCount - 1);
       
  1895         initializeSections(min, newCount - 1);
       
  1896         if (stretchLastSection()) // we've already gotten the size hint
       
  1897             d->lastSectionSize = sectionSize(logicalIndex(d->sectionCount - 1));
       
  1898 
       
  1899         //make sure we update the hidden sections
       
  1900         if (newCount < oldCount)
       
  1901             d->updateHiddenSections(0, newCount-1);
       
  1902     }
       
  1903 }
       
  1904 
       
  1905 /*!
       
  1906     \internal
       
  1907 */
       
  1908 
       
  1909 void QHeaderView::initializeSections(int start, int end)
       
  1910 {
       
  1911     Q_D(QHeaderView);
       
  1912 
       
  1913     Q_ASSERT(start >= 0);
       
  1914     Q_ASSERT(end >= 0);
       
  1915 
       
  1916     d->invalidateCachedSizeHint();
       
  1917 
       
  1918     if (end + 1 < d->sectionCount) {
       
  1919         int newCount = end + 1;
       
  1920         d->removeSectionsFromSpans(newCount, d->sectionCount);
       
  1921         if (!d->hiddenSectionSize.isEmpty()) {
       
  1922             if (d->sectionCount - newCount > d->hiddenSectionSize.count()) {
       
  1923                 for (int i = end + 1; i < d->sectionCount; ++i)
       
  1924                     d->hiddenSectionSize.remove(i);
       
  1925             } else {
       
  1926                 QHash<int, int>::iterator it = d->hiddenSectionSize.begin();
       
  1927                 while (it != d->hiddenSectionSize.end()) {
       
  1928                     if (it.key() > end)
       
  1929                         it = d->hiddenSectionSize.erase(it);
       
  1930                     else
       
  1931                         ++it;
       
  1932                 }
       
  1933             }
       
  1934         }
       
  1935     }
       
  1936 
       
  1937     int oldCount = d->sectionCount;
       
  1938     d->sectionCount = end + 1;
       
  1939 
       
  1940     if (!d->logicalIndices.isEmpty()) {
       
  1941         if (oldCount <= d->sectionCount) {
       
  1942             d->logicalIndices.resize(d->sectionCount);
       
  1943             d->visualIndices.resize(d->sectionCount);
       
  1944             for (int i = oldCount; i < d->sectionCount; ++i) {
       
  1945                 d->logicalIndices[i] = i;
       
  1946                 d->visualIndices[i] = i;
       
  1947             }
       
  1948         } else {
       
  1949             int j = 0;
       
  1950             for (int i = 0; i < oldCount; ++i) {
       
  1951                 int v = d->logicalIndices.at(i);
       
  1952                 if (v < d->sectionCount) {
       
  1953                     d->logicalIndices[j] = v;
       
  1954                     d->visualIndices[v] = j;
       
  1955                     j++;
       
  1956                 }
       
  1957             }
       
  1958             d->logicalIndices.resize(d->sectionCount);
       
  1959             d->visualIndices.resize(d->sectionCount);
       
  1960         }
       
  1961     }
       
  1962 
       
  1963     if (d->globalResizeMode == Stretch)
       
  1964         d->stretchSections = d->sectionCount;
       
  1965     else if (d->globalResizeMode == ResizeToContents)
       
  1966          d->contentsSections = d->sectionCount;
       
  1967     if (!d->sectionHidden.isEmpty())
       
  1968         d->sectionHidden.resize(d->sectionCount);
       
  1969 
       
  1970     if (d->sectionCount > oldCount)
       
  1971         d->createSectionSpan(start, end, (end - start + 1) * d->defaultSectionSize, d->globalResizeMode);
       
  1972     //Q_ASSERT(d->headerLength() == d->length);
       
  1973 
       
  1974     if (d->sectionCount != oldCount)
       
  1975         emit sectionCountChanged(oldCount,  d->sectionCount);
       
  1976     d->viewport->update();
       
  1977 }
       
  1978 
       
  1979 /*!
       
  1980   \reimp
       
  1981 */
       
  1982 
       
  1983 void QHeaderView::currentChanged(const QModelIndex &current, const QModelIndex &old)
       
  1984 {
       
  1985     Q_D(QHeaderView);
       
  1986 
       
  1987     if (d->orientation == Qt::Horizontal && current.column() != old.column()) {
       
  1988         if (old.isValid() && old.parent() == d->root)
       
  1989             d->viewport->update(QRect(sectionViewportPosition(old.column()), 0,
       
  1990                                     sectionSize(old.column()), d->viewport->height()));
       
  1991         if (current.isValid() && current.parent() == d->root)
       
  1992             d->viewport->update(QRect(sectionViewportPosition(current.column()), 0,
       
  1993                                     sectionSize(current.column()), d->viewport->height()));
       
  1994     } else if (d->orientation == Qt::Vertical && current.row() != old.row()) {
       
  1995         if (old.isValid() && old.parent() == d->root)
       
  1996             d->viewport->update(QRect(0, sectionViewportPosition(old.row()),
       
  1997                                     d->viewport->width(), sectionSize(old.row())));
       
  1998         if (current.isValid() && current.parent() == d->root)
       
  1999             d->viewport->update(QRect(0, sectionViewportPosition(current.row()),
       
  2000                                     d->viewport->width(), sectionSize(current.row())));
       
  2001     }
       
  2002 }
       
  2003 
       
  2004 
       
  2005 /*!
       
  2006   \reimp
       
  2007 */
       
  2008 
       
  2009 bool QHeaderView::event(QEvent *e)
       
  2010 {
       
  2011     Q_D(QHeaderView);
       
  2012     switch (e->type()) {
       
  2013     case QEvent::HoverEnter: {
       
  2014         QHoverEvent *he = static_cast<QHoverEvent*>(e);
       
  2015         d->hover = logicalIndexAt(he->pos());
       
  2016         if (d->hover != -1)
       
  2017             updateSection(d->hover);
       
  2018         break; }
       
  2019     case QEvent::Leave:
       
  2020     case QEvent::HoverLeave: {
       
  2021         if (d->hover != -1)
       
  2022             updateSection(d->hover);
       
  2023         d->hover = -1;
       
  2024         break; }
       
  2025     case QEvent::HoverMove: {
       
  2026         QHoverEvent *he = static_cast<QHoverEvent*>(e);
       
  2027         int oldHover = d->hover;
       
  2028         d->hover = logicalIndexAt(he->pos());
       
  2029         if (d->hover != oldHover) {
       
  2030             if (oldHover != -1)
       
  2031                 updateSection(oldHover);
       
  2032             if (d->hover != -1)
       
  2033                 updateSection(d->hover);
       
  2034         }
       
  2035         break; }
       
  2036     case QEvent::Timer: { // ### reimplement timerEvent() instead ?
       
  2037         QTimerEvent *te = static_cast<QTimerEvent*>(e);
       
  2038         if (te->timerId() == d->delayedResize.timerId()) {
       
  2039             d->delayedResize.stop();
       
  2040             resizeSections();
       
  2041         }
       
  2042         break; }
       
  2043     default:
       
  2044         break;
       
  2045     }
       
  2046     return QAbstractItemView::event(e);
       
  2047 }
       
  2048 
       
  2049 /*!
       
  2050   \reimp
       
  2051 */
       
  2052 
       
  2053 void QHeaderView::paintEvent(QPaintEvent *e)
       
  2054 {
       
  2055     Q_D(QHeaderView);
       
  2056 
       
  2057     if (count() == 0)
       
  2058         return;
       
  2059 
       
  2060     QPainter painter(d->viewport);
       
  2061     const QPoint offset = d->scrollDelayOffset;
       
  2062     QRect translatedEventRect = e->rect();
       
  2063     translatedEventRect.translate(offset);
       
  2064 
       
  2065     int start = -1;
       
  2066     int end = -1;
       
  2067     if (d->orientation == Qt::Horizontal) {
       
  2068         start = visualIndexAt(translatedEventRect.left());
       
  2069         end = visualIndexAt(translatedEventRect.right());
       
  2070     } else {
       
  2071         start = visualIndexAt(translatedEventRect.top());
       
  2072         end = visualIndexAt(translatedEventRect.bottom());
       
  2073     }
       
  2074 
       
  2075     if (d->reverse()) {
       
  2076         start = (start == -1 ? count() - 1 : start);
       
  2077         end = (end == -1 ? 0 : end);
       
  2078     } else {
       
  2079         start = (start == -1 ? 0 : start);
       
  2080         end = (end == -1 ? count() - 1 : end);
       
  2081     }
       
  2082 
       
  2083     int tmp = start;
       
  2084     start = qMin(start, end);
       
  2085     end = qMax(tmp, end);
       
  2086 
       
  2087     d->prepareSectionSelected(); // clear and resize the bit array
       
  2088 
       
  2089     QRect currentSectionRect;
       
  2090     int logical;
       
  2091     const int width = d->viewport->width();
       
  2092     const int height = d->viewport->height();
       
  2093     for (int i = start; i <= end; ++i) {
       
  2094         if (d->isVisualIndexHidden(i))
       
  2095             continue;
       
  2096         painter.save();
       
  2097         logical = logicalIndex(i);
       
  2098         if (d->orientation == Qt::Horizontal) {
       
  2099             currentSectionRect.setRect(sectionViewportPosition(logical), 0, sectionSize(logical), height);
       
  2100         } else {
       
  2101             currentSectionRect.setRect(0, sectionViewportPosition(logical), width, sectionSize(logical));
       
  2102         }
       
  2103         currentSectionRect.translate(offset);
       
  2104 
       
  2105         QVariant variant = d->model->headerData(logical, d->orientation,
       
  2106                                                 Qt::FontRole);
       
  2107         if (variant.isValid() && qVariantCanConvert<QFont>(variant)) {
       
  2108             QFont sectionFont = qvariant_cast<QFont>(variant);
       
  2109             painter.setFont(sectionFont);
       
  2110         }
       
  2111         paintSection(&painter, currentSectionRect, logical);
       
  2112         painter.restore();
       
  2113     }
       
  2114 
       
  2115     QStyleOption opt;
       
  2116     opt.init(this);
       
  2117     // Paint the area beyond where there are indexes
       
  2118     if (d->reverse()) {
       
  2119         opt.state |= QStyle::State_Horizontal;
       
  2120         if (currentSectionRect.left() > translatedEventRect.left()) {
       
  2121             opt.rect = QRect(translatedEventRect.left(), 0,
       
  2122                              currentSectionRect.left() - translatedEventRect.left(), height);
       
  2123             style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter, this);
       
  2124         }
       
  2125     } else if (currentSectionRect.right() < translatedEventRect.right()) {
       
  2126         // paint to the right
       
  2127         opt.state |= QStyle::State_Horizontal;
       
  2128         opt.rect = QRect(currentSectionRect.right() + 1, 0,
       
  2129                          translatedEventRect.right() - currentSectionRect.right(), height);
       
  2130         style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter, this);
       
  2131     } else if (currentSectionRect.bottom() < translatedEventRect.bottom()) {
       
  2132         // paint the bottom section
       
  2133         opt.state &= ~QStyle::State_Horizontal;
       
  2134         opt.rect = QRect(0, currentSectionRect.bottom() + 1,
       
  2135                          width, height - currentSectionRect.bottom() - 1);
       
  2136         style()->drawControl(QStyle::CE_HeaderEmptyArea, &opt, &painter, this);
       
  2137     }
       
  2138 
       
  2139 #if 0
       
  2140     // ### visualize section spans
       
  2141     for (int a = 0, i = 0; i < d->sectionSpans.count(); ++i) {
       
  2142         QColor color((i & 4 ? 255 : 0), (i & 2 ? 255 : 0), (i & 1 ? 255 : 0));
       
  2143         if (d->orientation == Qt::Horizontal)
       
  2144             painter.fillRect(a - d->offset, 0, d->sectionSpans.at(i).size, 4, color);
       
  2145         else
       
  2146             painter.fillRect(0, a - d->offset, 4, d->sectionSpans.at(i).size, color);
       
  2147         a += d->sectionSpans.at(i).size;
       
  2148     }
       
  2149 
       
  2150 #endif
       
  2151 }
       
  2152 
       
  2153 /*!
       
  2154   \reimp
       
  2155 */
       
  2156 
       
  2157 void QHeaderView::mousePressEvent(QMouseEvent *e)
       
  2158 {
       
  2159     Q_D(QHeaderView);
       
  2160     if (d->state != QHeaderViewPrivate::NoState || e->button() != Qt::LeftButton)
       
  2161         return;
       
  2162     int pos = d->orientation == Qt::Horizontal ? e->x() : e->y();
       
  2163     int handle = d->sectionHandleAt(pos);
       
  2164     d->originalSize = -1; // clear the stored original size
       
  2165     if (handle == -1) {
       
  2166         d->pressed = logicalIndexAt(pos);
       
  2167         if (d->clickableSections)
       
  2168             emit sectionPressed(d->pressed);
       
  2169         if (d->movableSections) {
       
  2170             d->section = d->target = d->pressed;
       
  2171             if (d->section == -1)
       
  2172                 return;
       
  2173             d->state = QHeaderViewPrivate::MoveSection;
       
  2174             d->setupSectionIndicator(d->section, pos);
       
  2175         } else if (d->clickableSections && d->pressed != -1) {
       
  2176             updateSection(d->pressed);
       
  2177             d->state = QHeaderViewPrivate::SelectSections;
       
  2178         }
       
  2179     } else if (resizeMode(handle) == Interactive) {
       
  2180         d->originalSize = sectionSize(handle);
       
  2181         d->state = QHeaderViewPrivate::ResizeSection;
       
  2182         d->section = handle;
       
  2183     }
       
  2184 
       
  2185     d->firstPos = pos;
       
  2186     d->lastPos = pos;
       
  2187 
       
  2188     d->clearCascadingSections();
       
  2189 }
       
  2190 
       
  2191 /*!
       
  2192   \reimp
       
  2193 */
       
  2194 
       
  2195 void QHeaderView::mouseMoveEvent(QMouseEvent *e)
       
  2196 {
       
  2197     Q_D(QHeaderView);
       
  2198     int pos = d->orientation == Qt::Horizontal ? e->x() : e->y();
       
  2199     if (pos < 0)
       
  2200         return;
       
  2201     if (e->buttons() == Qt::NoButton) {
       
  2202         d->state = QHeaderViewPrivate::NoState;
       
  2203         d->pressed = -1;
       
  2204     }
       
  2205     switch (d->state) {
       
  2206         case QHeaderViewPrivate::ResizeSection: {
       
  2207             Q_ASSERT(d->originalSize != -1);
       
  2208             if (d->cascadingResizing) {
       
  2209                 int delta = d->reverse() ? d->lastPos - pos : pos - d->lastPos;
       
  2210                 int visual = visualIndex(d->section);
       
  2211                 d->cascadingResize(visual, d->headerSectionSize(visual) + delta);
       
  2212             } else {
       
  2213                 int delta = d->reverse() ? d->firstPos - pos : pos - d->firstPos;
       
  2214                 resizeSection(d->section, qMax(d->originalSize + delta, minimumSectionSize()));
       
  2215             }
       
  2216             d->lastPos = pos;
       
  2217             return;
       
  2218         }
       
  2219         case QHeaderViewPrivate::MoveSection: {
       
  2220             if (qAbs(pos - d->firstPos) >= QApplication::startDragDistance()) {
       
  2221                 int indicatorCenter = (d->orientation == Qt::Horizontal
       
  2222                                        ? d->sectionIndicator->width()
       
  2223                                        : d->sectionIndicator->height()) / 2;
       
  2224                 int centerOffset = indicatorCenter - d->sectionIndicatorOffset;
       
  2225                 // This will drop the moved section to the position under the center of the indicator.
       
  2226                 // If centerOffset is 0, the section will be moved to the position of the mouse cursor.
       
  2227                 int visual = visualIndexAt(pos + centerOffset);
       
  2228                 if (visual == -1)
       
  2229                     return;
       
  2230                 d->target = d->logicalIndex(visual);
       
  2231                 d->updateSectionIndicator(d->section, pos);
       
  2232             } else {
       
  2233                 int visual = visualIndexAt(d->firstPos);
       
  2234                 if (visual == -1)
       
  2235                     return;
       
  2236                 d->target = d->logicalIndex(visual);
       
  2237                 d->updateSectionIndicator(d->section, d->firstPos);
       
  2238             }
       
  2239             return;
       
  2240         }
       
  2241         case QHeaderViewPrivate::SelectSections: {
       
  2242             int logical = logicalIndexAt(pos);
       
  2243             if (logical == d->pressed)
       
  2244                 return; // nothing to do
       
  2245             else if (d->pressed != -1)
       
  2246                 updateSection(d->pressed);
       
  2247             d->pressed = logical;
       
  2248             if (d->clickableSections && logical != -1) {
       
  2249                 emit sectionEntered(d->pressed);
       
  2250                 updateSection(d->pressed);
       
  2251             }
       
  2252             return;
       
  2253         }
       
  2254         case QHeaderViewPrivate::NoState: {
       
  2255 #ifndef QT_NO_CURSOR
       
  2256             int handle = d->sectionHandleAt(pos);
       
  2257             bool hasCursor = testAttribute(Qt::WA_SetCursor);
       
  2258             if (handle != -1 && (resizeMode(handle) == Interactive)) {
       
  2259                 if (!hasCursor)
       
  2260                     setCursor(d->orientation == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor);
       
  2261             } else if (hasCursor) {
       
  2262                 unsetCursor();
       
  2263             }
       
  2264 #endif
       
  2265             return;
       
  2266         }
       
  2267         default:
       
  2268             break;
       
  2269     }
       
  2270 }
       
  2271 
       
  2272 /*!
       
  2273   \reimp
       
  2274 */
       
  2275 
       
  2276 void QHeaderView::mouseReleaseEvent(QMouseEvent *e)
       
  2277 {
       
  2278     Q_D(QHeaderView);
       
  2279     int pos = d->orientation == Qt::Horizontal ? e->x() : e->y();
       
  2280     switch (d->state) {
       
  2281     case QHeaderViewPrivate::MoveSection:
       
  2282         if (!d->sectionIndicator->isHidden()) { // moving
       
  2283             int from = visualIndex(d->section);
       
  2284             Q_ASSERT(from != -1);
       
  2285             int to = visualIndex(d->target);
       
  2286             Q_ASSERT(to != -1);
       
  2287             moveSection(from, to);
       
  2288             d->section = d->target = -1;
       
  2289             d->updateSectionIndicator(d->section, pos);
       
  2290             break;
       
  2291         } // not moving
       
  2292     case QHeaderViewPrivate::SelectSections:
       
  2293         if (!d->clickableSections) {
       
  2294             int section = logicalIndexAt(pos);
       
  2295             updateSection(section);
       
  2296         }
       
  2297         // fall through
       
  2298     case QHeaderViewPrivate::NoState:
       
  2299         if (d->clickableSections) {
       
  2300             int section = logicalIndexAt(pos);
       
  2301             if (section != -1 && section == d->pressed) {
       
  2302                 d->flipSortIndicator(section);
       
  2303                 emit sectionClicked(logicalIndexAt(pos));
       
  2304             }
       
  2305             if (d->pressed != -1)
       
  2306                 updateSection(d->pressed);
       
  2307         }
       
  2308         break;
       
  2309     case QHeaderViewPrivate::ResizeSection:
       
  2310         d->originalSize = -1;
       
  2311         d->clearCascadingSections();
       
  2312         break;
       
  2313     default:
       
  2314         break;
       
  2315     }
       
  2316     d->state = QHeaderViewPrivate::NoState;
       
  2317     d->pressed = -1;
       
  2318 }
       
  2319 
       
  2320 /*!
       
  2321   \reimp
       
  2322 */
       
  2323 
       
  2324 void QHeaderView::mouseDoubleClickEvent(QMouseEvent *e)
       
  2325 {
       
  2326     Q_D(QHeaderView);
       
  2327     int pos = d->orientation == Qt::Horizontal ? e->x() : e->y();
       
  2328     int handle = d->sectionHandleAt(pos);
       
  2329     if (handle > -1 && resizeMode(handle) == Interactive) {
       
  2330         emit sectionHandleDoubleClicked(handle);
       
  2331 #ifndef QT_NO_CURSOR
       
  2332         Qt::CursorShape splitCursor = (d->orientation == Qt::Horizontal)
       
  2333                                       ? Qt::SplitHCursor : Qt::SplitVCursor;
       
  2334         if (cursor().shape() == splitCursor) {
       
  2335             // signal handlers may have changed the section size
       
  2336             handle = d->sectionHandleAt(pos);
       
  2337             if (!(handle > -1 && resizeMode(handle) == Interactive))
       
  2338                 setCursor(Qt::ArrowCursor);
       
  2339         }
       
  2340 #endif
       
  2341     } else {
       
  2342         emit sectionDoubleClicked(logicalIndexAt(e->pos()));
       
  2343     }
       
  2344 }
       
  2345 
       
  2346 /*!
       
  2347   \reimp
       
  2348 */
       
  2349 
       
  2350 bool QHeaderView::viewportEvent(QEvent *e)
       
  2351 {
       
  2352     Q_D(QHeaderView);
       
  2353     switch (e->type()) {
       
  2354 #ifndef QT_NO_TOOLTIP
       
  2355     case QEvent::ToolTip: {
       
  2356         QHelpEvent *he = static_cast<QHelpEvent*>(e);
       
  2357         int logical = logicalIndexAt(he->pos());
       
  2358         if (logical != -1) {
       
  2359             QVariant variant = d->model->headerData(logical, d->orientation, Qt::ToolTipRole);
       
  2360             if (variant.isValid()) {
       
  2361                 QToolTip::showText(he->globalPos(), variant.toString(), this);
       
  2362                 return true;
       
  2363             }
       
  2364         }
       
  2365         break; }
       
  2366 #endif
       
  2367 #ifndef QT_NO_WHATSTHIS
       
  2368     case QEvent::QueryWhatsThis: {
       
  2369         QHelpEvent *he = static_cast<QHelpEvent*>(e);
       
  2370         int logical = logicalIndexAt(he->pos());
       
  2371         if (logical != -1
       
  2372             && d->model->headerData(logical, d->orientation, Qt::WhatsThisRole).isValid())
       
  2373             return true;
       
  2374         break; }
       
  2375     case QEvent::WhatsThis: {
       
  2376         QHelpEvent *he = static_cast<QHelpEvent*>(e);
       
  2377         int logical = logicalIndexAt(he->pos());
       
  2378         if (logical != -1) {
       
  2379              QVariant whatsthis = d->model->headerData(logical, d->orientation,
       
  2380                                                       Qt::WhatsThisRole);
       
  2381              if (whatsthis.isValid()) {
       
  2382                  QWhatsThis::showText(he->globalPos(), whatsthis.toString(), this);
       
  2383                  return true;
       
  2384              }
       
  2385         }
       
  2386         break; }
       
  2387 #endif // QT_NO_WHATSTHIS
       
  2388 #ifndef QT_NO_STATUSTIP
       
  2389     case QEvent::StatusTip: {
       
  2390         QHelpEvent *he = static_cast<QHelpEvent*>(e);
       
  2391         int logical = logicalIndexAt(he->pos());
       
  2392         if (logical != -1) {
       
  2393             QString statustip = d->model->headerData(logical, d->orientation,
       
  2394                                                     Qt::StatusTipRole).toString();
       
  2395             if (!statustip.isEmpty())
       
  2396                 setStatusTip(statustip);
       
  2397         }
       
  2398         return true; }
       
  2399 #endif // QT_NO_STATUSTIP
       
  2400     case QEvent::Hide:
       
  2401     case QEvent::Show:
       
  2402     case QEvent::FontChange:
       
  2403     case QEvent::StyleChange:
       
  2404         d->invalidateCachedSizeHint();
       
  2405         resizeSections();
       
  2406         emit geometriesChanged();
       
  2407         break;
       
  2408     case QEvent::ContextMenu: {
       
  2409         d->state = QHeaderViewPrivate::NoState;
       
  2410         d->pressed = d->section = d->target = -1;
       
  2411         d->updateSectionIndicator(d->section, -1);
       
  2412         break; }
       
  2413     case QEvent::Wheel: {
       
  2414         QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea *>(parentWidget());
       
  2415         if (asa)
       
  2416             return QApplication::sendEvent(asa->viewport(), e);
       
  2417         break; }
       
  2418     default:
       
  2419         break;
       
  2420     }
       
  2421     return QAbstractItemView::viewportEvent(e);
       
  2422 }
       
  2423 
       
  2424 /*!
       
  2425     Paints the section specified by the given \a logicalIndex, using the given
       
  2426     \a painter and \a rect.
       
  2427 
       
  2428     Normally, you do not have to call this function.
       
  2429 */
       
  2430 
       
  2431 void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
       
  2432 {
       
  2433     Q_D(const QHeaderView);
       
  2434     if (!rect.isValid())
       
  2435         return;
       
  2436     // get the state of the section
       
  2437     QStyleOptionHeader opt;
       
  2438     initStyleOption(&opt);
       
  2439     QStyle::State state = QStyle::State_None;
       
  2440     if (isEnabled())
       
  2441         state |= QStyle::State_Enabled;
       
  2442     if (window()->isActiveWindow())
       
  2443         state |= QStyle::State_Active;
       
  2444     if (d->clickableSections) {
       
  2445         if (logicalIndex == d->hover)
       
  2446             state |= QStyle::State_MouseOver;
       
  2447         if (logicalIndex == d->pressed)
       
  2448             state |= QStyle::State_Sunken;
       
  2449         else if (d->highlightSelected) {
       
  2450             if (d->sectionIntersectsSelection(logicalIndex))
       
  2451                 state |= QStyle::State_On;
       
  2452             if (d->isSectionSelected(logicalIndex))
       
  2453                 state |= QStyle::State_Sunken;
       
  2454         }
       
  2455 
       
  2456     }
       
  2457     if (isSortIndicatorShown() && sortIndicatorSection() == logicalIndex)
       
  2458         opt.sortIndicator = (sortIndicatorOrder() == Qt::AscendingOrder)
       
  2459                             ? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;
       
  2460 
       
  2461     // setup the style options structure
       
  2462     QVariant textAlignment = d->model->headerData(logicalIndex, d->orientation,
       
  2463                                                   Qt::TextAlignmentRole);
       
  2464     opt.rect = rect;
       
  2465     opt.section = logicalIndex;
       
  2466     opt.state |= state;
       
  2467     opt.textAlignment = Qt::Alignment(textAlignment.isValid()
       
  2468                                       ? Qt::Alignment(textAlignment.toInt())
       
  2469                                       : d->defaultAlignment);
       
  2470 
       
  2471     opt.iconAlignment = Qt::AlignVCenter;
       
  2472     opt.text = d->model->headerData(logicalIndex, d->orientation,
       
  2473                                     Qt::DisplayRole).toString();
       
  2474     if (d->textElideMode != Qt::ElideNone)
       
  2475         opt.text = opt.fontMetrics.elidedText(opt.text, d->textElideMode , rect.width() - 4);
       
  2476 
       
  2477     QVariant variant = d->model->headerData(logicalIndex, d->orientation,
       
  2478                                     Qt::DecorationRole);
       
  2479     opt.icon = qvariant_cast<QIcon>(variant);
       
  2480     if (opt.icon.isNull())
       
  2481         opt.icon = qvariant_cast<QPixmap>(variant);
       
  2482     QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation,
       
  2483                                                     Qt::ForegroundRole);
       
  2484     if (qVariantCanConvert<QBrush>(foregroundBrush))
       
  2485         opt.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(foregroundBrush));
       
  2486 
       
  2487     QPointF oldBO = painter->brushOrigin();
       
  2488     QVariant backgroundBrush = d->model->headerData(logicalIndex, d->orientation,
       
  2489                                                     Qt::BackgroundRole);
       
  2490     if (qVariantCanConvert<QBrush>(backgroundBrush)) {
       
  2491         opt.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(backgroundBrush));
       
  2492         opt.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(backgroundBrush));
       
  2493         painter->setBrushOrigin(opt.rect.topLeft());
       
  2494     }
       
  2495 
       
  2496     // the section position
       
  2497     int visual = visualIndex(logicalIndex);
       
  2498     Q_ASSERT(visual != -1);
       
  2499     if (count() == 1)
       
  2500         opt.position = QStyleOptionHeader::OnlyOneSection;
       
  2501     else if (visual == 0)
       
  2502         opt.position = QStyleOptionHeader::Beginning;
       
  2503     else if (visual == count() - 1)
       
  2504         opt.position = QStyleOptionHeader::End;
       
  2505     else
       
  2506         opt.position = QStyleOptionHeader::Middle;
       
  2507     opt.orientation = d->orientation;
       
  2508     // the selected position
       
  2509     bool previousSelected = d->isSectionSelected(this->logicalIndex(visual - 1));
       
  2510     bool nextSelected =  d->isSectionSelected(this->logicalIndex(visual + 1));
       
  2511     if (previousSelected && nextSelected)
       
  2512         opt.selectedPosition = QStyleOptionHeader::NextAndPreviousAreSelected;
       
  2513     else if (previousSelected)
       
  2514         opt.selectedPosition = QStyleOptionHeader::PreviousIsSelected;
       
  2515     else if (nextSelected)
       
  2516         opt.selectedPosition = QStyleOptionHeader::NextIsSelected;
       
  2517     else
       
  2518         opt.selectedPosition = QStyleOptionHeader::NotAdjacent;
       
  2519     // draw the section
       
  2520     style()->drawControl(QStyle::CE_Header, &opt, painter, this);
       
  2521 
       
  2522     painter->setBrushOrigin(oldBO);
       
  2523 }
       
  2524 
       
  2525 /*!
       
  2526     Returns the size of the contents of the section specified by the given
       
  2527     \a logicalIndex.
       
  2528 
       
  2529     \sa defaultSectionSize()
       
  2530 */
       
  2531 
       
  2532 QSize QHeaderView::sectionSizeFromContents(int logicalIndex) const
       
  2533 {
       
  2534     Q_D(const QHeaderView);
       
  2535     Q_ASSERT(logicalIndex >= 0);
       
  2536 
       
  2537     ensurePolished();
       
  2538 
       
  2539     // use SizeHintRole
       
  2540     QVariant variant = d->model->headerData(logicalIndex, d->orientation, Qt::SizeHintRole);
       
  2541     if (variant.isValid())
       
  2542         return qvariant_cast<QSize>(variant);
       
  2543 
       
  2544     // otherwise use the contents
       
  2545     QStyleOptionHeader opt;
       
  2546     initStyleOption(&opt);
       
  2547     opt.section = logicalIndex;
       
  2548     QVariant var = d->model->headerData(logicalIndex, d->orientation,
       
  2549                                             Qt::FontRole);
       
  2550     QFont fnt;
       
  2551     if (var.isValid() && qVariantCanConvert<QFont>(var))
       
  2552         fnt = qvariant_cast<QFont>(var);
       
  2553     else
       
  2554         fnt = font();
       
  2555     fnt.setBold(true);
       
  2556     opt.fontMetrics = QFontMetrics(fnt);
       
  2557     opt.text = d->model->headerData(logicalIndex, d->orientation,
       
  2558                                     Qt::DisplayRole).toString();
       
  2559     variant = d->model->headerData(logicalIndex, d->orientation, Qt::DecorationRole);
       
  2560     opt.icon = qvariant_cast<QIcon>(variant);
       
  2561     if (opt.icon.isNull())
       
  2562         opt.icon = qvariant_cast<QPixmap>(variant);
       
  2563     QSize size = style()->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize(), this);
       
  2564     if (isSortIndicatorShown()) {
       
  2565         int margin = style()->pixelMetric(QStyle::PM_HeaderMargin, &opt, this);
       
  2566         if (d->orientation == Qt::Horizontal)
       
  2567             size.rwidth() += size.height() + margin;
       
  2568         else
       
  2569             size.rheight() += size.width() + margin;
       
  2570     }
       
  2571     return size;
       
  2572 }
       
  2573 
       
  2574 /*!
       
  2575     Returns the horizontal offset of the header. This is 0 for vertical
       
  2576     headers.
       
  2577 
       
  2578     \sa offset()
       
  2579 */
       
  2580 
       
  2581 int QHeaderView::horizontalOffset() const
       
  2582 {
       
  2583     Q_D(const QHeaderView);
       
  2584     if (d->orientation == Qt::Horizontal)
       
  2585         return d->offset;
       
  2586     return 0;
       
  2587 }
       
  2588 
       
  2589 /*!
       
  2590     Returns the vertical offset of the header. This is 0 for horizontal
       
  2591     headers.
       
  2592 
       
  2593     \sa offset()
       
  2594 */
       
  2595 
       
  2596 int QHeaderView::verticalOffset() const
       
  2597 {
       
  2598     Q_D(const QHeaderView);
       
  2599     if (d->orientation == Qt::Vertical)
       
  2600         return d->offset;
       
  2601     return 0;
       
  2602 }
       
  2603 
       
  2604 /*!
       
  2605     \reimp
       
  2606     \internal
       
  2607 */
       
  2608 
       
  2609 void QHeaderView::updateGeometries()
       
  2610 {
       
  2611     Q_D(QHeaderView);
       
  2612     d->layoutChildren();
       
  2613     if (d->hasAutoResizeSections())
       
  2614         resizeSections();
       
  2615 }
       
  2616 
       
  2617 /*!
       
  2618     \reimp
       
  2619     \internal
       
  2620 */
       
  2621 
       
  2622 void QHeaderView::scrollContentsBy(int dx, int dy)
       
  2623 {
       
  2624     Q_D(QHeaderView);
       
  2625     d->scrollDirtyRegion(dx, dy);
       
  2626 }
       
  2627 
       
  2628 /*!
       
  2629     \reimp
       
  2630     \internal
       
  2631 */
       
  2632 void QHeaderView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
       
  2633 {
       
  2634     Q_D(QHeaderView);
       
  2635     d->invalidateCachedSizeHint();
       
  2636     if (d->hasAutoResizeSections()) {
       
  2637         bool resizeRequired = d->globalResizeMode == ResizeToContents;
       
  2638         int first = orientation() == Qt::Horizontal ? topLeft.column() : topLeft.row();
       
  2639         int last = orientation() == Qt::Horizontal ? bottomRight.column() : bottomRight.row();
       
  2640         for (int i = first; i <= last && !resizeRequired; ++i)
       
  2641             resizeRequired = (resizeMode(i) == ResizeToContents);
       
  2642         if (resizeRequired)
       
  2643             d->doDelayedResizeSections();
       
  2644     }
       
  2645 }
       
  2646 
       
  2647 /*!
       
  2648     \reimp
       
  2649     \internal
       
  2650 
       
  2651     Empty implementation because the header doesn't show QModelIndex items.
       
  2652 */
       
  2653 void QHeaderView::rowsInserted(const QModelIndex &, int, int)
       
  2654 {
       
  2655     // do nothing
       
  2656 }
       
  2657 
       
  2658 /*!
       
  2659     \reimp
       
  2660     \internal
       
  2661 
       
  2662     Empty implementation because the header doesn't show QModelIndex items.
       
  2663 */
       
  2664 
       
  2665 QRect QHeaderView::visualRect(const QModelIndex &) const
       
  2666 {
       
  2667     return QRect();
       
  2668 }
       
  2669 
       
  2670 /*!
       
  2671     \reimp
       
  2672     \internal
       
  2673 
       
  2674     Empty implementation because the header doesn't show QModelIndex items.
       
  2675 */
       
  2676 
       
  2677 void QHeaderView::scrollTo(const QModelIndex &, ScrollHint)
       
  2678 {
       
  2679     // do nothing - the header only displays sections
       
  2680 }
       
  2681 
       
  2682 /*!
       
  2683     \reimp
       
  2684     \internal
       
  2685 
       
  2686     Empty implementation because the header doesn't show QModelIndex items.
       
  2687 */
       
  2688 
       
  2689 QModelIndex QHeaderView::indexAt(const QPoint &) const
       
  2690 {
       
  2691     return QModelIndex();
       
  2692 }
       
  2693 
       
  2694 /*!
       
  2695     \reimp
       
  2696     \internal
       
  2697 
       
  2698     Empty implementation because the header doesn't show QModelIndex items.
       
  2699 */
       
  2700 
       
  2701 bool QHeaderView::isIndexHidden(const QModelIndex &) const
       
  2702 {
       
  2703     return true; // the header view has no items, just sections
       
  2704 }
       
  2705 
       
  2706 /*!
       
  2707     \reimp
       
  2708     \internal
       
  2709 
       
  2710     Empty implementation because the header doesn't show QModelIndex items.
       
  2711 */
       
  2712 
       
  2713 QModelIndex QHeaderView::moveCursor(CursorAction, Qt::KeyboardModifiers)
       
  2714 {
       
  2715     return QModelIndex();
       
  2716 }
       
  2717 
       
  2718 /*!
       
  2719     \reimp
       
  2720 
       
  2721     Selects the items in the given \a rect according to the specified
       
  2722     \a flags.
       
  2723 
       
  2724     The base class implementation does nothing.
       
  2725 */
       
  2726 
       
  2727 void QHeaderView::setSelection(const QRect&, QItemSelectionModel::SelectionFlags)
       
  2728 {
       
  2729     // do nothing
       
  2730 }
       
  2731 
       
  2732 /*!
       
  2733     \internal
       
  2734 */
       
  2735 
       
  2736 QRegion QHeaderView::visualRegionForSelection(const QItemSelection &selection) const
       
  2737 {
       
  2738     Q_D(const QHeaderView);
       
  2739     const int max = d->modelSectionCount();
       
  2740     if (d->orientation == Qt::Horizontal) {
       
  2741         int left = max;
       
  2742         int right = 0;
       
  2743         int rangeLeft, rangeRight;
       
  2744 
       
  2745         for (int i = 0; i < selection.count(); ++i) {
       
  2746             QItemSelectionRange r = selection.at(i);
       
  2747             if (r.parent().isValid() || !r.isValid())
       
  2748                 continue; // we only know about toplevel items and we don't want invalid ranges
       
  2749             // FIXME an item inside the range may be the leftmost or rightmost
       
  2750             rangeLeft = visualIndex(r.left());
       
  2751             if (rangeLeft == -1) // in some cases users may change the selections
       
  2752                 continue;        // before we have a chance to do the layout
       
  2753             rangeRight = visualIndex(r.right());
       
  2754             if (rangeRight == -1) // in some cases users may change the selections
       
  2755                 continue;         // before we have a chance to do the layout
       
  2756             if (rangeLeft < left)
       
  2757                 left = rangeLeft;
       
  2758             if (rangeRight > right)
       
  2759                 right = rangeRight;
       
  2760         }
       
  2761 
       
  2762         int logicalLeft = logicalIndex(left);
       
  2763         int logicalRight = logicalIndex(right);
       
  2764 
       
  2765         if (logicalLeft < 0  || logicalLeft >= count() ||
       
  2766             logicalRight < 0 || logicalRight >= count())
       
  2767             return QRegion();
       
  2768 
       
  2769         int leftPos = sectionViewportPosition(logicalLeft);
       
  2770         int rightPos = sectionViewportPosition(logicalRight);
       
  2771         rightPos += sectionSize(logicalRight);
       
  2772         return QRect(leftPos, 0, rightPos - leftPos, height());
       
  2773     }
       
  2774     // orientation() == Qt::Vertical
       
  2775     int top = max;
       
  2776     int bottom = 0;
       
  2777     int rangeTop, rangeBottom;
       
  2778 
       
  2779     for (int i = 0; i < selection.count(); ++i) {
       
  2780         QItemSelectionRange r = selection.at(i);
       
  2781         if (r.parent().isValid() || !r.isValid())
       
  2782             continue; // we only know about toplevel items
       
  2783         // FIXME an item inside the range may be the leftmost or rightmost
       
  2784         rangeTop = visualIndex(r.top());
       
  2785         if (rangeTop == -1) // in some cases users may change the selections
       
  2786             continue;       // before we have a chance to do the layout
       
  2787         rangeBottom = visualIndex(r.bottom());
       
  2788         if (rangeBottom == -1) // in some cases users may change the selections
       
  2789             continue;          // before we have a chance to do the layout
       
  2790         if (rangeTop < top)
       
  2791             top = rangeTop;
       
  2792         if (rangeBottom > bottom)
       
  2793             bottom = rangeBottom;
       
  2794     }
       
  2795 
       
  2796     int logicalTop = logicalIndex(top);
       
  2797     int logicalBottom = logicalIndex(bottom);
       
  2798 
       
  2799     if (logicalTop == -1 || logicalBottom == -1)
       
  2800         return QRect();
       
  2801 
       
  2802     int topPos = sectionViewportPosition(logicalTop);
       
  2803     int bottomPos = sectionViewportPosition(logicalBottom) + sectionSize(logicalBottom);
       
  2804 
       
  2805     return QRect(0, topPos, width(), bottomPos - topPos);
       
  2806 }
       
  2807 
       
  2808 
       
  2809 // private implementation
       
  2810 
       
  2811 int QHeaderViewPrivate::sectionHandleAt(int position)
       
  2812 {
       
  2813     Q_Q(QHeaderView);
       
  2814     int visual = q->visualIndexAt(position);
       
  2815     if (visual == -1)
       
  2816         return -1;
       
  2817     int log = logicalIndex(visual);
       
  2818     int pos = q->sectionViewportPosition(log);
       
  2819     int grip = q->style()->pixelMetric(QStyle::PM_HeaderGripMargin, 0, q);
       
  2820 
       
  2821     bool atLeft = position < pos + grip;
       
  2822     bool atRight = (position > pos + q->sectionSize(log) - grip);
       
  2823     if (reverse())
       
  2824         qSwap(atLeft, atRight);
       
  2825 
       
  2826     if (atLeft) {
       
  2827         //grip at the beginning of the section
       
  2828         while(visual > -1) {
       
  2829             int logical = q->logicalIndex(--visual);
       
  2830             if (!q->isSectionHidden(logical))
       
  2831                 return logical;
       
  2832         }
       
  2833     } else if (atRight) {
       
  2834         //grip at the end of the section
       
  2835         return log;
       
  2836     }
       
  2837     return -1;
       
  2838 }
       
  2839 
       
  2840 void QHeaderViewPrivate::setupSectionIndicator(int section, int position)
       
  2841 {
       
  2842     Q_Q(QHeaderView);
       
  2843     if (!sectionIndicator) {
       
  2844         sectionIndicator = new QLabel(viewport);
       
  2845     }
       
  2846 
       
  2847     int w, h;
       
  2848     int p = q->sectionViewportPosition(section);
       
  2849     if (orientation == Qt::Horizontal) {
       
  2850         w = q->sectionSize(section);
       
  2851         h = viewport->height();
       
  2852     } else {
       
  2853         w = viewport->width();
       
  2854         h = q->sectionSize(section);
       
  2855     }
       
  2856     sectionIndicator->resize(w, h);
       
  2857 
       
  2858     QPixmap pm(w, h);
       
  2859     pm.fill(QColor(0, 0, 0, 45));
       
  2860     QRect rect(0, 0, w, h);
       
  2861 
       
  2862     QPainter painter(&pm);
       
  2863     painter.setOpacity(0.75);
       
  2864     q->paintSection(&painter, rect, section);
       
  2865     painter.end();
       
  2866 
       
  2867     sectionIndicator->setPixmap(pm);
       
  2868     sectionIndicatorOffset = position - qMax(p, 0);
       
  2869 }
       
  2870 
       
  2871 void QHeaderViewPrivate::updateSectionIndicator(int section, int position)
       
  2872 {
       
  2873     if (!sectionIndicator)
       
  2874         return;
       
  2875 
       
  2876     if (section == -1 || target == -1) {
       
  2877         sectionIndicator->hide();
       
  2878         return;
       
  2879     }
       
  2880 
       
  2881     if (orientation == Qt::Horizontal)
       
  2882         sectionIndicator->move(position - sectionIndicatorOffset, 0);
       
  2883     else
       
  2884         sectionIndicator->move(0, position - sectionIndicatorOffset);
       
  2885 
       
  2886     sectionIndicator->show();
       
  2887 }
       
  2888 
       
  2889 /*!
       
  2890     Initialize \a option with the values from this QHeaderView. This method is
       
  2891     useful for subclasses when they need a QStyleOptionHeader, but do not want
       
  2892     to fill in all the information themselves.
       
  2893 
       
  2894     \sa QStyleOption::initFrom()
       
  2895 */
       
  2896 void QHeaderView::initStyleOption(QStyleOptionHeader *option) const
       
  2897 {
       
  2898     Q_D(const QHeaderView);
       
  2899     option->initFrom(this);
       
  2900     option->state = QStyle::State_None | QStyle::State_Raised;
       
  2901     option->orientation = d->orientation;
       
  2902     if (d->orientation == Qt::Horizontal)
       
  2903         option->state |= QStyle::State_Horizontal;
       
  2904     if (isEnabled())
       
  2905         option->state |= QStyle::State_Enabled;
       
  2906     option->section = 0;
       
  2907 }
       
  2908 
       
  2909 bool QHeaderViewPrivate::isSectionSelected(int section) const
       
  2910 {
       
  2911     int i = section * 2;
       
  2912     if (i < 0 || i >= sectionSelected.count())
       
  2913         return false;
       
  2914     if (sectionSelected.testBit(i)) // if the value was cached
       
  2915         return sectionSelected.testBit(i + 1);
       
  2916     bool s = false;
       
  2917     if (orientation == Qt::Horizontal)
       
  2918         s = isColumnSelected(section);
       
  2919     else
       
  2920         s = isRowSelected(section);
       
  2921     sectionSelected.setBit(i + 1, s); // selection state
       
  2922     sectionSelected.setBit(i, true); // cache state
       
  2923     return s;
       
  2924 }
       
  2925 
       
  2926 /*!
       
  2927     \internal
       
  2928     Returns the last visible (ie. not hidden) visual index
       
  2929 */
       
  2930 int QHeaderViewPrivate::lastVisibleVisualIndex() const
       
  2931 {
       
  2932     Q_Q(const QHeaderView);
       
  2933     for (int visual = q->count()-1; visual >= 0; --visual) {
       
  2934         if (!q->isSectionHidden(q->logicalIndex(visual)))
       
  2935             return visual;
       
  2936     }
       
  2937 
       
  2938     //default value if no section is actually visible
       
  2939     return -1;
       
  2940 }
       
  2941 
       
  2942 /*!
       
  2943     \internal
       
  2944     Go through and resize all of the sections applying stretchLastSection,
       
  2945     manualy stretches, sizes, and useGlobalMode.
       
  2946 
       
  2947     The different resize modes are:
       
  2948     Interactive - the user decides the size
       
  2949     Stretch - take up whatever space is left
       
  2950     Fixed - the size is set programmatically outside the header
       
  2951     ResizeToContentes - the size is set based on the contents of the row or column in the parent view
       
  2952 
       
  2953     The resize mode will not affect the last section if stretchLastSection is true.
       
  2954 */
       
  2955 void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool useGlobalMode)
       
  2956 {
       
  2957     Q_Q(QHeaderView);
       
  2958     //stop the timer in case it is delayed
       
  2959     delayedResize.stop();
       
  2960 
       
  2961     executePostedLayout();
       
  2962     if (sectionCount == 0)
       
  2963         return;
       
  2964 
       
  2965     if (resizeRecursionBlock)
       
  2966         return;
       
  2967     resizeRecursionBlock = true;
       
  2968 
       
  2969     invalidateCachedSizeHint();
       
  2970 
       
  2971     const int lastVisibleSection = lastVisibleVisualIndex();
       
  2972 
       
  2973     // find stretchLastSection if we have it
       
  2974     int stretchSection = -1;
       
  2975     if (stretchLastSection && !useGlobalMode)
       
  2976         stretchSection = lastVisibleVisualIndex();
       
  2977 
       
  2978     // count up the number of strected sections and how much space left for them
       
  2979     int lengthToStrech = (orientation == Qt::Horizontal ? viewport->width() : viewport->height());
       
  2980     int numberOfStretchedSections = 0;
       
  2981     QList<int> section_sizes;
       
  2982     for (int i = 0; i < sectionCount; ++i) {
       
  2983         if (isVisualIndexHidden(i))
       
  2984             continue;
       
  2985 
       
  2986         QHeaderView::ResizeMode resizeMode;
       
  2987         if (useGlobalMode && (i != stretchSection))
       
  2988             resizeMode = globalMode;
       
  2989         else
       
  2990             resizeMode = (i == stretchSection ? QHeaderView::Stretch : headerSectionResizeMode(i));
       
  2991 
       
  2992         if (resizeMode == QHeaderView::Stretch) {
       
  2993             ++numberOfStretchedSections;
       
  2994             section_sizes.append(headerSectionSize(i));
       
  2995             continue;
       
  2996         }
       
  2997 
       
  2998         // because it isn't stretch, determine its width and remove that from lengthToStrech
       
  2999         int sectionSize = 0;
       
  3000         if (resizeMode == QHeaderView::Interactive || resizeMode == QHeaderView::Fixed) {
       
  3001             sectionSize = headerSectionSize(i);
       
  3002         } else { // resizeMode == QHeaderView::ResizeToContents
       
  3003             int logicalIndex = q->logicalIndex(i);
       
  3004             sectionSize = qMax(viewSectionSizeHint(logicalIndex),
       
  3005                                q->sectionSizeHint(logicalIndex));
       
  3006         }
       
  3007         section_sizes.append(sectionSize);
       
  3008         lengthToStrech -= sectionSize;
       
  3009     }
       
  3010 
       
  3011     // calculate the new length for all of the stretched sections
       
  3012     int stretchSectionLength = -1;
       
  3013     int pixelReminder = 0;
       
  3014     if (numberOfStretchedSections > 0 && lengthToStrech > 0) { // we have room to stretch in
       
  3015         int hintLengthForEveryStretchedSection = lengthToStrech / numberOfStretchedSections;
       
  3016         stretchSectionLength = qMax(hintLengthForEveryStretchedSection, q->minimumSectionSize());
       
  3017         pixelReminder = lengthToStrech % numberOfStretchedSections;
       
  3018     }
       
  3019 
       
  3020     int spanStartSection = 0;
       
  3021     int previousSectionLength = 0;
       
  3022 
       
  3023     QHeaderView::ResizeMode previousSectionResizeMode = QHeaderView::Interactive;
       
  3024 
       
  3025     // resize each section along the total length
       
  3026     for (int i = 0; i < sectionCount; ++i) {
       
  3027         int oldSectionLength = headerSectionSize(i);
       
  3028         int newSectionLength = -1;
       
  3029         QHeaderView::ResizeMode newSectionResizeMode = headerSectionResizeMode(i);
       
  3030 
       
  3031         if (isVisualIndexHidden(i)) {
       
  3032             newSectionLength = 0;
       
  3033         } else {
       
  3034             QHeaderView::ResizeMode resizeMode;
       
  3035             if (useGlobalMode)
       
  3036                 resizeMode = globalMode;
       
  3037             else
       
  3038                 resizeMode = (i == stretchSection
       
  3039                               ? QHeaderView::Stretch
       
  3040                               : newSectionResizeMode);
       
  3041             if (resizeMode == QHeaderView::Stretch && stretchSectionLength != -1) {
       
  3042                 if (i == lastVisibleSection)
       
  3043                     newSectionLength = qMax(stretchSectionLength, lastSectionSize);
       
  3044                 else
       
  3045                     newSectionLength = stretchSectionLength;
       
  3046                 if (pixelReminder > 0) {
       
  3047                     newSectionLength += 1;
       
  3048                     --pixelReminder;
       
  3049                 }
       
  3050                 section_sizes.removeFirst();
       
  3051             } else {
       
  3052                 newSectionLength = section_sizes.front();
       
  3053                 section_sizes.removeFirst();
       
  3054             }
       
  3055         }
       
  3056 
       
  3057         //Q_ASSERT(newSectionLength > 0);
       
  3058         if ((previousSectionResizeMode != newSectionResizeMode
       
  3059             || previousSectionLength != newSectionLength) && i > 0) {
       
  3060             int spanLength = (i - spanStartSection) * previousSectionLength;
       
  3061             createSectionSpan(spanStartSection, i - 1, spanLength, previousSectionResizeMode);
       
  3062             //Q_ASSERT(headerLength() == length);
       
  3063             spanStartSection = i;
       
  3064         }
       
  3065 
       
  3066         if (newSectionLength != oldSectionLength)
       
  3067             emit q->sectionResized(logicalIndex(i), oldSectionLength, newSectionLength);
       
  3068 
       
  3069         previousSectionLength = newSectionLength;
       
  3070         previousSectionResizeMode = newSectionResizeMode;
       
  3071     }
       
  3072 
       
  3073     createSectionSpan(spanStartSection, sectionCount - 1,
       
  3074                       (sectionCount - spanStartSection) * previousSectionLength,
       
  3075                       previousSectionResizeMode);
       
  3076     //Q_ASSERT(headerLength() == length);
       
  3077     resizeRecursionBlock = false;
       
  3078     viewport->update();
       
  3079 }
       
  3080 
       
  3081 void QHeaderViewPrivate::createSectionSpan(int start, int end, int size, QHeaderView::ResizeMode mode)
       
  3082 {
       
  3083     // ### the code for merging spans does not merge at all opertuneties
       
  3084     // ### what if the number of sections is reduced ?
       
  3085 
       
  3086     SectionSpan span(size, (end - start) + 1, mode);
       
  3087     int start_section = 0;
       
  3088 #ifndef QT_NO_DEBUG
       
  3089     int initial_section_count = headerSectionCount(); // ### debug code
       
  3090 #endif
       
  3091 
       
  3092     QList<int> spansToRemove;
       
  3093     for (int i = 0; i < sectionSpans.count(); ++i) {
       
  3094         int end_section = start_section + sectionSpans.at(i).count - 1;
       
  3095         int section_count = sectionSpans.at(i).count;
       
  3096         if (start <= start_section && end > end_section) {
       
  3097             // the existing span is entirely coveded by the new span
       
  3098             spansToRemove.append(i);
       
  3099         } else if (start < start_section && end >= end_section) {
       
  3100             // the existing span is entirely coveded by the new span
       
  3101             spansToRemove.append(i);
       
  3102         } else if (start == start_section && end == end_section) {
       
  3103             // the new span is covered by an existin span
       
  3104             length -= sectionSpans.at(i).size;
       
  3105             length += size;
       
  3106             sectionSpans[i].size = size;
       
  3107             sectionSpans[i].resizeMode = mode;
       
  3108             // ### check if we can merge the section with any of its neighbours
       
  3109             removeSpans(spansToRemove);
       
  3110             Q_ASSERT(initial_section_count == headerSectionCount());
       
  3111             return;
       
  3112         } else if (start > start_section && end < end_section) {
       
  3113             if (sectionSpans.at(i).sectionSize() == span.sectionSize()
       
  3114                 && sectionSpans.at(i).resizeMode == span.resizeMode) {
       
  3115                 Q_ASSERT(initial_section_count == headerSectionCount());
       
  3116                 return;
       
  3117             }
       
  3118             // the new span is in the middle of the old span, so we have to split it
       
  3119             length -= sectionSpans.at(i).size;
       
  3120             int section_size = sectionSpans.at(i).sectionSize();
       
  3121 #ifndef QT_NO_DEBUG
       
  3122             int span_count = sectionSpans.at(i).count;
       
  3123 #endif
       
  3124             QHeaderView::ResizeMode span_mode = sectionSpans.at(i).resizeMode;
       
  3125             // first span
       
  3126             int first_span_count = start - start_section;
       
  3127             int first_span_size = section_size * first_span_count;
       
  3128             sectionSpans[i].count = first_span_count;
       
  3129             sectionSpans[i].size = first_span_size;
       
  3130             sectionSpans[i].resizeMode = span_mode;
       
  3131             length += first_span_size;
       
  3132             // middle span (the new span)
       
  3133 #ifndef QT_NO_DEBUG
       
  3134             int mid_span_count = span.count;
       
  3135 #endif
       
  3136             int mid_span_size = span.size;
       
  3137             sectionSpans.insert(i + 1, span);
       
  3138             length += mid_span_size;
       
  3139             // last span
       
  3140             int last_span_count = end_section - end;
       
  3141             int last_span_size = section_size * last_span_count;
       
  3142             sectionSpans.insert(i + 2, SectionSpan(last_span_size, last_span_count, span_mode));
       
  3143             length += last_span_size;
       
  3144             Q_ASSERT(span_count == first_span_count + mid_span_count + last_span_count);
       
  3145             removeSpans(spansToRemove);
       
  3146             Q_ASSERT(initial_section_count == headerSectionCount());
       
  3147             return;
       
  3148         } else if (start > start_section && start <= end_section && end >= end_section) {
       
  3149             // the new span covers the last part of the existing span
       
  3150             length -= sectionSpans.at(i).size;
       
  3151             int removed_count = (end_section - start + 1);
       
  3152             int span_count = sectionSpans.at(i).count - removed_count;
       
  3153             int section_size = sectionSpans.at(i).sectionSize();
       
  3154             int span_size = section_size * span_count;
       
  3155             sectionSpans[i].count = span_count;
       
  3156             sectionSpans[i].size = span_size;
       
  3157             length += span_size;
       
  3158             if (end == end_section) {
       
  3159                 sectionSpans.insert(i + 1, span); // insert after
       
  3160                 length += span.size;
       
  3161                 removeSpans(spansToRemove);
       
  3162                 Q_ASSERT(initial_section_count == headerSectionCount());
       
  3163                 return;
       
  3164             }
       
  3165         } else if (end < end_section && end >= start_section && start <= start_section) {
       
  3166             // the new span covers the first part of the existing span
       
  3167             length -= sectionSpans.at(i).size;
       
  3168             int removed_count = (end - start_section + 1);
       
  3169             int section_size = sectionSpans.at(i).sectionSize();
       
  3170             int span_count = sectionSpans.at(i).count - removed_count;
       
  3171             int span_size = section_size * span_count;
       
  3172             sectionSpans[i].count = span_count;
       
  3173             sectionSpans[i].size = span_size;
       
  3174             length += span_size;
       
  3175             sectionSpans.insert(i, span); // insert before
       
  3176             length += span.size;
       
  3177             removeSpans(spansToRemove);
       
  3178             Q_ASSERT(initial_section_count == headerSectionCount());
       
  3179             return;
       
  3180         }
       
  3181         start_section += section_count;
       
  3182     }
       
  3183 
       
  3184     // ### adding and removing _ sections_  in addition to spans
       
  3185     // ### add some more checks here
       
  3186 
       
  3187     if (spansToRemove.isEmpty()) {
       
  3188         if (!sectionSpans.isEmpty()
       
  3189             && sectionSpans.last().sectionSize() == span.sectionSize()
       
  3190             && sectionSpans.last().resizeMode == span.resizeMode) {
       
  3191             length += span.size;
       
  3192             int last = sectionSpans.count() - 1;
       
  3193             sectionSpans[last].count += span.count;
       
  3194             sectionSpans[last].size += span.size;
       
  3195             sectionSpans[last].resizeMode = span.resizeMode;
       
  3196         } else {
       
  3197             length += span.size;
       
  3198             sectionSpans.append(span);
       
  3199         }
       
  3200     } else {
       
  3201         removeSpans(spansToRemove);
       
  3202         length += span.size;
       
  3203         sectionSpans.insert(spansToRemove.first(), span);
       
  3204         //Q_ASSERT(initial_section_count == headerSectionCount());
       
  3205     }
       
  3206 }
       
  3207 
       
  3208 void QHeaderViewPrivate::removeSectionsFromSpans(int start, int end)
       
  3209 {
       
  3210     // remove sections
       
  3211     int start_section = 0;
       
  3212     QList<int> spansToRemove;
       
  3213     for (int i = 0; i < sectionSpans.count(); ++i) {
       
  3214         int end_section = start_section + sectionSpans.at(i).count - 1;
       
  3215         int section_size = sectionSpans.at(i).sectionSize();
       
  3216         int section_count = sectionSpans.at(i).count;
       
  3217         if (start <= start_section && end >= end_section) {
       
  3218             // the change covers the entire span
       
  3219             spansToRemove.append(i);
       
  3220             if (end == end_section)
       
  3221                 break;
       
  3222         } else if (start > start_section && end < end_section) {
       
  3223             // all the removed sections are inside the span
       
  3224             int change = (end - start + 1);
       
  3225             sectionSpans[i].count -= change;
       
  3226             sectionSpans[i].size = section_size * sectionSpans.at(i).count;
       
  3227             length -= (change * section_size);
       
  3228             break;
       
  3229         } else if (start >= start_section && start <= end_section) {
       
  3230             // the some of the removed sections are inside the span,at the end
       
  3231             int change = qMin(end_section - start + 1, end - start + 1);
       
  3232             sectionSpans[i].count -= change;
       
  3233             sectionSpans[i].size = section_size * sectionSpans.at(i).count;
       
  3234             start += change;
       
  3235             length -= (change * section_size);
       
  3236             // the change affects several spans
       
  3237         } else if (end >= start_section && end <= end_section) {
       
  3238             // the some of the removed sections are inside the span, at the beginning
       
  3239             int change = qMin((end - start_section + 1), end - start + 1);
       
  3240             sectionSpans[i].count -= change;
       
  3241             sectionSpans[i].size = section_size * sectionSpans.at(i).count;
       
  3242             length -= (change * section_size);
       
  3243             break;
       
  3244         }
       
  3245         start_section += section_count;
       
  3246     }
       
  3247 
       
  3248     for (int i = spansToRemove.count() - 1; i >= 0; --i) {
       
  3249         int s = spansToRemove.at(i);
       
  3250         length -= sectionSpans.at(s).size;
       
  3251         sectionSpans.remove(s);
       
  3252         // ### merge remaining spans
       
  3253     }
       
  3254 }
       
  3255 
       
  3256 void QHeaderViewPrivate::clear()
       
  3257 {
       
  3258     if (state != NoClear) {
       
  3259     length = 0;
       
  3260     sectionCount = 0;
       
  3261     visualIndices.clear();
       
  3262     logicalIndices.clear();
       
  3263     sectionSelected.clear();
       
  3264     sectionHidden.clear();
       
  3265     hiddenSectionSize.clear();
       
  3266     sectionSpans.clear();
       
  3267     }
       
  3268 }
       
  3269 
       
  3270 void QHeaderViewPrivate::flipSortIndicator(int section)
       
  3271 {
       
  3272     Q_Q(QHeaderView);
       
  3273     bool ascending = (sortIndicatorSection != section
       
  3274                       || sortIndicatorOrder == Qt::DescendingOrder);
       
  3275     q->setSortIndicator(section, ascending ? Qt::AscendingOrder : Qt::DescendingOrder);
       
  3276 }
       
  3277 
       
  3278 void QHeaderViewPrivate::cascadingResize(int visual, int newSize)
       
  3279 {
       
  3280     Q_Q(QHeaderView);
       
  3281     const int minimumSize = q->minimumSectionSize();
       
  3282     const int oldSize = headerSectionSize(visual);
       
  3283     int delta = newSize - oldSize;
       
  3284 
       
  3285     if (delta > 0) { // larger
       
  3286         bool sectionResized = false;
       
  3287 
       
  3288         // restore old section sizes
       
  3289         for (int i = firstCascadingSection; i < visual; ++i) {
       
  3290             if (cascadingSectionSize.contains(i)) {
       
  3291                 int currentSectionSize = headerSectionSize(i);
       
  3292                 int originalSectionSize = cascadingSectionSize.value(i);
       
  3293                 if (currentSectionSize < originalSectionSize) {
       
  3294                     int newSectionSize = currentSectionSize + delta;
       
  3295                     resizeSectionSpan(i, currentSectionSize, newSectionSize);
       
  3296                     if (newSectionSize >= originalSectionSize && false)
       
  3297                         cascadingSectionSize.remove(i); // the section is now restored
       
  3298                     sectionResized = true;
       
  3299                     break;
       
  3300                 }
       
  3301             }
       
  3302 
       
  3303         }
       
  3304 
       
  3305         // resize the section
       
  3306         if (!sectionResized) {
       
  3307             newSize = qMax(newSize, minimumSize);
       
  3308             if (oldSize != newSize)
       
  3309                 resizeSectionSpan(visual, oldSize, newSize);
       
  3310         }
       
  3311 
       
  3312         // cascade the section size change
       
  3313         for (int i = visual + 1; i < sectionCount; ++i) {
       
  3314             if (!sectionIsCascadable(i))
       
  3315                 continue;
       
  3316             int currentSectionSize = headerSectionSize(i);
       
  3317             if (currentSectionSize <= minimumSize)
       
  3318                 continue;
       
  3319             int newSectionSize = qMax(currentSectionSize - delta, minimumSize);
       
  3320             //qDebug() << "### cascading to" << i << newSectionSize - currentSectionSize << delta;
       
  3321             resizeSectionSpan(i, currentSectionSize, newSectionSize);
       
  3322             saveCascadingSectionSize(i, currentSectionSize);
       
  3323             delta = delta - (currentSectionSize - newSectionSize);
       
  3324             //qDebug() << "new delta" << delta;
       
  3325             //if (newSectionSize != minimumSize)
       
  3326             if (delta <= 0)
       
  3327                 break;
       
  3328         }
       
  3329     } else { // smaller
       
  3330         bool sectionResized = false;
       
  3331 
       
  3332         // restore old section sizes
       
  3333         for (int i = lastCascadingSection; i > visual; --i) {
       
  3334             if (!cascadingSectionSize.contains(i))
       
  3335                 continue;
       
  3336             int currentSectionSize = headerSectionSize(i);
       
  3337             int originalSectionSize = cascadingSectionSize.value(i);
       
  3338             if (currentSectionSize >= originalSectionSize)
       
  3339                 continue;
       
  3340             int newSectionSize = currentSectionSize - delta;
       
  3341             resizeSectionSpan(i, currentSectionSize, newSectionSize);
       
  3342             if (newSectionSize >= originalSectionSize && false) {
       
  3343                 //qDebug() << "section" << i << "restored to" << originalSectionSize;
       
  3344                 cascadingSectionSize.remove(i); // the section is now restored
       
  3345             }
       
  3346             sectionResized = true;
       
  3347             break;
       
  3348         }
       
  3349 
       
  3350         // resize the section
       
  3351         resizeSectionSpan(visual, oldSize, qMax(newSize, minimumSize));
       
  3352 
       
  3353         // cascade the section size change
       
  3354         if (delta < 0 && newSize < minimumSize) {
       
  3355             for (int i = visual - 1; i >= 0; --i) {
       
  3356                 if (!sectionIsCascadable(i))
       
  3357                     continue;
       
  3358                 int sectionSize = headerSectionSize(i);
       
  3359                 if (sectionSize <= minimumSize)
       
  3360                     continue;
       
  3361                 resizeSectionSpan(i, sectionSize, qMax(sectionSize + delta, minimumSize));
       
  3362                 saveCascadingSectionSize(i, sectionSize);
       
  3363                 break;
       
  3364             }
       
  3365         }
       
  3366 
       
  3367         // let the next section get the space from the resized section
       
  3368         if (!sectionResized) {
       
  3369             for (int i = visual + 1; i < sectionCount; ++i) {
       
  3370                 if (!sectionIsCascadable(i))
       
  3371                     continue;
       
  3372                 int currentSectionSize = headerSectionSize(i);
       
  3373                 int newSectionSize = qMax(currentSectionSize - delta, minimumSize);
       
  3374                 resizeSectionSpan(i, currentSectionSize, newSectionSize);
       
  3375                 break;
       
  3376             }
       
  3377         }
       
  3378     }
       
  3379 
       
  3380     if (hasAutoResizeSections())
       
  3381         doDelayedResizeSections();
       
  3382 
       
  3383     viewport->update();
       
  3384 }
       
  3385 
       
  3386 void QHeaderViewPrivate::setDefaultSectionSize(int size)
       
  3387 {
       
  3388     Q_Q(QHeaderView);
       
  3389     defaultSectionSize = size;
       
  3390     int currentVisualIndex = 0;
       
  3391     for (int i = 0; i < sectionSpans.count(); ++i) {
       
  3392         QHeaderViewPrivate::SectionSpan &span = sectionSpans[i];
       
  3393         if (span.size > 0) {
       
  3394             //we resize it if it is not hidden (ie size > 0)
       
  3395             const int newSize = span.count * size;
       
  3396             if (newSize != span.size) {
       
  3397                 length += newSize - span.size; //the whole length is changed
       
  3398                 const int oldSectionSize = span.sectionSize();
       
  3399                 span.size = span.count * size;
       
  3400                 for (int i = currentVisualIndex; i < currentVisualIndex + span.count; ++i) {
       
  3401                     emit q->sectionResized(logicalIndex(i), oldSectionSize, size);
       
  3402                 }
       
  3403             }
       
  3404         }
       
  3405         currentVisualIndex += span.count;
       
  3406     }
       
  3407 }
       
  3408 
       
  3409 void QHeaderViewPrivate::resizeSectionSpan(int visualIndex, int oldSize, int newSize)
       
  3410 {
       
  3411     Q_Q(QHeaderView);
       
  3412     QHeaderView::ResizeMode mode = headerSectionResizeMode(visualIndex);
       
  3413     createSectionSpan(visualIndex, visualIndex, newSize, mode);
       
  3414     emit q->sectionResized(logicalIndex(visualIndex), oldSize, newSize);
       
  3415 }
       
  3416 
       
  3417 int QHeaderViewPrivate::headerSectionSize(int visual) const
       
  3418 {
       
  3419     // ### stupid iteration
       
  3420     int section_start = 0;
       
  3421     const int sectionSpansCount = sectionSpans.count();
       
  3422     for (int i = 0; i < sectionSpansCount; ++i) {
       
  3423         const QHeaderViewPrivate::SectionSpan &currentSection = sectionSpans.at(i);
       
  3424         int section_end = section_start + currentSection.count - 1;
       
  3425         if (visual >= section_start && visual <= section_end)
       
  3426             return currentSection.sectionSize();
       
  3427         section_start = section_end + 1;
       
  3428     }
       
  3429     return -1;
       
  3430 }
       
  3431 
       
  3432 int QHeaderViewPrivate::headerSectionPosition(int visual) const
       
  3433 {
       
  3434     // ### stupid iteration
       
  3435     int section_start = 0;
       
  3436     int span_position = 0;
       
  3437     const int sectionSpansCount = sectionSpans.count();
       
  3438     for (int i = 0; i < sectionSpansCount; ++i) {
       
  3439         const QHeaderViewPrivate::SectionSpan &currentSection = sectionSpans.at(i);
       
  3440         int section_end = section_start + currentSection.count - 1;
       
  3441         if (visual >= section_start && visual <= section_end)
       
  3442             return span_position + (visual - section_start) * currentSection.sectionSize();
       
  3443         section_start = section_end + 1;
       
  3444         span_position += currentSection.size;
       
  3445     }
       
  3446     return -1;
       
  3447 }
       
  3448 
       
  3449 int QHeaderViewPrivate::headerVisualIndexAt(int position) const
       
  3450 {
       
  3451     // ### stupid iteration
       
  3452     int span_start_section = 0;
       
  3453     int span_position = 0;
       
  3454     const int sectionSpansCount = sectionSpans.count();
       
  3455     for (int i = 0; i < sectionSpansCount; ++i) {
       
  3456         const QHeaderViewPrivate::SectionSpan &currentSection = sectionSpans.at(i);
       
  3457         int next_span_start_section = span_start_section + currentSection.count;
       
  3458         int next_span_position = span_position + currentSection.size;
       
  3459         if (position == span_position)
       
  3460             return span_start_section; // spans with no size
       
  3461         if (position > span_position && position < next_span_position) {
       
  3462             int position_in_span = position - span_position;
       
  3463             return span_start_section + (position_in_span / currentSection.sectionSize());
       
  3464         }
       
  3465         span_start_section = next_span_start_section;
       
  3466         span_position = next_span_position;
       
  3467     }
       
  3468     return -1;
       
  3469 }
       
  3470 
       
  3471 void QHeaderViewPrivate::setHeaderSectionResizeMode(int visual, QHeaderView::ResizeMode mode)
       
  3472 {
       
  3473     int size = headerSectionSize(visual);
       
  3474     createSectionSpan(visual, visual, size, mode);
       
  3475 }
       
  3476 
       
  3477 QHeaderView::ResizeMode QHeaderViewPrivate::headerSectionResizeMode(int visual) const
       
  3478 {
       
  3479     int span = sectionSpanIndex(visual);
       
  3480     if (span == -1)
       
  3481         return globalResizeMode;
       
  3482     return sectionSpans.at(span).resizeMode;
       
  3483 }
       
  3484 
       
  3485 void QHeaderViewPrivate::setGlobalHeaderResizeMode(QHeaderView::ResizeMode mode)
       
  3486 {
       
  3487     globalResizeMode = mode;
       
  3488     for (int i = 0; i < sectionSpans.count(); ++i)
       
  3489         sectionSpans[i].resizeMode = mode;
       
  3490 }
       
  3491 
       
  3492 int QHeaderViewPrivate::viewSectionSizeHint(int logical) const
       
  3493 {
       
  3494     if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(parent)) {
       
  3495         return (orientation == Qt::Horizontal
       
  3496                 ? view->sizeHintForColumn(logical)
       
  3497                 : view->sizeHintForRow(logical));
       
  3498     }
       
  3499     return 0;
       
  3500 }
       
  3501 
       
  3502 int QHeaderViewPrivate::adjustedVisualIndex(int visualIndex) const
       
  3503 {
       
  3504     if (hiddenSectionSize.count() > 0) {
       
  3505         int adjustedVisualIndex = visualIndex;
       
  3506         int currentVisualIndex = 0;
       
  3507         for (int i = 0; i < sectionSpans.count(); ++i) {
       
  3508             if (sectionSpans.at(i).size == 0)
       
  3509                 adjustedVisualIndex += sectionSpans.at(i).count;
       
  3510             else
       
  3511                 currentVisualIndex += sectionSpans.at(i).count;
       
  3512             if (currentVisualIndex >= visualIndex)
       
  3513                 break;
       
  3514         }
       
  3515         visualIndex = adjustedVisualIndex;
       
  3516     }
       
  3517     return visualIndex;
       
  3518 }
       
  3519 
       
  3520 #ifndef QT_NO_DATASTREAM
       
  3521 void QHeaderViewPrivate::write(QDataStream &out) const
       
  3522 {
       
  3523     out << int(orientation);
       
  3524     out << int(sortIndicatorOrder);
       
  3525     out << sortIndicatorSection;
       
  3526     out << sortIndicatorShown;
       
  3527 
       
  3528     out << visualIndices;
       
  3529     out << logicalIndices;
       
  3530 
       
  3531     out << sectionHidden;
       
  3532     out << hiddenSectionSize;
       
  3533 
       
  3534     out << length;
       
  3535     out << sectionCount;
       
  3536     out << movableSections;
       
  3537     out << clickableSections;
       
  3538     out << highlightSelected;
       
  3539     out << stretchLastSection;
       
  3540     out << cascadingResizing;
       
  3541     out << stretchSections;
       
  3542     out << contentsSections;
       
  3543     out << defaultSectionSize;
       
  3544     out << minimumSectionSize;
       
  3545 
       
  3546     out << int(defaultAlignment);
       
  3547     out << int(globalResizeMode);
       
  3548 
       
  3549     out << sectionSpans;
       
  3550 }
       
  3551 
       
  3552 bool QHeaderViewPrivate::read(QDataStream &in)
       
  3553 {
       
  3554     int orient, order, align, global;
       
  3555     in >> orient;
       
  3556     orientation = (Qt::Orientation)orient;
       
  3557 
       
  3558     in >> order;
       
  3559     sortIndicatorOrder = (Qt::SortOrder)order;
       
  3560 
       
  3561     in >> sortIndicatorSection;
       
  3562     in >> sortIndicatorShown;
       
  3563 
       
  3564     in >> visualIndices;
       
  3565     in >> logicalIndices;
       
  3566 
       
  3567     in >> sectionHidden;
       
  3568     in >> hiddenSectionSize;
       
  3569 
       
  3570     in >> length;
       
  3571     in >> sectionCount;
       
  3572     in >> movableSections;
       
  3573     in >> clickableSections;
       
  3574     in >> highlightSelected;
       
  3575     in >> stretchLastSection;
       
  3576     in >> cascadingResizing;
       
  3577     in >> stretchSections;
       
  3578     in >> contentsSections;
       
  3579     in >> defaultSectionSize;
       
  3580     in >> minimumSectionSize;
       
  3581 
       
  3582     in >> align;
       
  3583     defaultAlignment = Qt::Alignment(align);
       
  3584 
       
  3585     in >> global;
       
  3586     globalResizeMode = (QHeaderView::ResizeMode)global;
       
  3587 
       
  3588     in >> sectionSpans;
       
  3589 
       
  3590     return true;
       
  3591 }
       
  3592 
       
  3593 #endif // QT_NO_DATASTREAM
       
  3594 
       
  3595 QT_END_NAMESPACE
       
  3596 
       
  3597 #endif // QT_NO_ITEMVIEWS
       
  3598 
       
  3599 #include "moc_qheaderview.cpp"