src/qt3support/widgets/q3header.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 Qt3Support 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 "q3header.h"
       
    43 #ifndef QT_NO_HEADER
       
    44 #include "qapplication.h"
       
    45 #include "qbitarray.h"
       
    46 #include "qcursor.h"
       
    47 #include "qdrawutil.h"
       
    48 #include "qevent.h"
       
    49 #include "qpainter.h"
       
    50 #include "qpixmap.h"
       
    51 #include "qstyle.h"
       
    52 #include "qstyleoption.h"
       
    53 #include "qvector.h"
       
    54 
       
    55 QT_BEGIN_NAMESPACE
       
    56 
       
    57 class Q3HeaderData
       
    58 {
       
    59 public:
       
    60     Q3HeaderData(int n)
       
    61     {
       
    62         count = n;
       
    63         sizes.resize(n);
       
    64         positions.resize(n);
       
    65         labels.resize(n);
       
    66         nullStringLabels.resize(n);
       
    67         icons.resize(n);
       
    68         i2s.resize(n);
       
    69         s2i.resize(n);
       
    70         clicks.resize(n);
       
    71         resize.resize(n);
       
    72         int p =0;
       
    73         for (int i = 0; i < n; i ++) {
       
    74             sizes[i] = 88;
       
    75             i2s[i] = i;
       
    76             s2i[i] = i;
       
    77             positions[i] = p;
       
    78             p += sizes[i];
       
    79         }
       
    80         clicks_default = true;
       
    81         resize_default = true;
       
    82         clicks.fill(clicks_default);
       
    83         resize.fill(resize_default);
       
    84         move = true;
       
    85         sortSection = -1;
       
    86         sortDirection = true;
       
    87         positionsDirty = true;
       
    88         lastPos = 0;
       
    89         fullSize = -2;
       
    90         pos_dirty = false;
       
    91         is_a_table_header = false;
       
    92         focusIdx = 0;
       
    93     }
       
    94     ~Q3HeaderData()
       
    95     {
       
    96         for (int i = 0; i < icons.size(); ++i)
       
    97             delete icons.at(i);
       
    98     }
       
    99 
       
   100 
       
   101     QVector<int>        sizes;
       
   102     int height; // we abuse the heights as widths for vertical layout
       
   103     bool heightDirty;
       
   104     QVector<int>        positions; // sorted by index
       
   105     QVector<QString>        labels;
       
   106     QVector<QIcon *> icons;
       
   107     QVector<int>                i2s;
       
   108     QVector<int>                s2i;
       
   109 
       
   110     QBitArray           clicks;
       
   111     QBitArray           resize;
       
   112     QBitArray           nullStringLabels;
       
   113     uint move : 1;
       
   114     uint clicks_default : 1; // default value for new clicks bits
       
   115     uint resize_default : 1; // default value for new resize bits
       
   116     uint pos_dirty : 1;
       
   117     uint is_a_table_header : 1;
       
   118     bool sortDirection;
       
   119     bool positionsDirty;
       
   120     int sortSection;
       
   121     int count;
       
   122     int lastPos;
       
   123     int fullSize;
       
   124     int focusIdx;
       
   125     int pressDelta;
       
   126 
       
   127     int sectionAt(int pos) {
       
   128         // positions is sorted by index, not by section
       
   129         if (!count)
       
   130             return -1;
       
   131         int l = 0;
       
   132         int r = count - 1;
       
   133         int i = ((l+r+1) / 2);
       
   134         while (r - l) {
       
   135             if (positions[i] > pos)
       
   136                 r = i -1;
       
   137             else
       
   138                 l = i;
       
   139             i = ((l+r+1) / 2);
       
   140         }
       
   141         if (positions[i] <= pos && pos <= positions[i] + sizes[i2s[i]])
       
   142             return i2s[i];
       
   143         return -1;
       
   144     }
       
   145 };
       
   146 
       
   147 static QStyleOptionHeader getStyleOption(const Q3Header *header, int section)
       
   148 {
       
   149     QStyleOptionHeader opt;
       
   150     opt.init(header);
       
   151     opt.section = section;
       
   152     opt.textAlignment = Qt::AlignVCenter;
       
   153     opt.iconAlignment = Qt::AlignVCenter;
       
   154     if (header->iconSet(section))
       
   155         opt.icon = *header->iconSet(section);
       
   156     opt.text = header->label(section);
       
   157     if (header->orientation() == Qt::Horizontal)
       
   158         opt.state = QStyle::State_Horizontal;
       
   159     return opt;
       
   160 }
       
   161 
       
   162 bool qt_get_null_label_bit(Q3HeaderData *data, int section)
       
   163 {
       
   164     return data->nullStringLabels.testBit(section);
       
   165 }
       
   166 
       
   167 void qt_set_null_label_bit(Q3HeaderData *data, int section, bool b)
       
   168 {
       
   169     data->nullStringLabels.setBit(section, b);
       
   170 }
       
   171 
       
   172 /*!
       
   173     \class Q3Header
       
   174     \brief The Q3Header class provides a header row or column, e.g. for
       
   175     tables and listviews.
       
   176 
       
   177     \compat
       
   178 
       
   179     This class provides a header, e.g. a vertical header to display
       
   180     row labels, or a horizontal header to display column labels. It is
       
   181     used by Q3Table and Q3ListView for example.
       
   182 
       
   183     A header is composed of one or more \e sections, each of which can
       
   184     display a text label and an \link QIcon icon\endlink. A sort
       
   185     indicator (an arrow) can also be displayed using
       
   186     setSortIndicator().
       
   187 
       
   188     Sections are added with addLabel() and removed with removeLabel().
       
   189     The label and icon are set in addLabel() and can be changed
       
   190     later with setLabel(). Use count() to retrieve the number of
       
   191     sections in the header.
       
   192 
       
   193     The orientation of the header is set with setOrientation(). If
       
   194     setStretchEnabled() is true, the sections will expand to take up
       
   195     the full width (height for vertical headers) of the header. The
       
   196     user can resize the sections manually if setResizeEnabled() is
       
   197     true. Call adjustHeaderSize() to have the sections resize to
       
   198     occupy the full width (or height).
       
   199 
       
   200     A section can be moved with moveSection(). If setMovingEnabled()
       
   201     is true (the default)the user may drag a section from one position
       
   202     to another. If a section is moved, the index positions at which
       
   203     sections were added (with addLabel()), may not be the same after the
       
   204     move. You don't have to worry about this in practice because the
       
   205     Q3Header API works in terms of section numbers, so it doesn't matter
       
   206     where a particular section has been moved to.
       
   207 
       
   208     If you want the current index position of a section call
       
   209     mapToIndex() giving it the section number. (This is the number
       
   210     returned by the addLabel() call which created the section.) If you
       
   211     want to get the section number of a section at a particular index
       
   212     position call mapToSection() giving it the index number.
       
   213 
       
   214     Here's an example to clarify mapToSection() and mapToIndex():
       
   215 
       
   216     \table
       
   217     \header \i41 Index positions
       
   218     \row \i 0 \i 1 \i 2 \i 3
       
   219     \header \i41 Original section ordering
       
   220     \row \i Sect 0 \i Sect 1 \i Sect 2 \i Sect 3
       
   221     \header \i41 Ordering after the user moves a section
       
   222     \row \i Sect 0 \i Sect 2 \i Sect 3 \i Sect 1
       
   223     \endtable
       
   224 
       
   225     \table
       
   226     \header \i \e k \i mapToSection(\e k) \i mapToIndex(\e k)
       
   227     \row \i 0 \i 0 \i 0
       
   228     \row \i 1 \i 2 \i 3
       
   229     \row \i 2 \i 3 \i 1
       
   230     \row \i 3 \i 1 \i 2
       
   231     \endtable
       
   232 
       
   233     In the example above, if we wanted to find out which section is at
       
   234     index position 3 we'd call mapToSection(3) and get a section
       
   235     number of 1 since section 1 was moved. Similarly, if we wanted to
       
   236     know which index position section 2 occupied we'd call
       
   237     mapToIndex(2) and get an index of 1.
       
   238 
       
   239     Q3Header provides the clicked(), pressed() and released() signals.
       
   240     If the user changes the size of a section, the sizeChange() signal
       
   241     is emitted. If you want to have a sizeChange() signal emitted
       
   242     continuously whilst the user is resizing (rather than just after
       
   243     the resizing is finished), use setTracking(). If the user moves a
       
   244     section the indexChange() signal is emitted.
       
   245 
       
   246     \sa Q3ListView Q3Table
       
   247 */
       
   248 
       
   249 
       
   250 
       
   251 /*!
       
   252     Constructs a horizontal header called \a name, with parent \a
       
   253     parent.
       
   254 */
       
   255 
       
   256 Q3Header::Q3Header(QWidget *parent, const char *name)
       
   257     : QWidget(parent, name, Qt::WStaticContents)
       
   258 {
       
   259     orient = Qt::Horizontal;
       
   260     init(0);
       
   261 }
       
   262 
       
   263 /*!
       
   264     Constructs a horizontal header called \a name, with \a n sections
       
   265     and parent \a parent.
       
   266 */
       
   267 
       
   268 Q3Header::Q3Header(int n, QWidget *parent, const char *name)
       
   269     : QWidget(parent, name, Qt::WStaticContents)
       
   270 {
       
   271     orient = Qt::Horizontal;
       
   272     init(n);
       
   273 }
       
   274 
       
   275 /*!
       
   276     Destroys the header and all its sections.
       
   277 */
       
   278 
       
   279 Q3Header::~Q3Header()
       
   280 {
       
   281     delete d;
       
   282     d = 0;
       
   283 }
       
   284 
       
   285 /*! \reimp
       
   286  */
       
   287 
       
   288 void Q3Header::showEvent(QShowEvent *e)
       
   289 {
       
   290     calculatePositions();
       
   291     QWidget::showEvent(e);
       
   292 }
       
   293 
       
   294 /*!
       
   295     \fn void Q3Header::sizeChange(int section, int oldSize, int newSize)
       
   296 
       
   297     This signal is emitted when the user has changed the size of a \a
       
   298     section from \a oldSize to \a newSize. This signal is typically
       
   299     connected to a slot that repaints the table or list that contains
       
   300     the header.
       
   301 */
       
   302 
       
   303 /*!
       
   304     \fn void Q3Header::clicked(int section)
       
   305 
       
   306     If isClickEnabled() is true, this signal is emitted when the user
       
   307     clicks section \a section.
       
   308 
       
   309     \sa pressed(), released()
       
   310 */
       
   311 
       
   312 /*!
       
   313     \fn void Q3Header::pressed(int section)
       
   314 
       
   315     This signal is emitted when the user presses section \a section
       
   316     down.
       
   317 
       
   318     \sa released()
       
   319 */
       
   320 
       
   321 /*!
       
   322     \fn void Q3Header::released(int section)
       
   323 
       
   324     This signal is emitted when section \a section is released.
       
   325 
       
   326     \sa pressed()
       
   327 */
       
   328 
       
   329 
       
   330 /*!
       
   331     \fn void Q3Header::indexChange(int section, int fromIndex, int toIndex)
       
   332 
       
   333     This signal is emitted when the user moves section \a section from
       
   334     index position \a fromIndex, to index position \a toIndex.
       
   335 */
       
   336 
       
   337 /*!
       
   338   \fn void Q3Header::moved(int fromIndex, int toIndex)
       
   339 
       
   340   Use indexChange() instead.
       
   341 
       
   342   This signal is emitted when the user has moved the section which
       
   343   is displayed at the index \a fromIndex to the index \a toIndex.
       
   344 */
       
   345 
       
   346 /*!
       
   347   \fn void Q3Header::sectionClicked(int index)
       
   348 
       
   349   Use clicked() instead.
       
   350 
       
   351   This signal is emitted when a part of the header is clicked. \a
       
   352   index is the index at which the section is displayed.
       
   353 
       
   354   In a list view this signal would typically be connected to a slot
       
   355   that sorts the specified column (or row).
       
   356 */
       
   357 
       
   358 /*! \fn int Q3Header::cellSize(int) const
       
   359 
       
   360   Use sectionSize() instead.
       
   361 
       
   362   Returns the size in pixels of the section that is displayed at
       
   363   the index \a i.
       
   364 */
       
   365 
       
   366 /*!
       
   367     \fn void Q3Header::sectionHandleDoubleClicked(int section)
       
   368 
       
   369     This signal is emitted when the user doubleclicks on the edge
       
   370     (handle) of section \a section.
       
   371 */
       
   372 
       
   373 /*!
       
   374 
       
   375   Use sectionPos() instead.
       
   376 
       
   377   Returns the position in pixels of the section that is displayed at the
       
   378   index \a i. The  position is measured from the start of the header.
       
   379 */
       
   380 
       
   381 int Q3Header::cellPos(int i) const
       
   382 {
       
   383     if (i == count() && i > 0)
       
   384         return  d->positions[i-1] + d->sizes[d->i2s[i-1]]; // compatibility
       
   385     return sectionPos(mapToSection(i));
       
   386 }
       
   387 
       
   388 
       
   389 /*!
       
   390     \property Q3Header::count
       
   391     \brief the number of sections in the header
       
   392 */
       
   393 
       
   394 int Q3Header::count() const
       
   395 {
       
   396     return d->count;
       
   397 }
       
   398 
       
   399 
       
   400 /*!
       
   401     \property Q3Header::tracking
       
   402     \brief whether the sizeChange() signal is emitted continuously
       
   403 
       
   404     If tracking is on, the sizeChange() signal is emitted continuously
       
   405     while the mouse is moved (i.e. when the header is resized),
       
   406     otherwise it is only emitted when the mouse button is released at
       
   407     the end of resizing.
       
   408 
       
   409     Tracking defaults to false.
       
   410 */
       
   411 
       
   412 
       
   413 /*
       
   414     Initializes with \a n columns.
       
   415 */
       
   416 void Q3Header::init(int n)
       
   417 {
       
   418     state = Idle;
       
   419     cachedPos = 0; // unused
       
   420     d = new Q3HeaderData(n);
       
   421     d->height = 0;
       
   422     d->heightDirty = true;
       
   423     offs = 0;
       
   424     if(reverse())
       
   425         offs = d->lastPos - width();
       
   426     oldHandleIdx = oldHIdxSize = handleIdx = 0;
       
   427 
       
   428     setMouseTracking(true);
       
   429     trackingIsOn = false;
       
   430     setBackgroundRole(QPalette::Button);
       
   431     setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
       
   432     setAttribute(Qt::WA_PaintOutsidePaintEvent);
       
   433 }
       
   434 
       
   435 /*!
       
   436     \property Q3Header::orientation
       
   437     \brief the header's orientation
       
   438 
       
   439     The orientation is either Qt::Vertical or Qt::Horizontal (the
       
   440     default).
       
   441 
       
   442     Call setOrientation() before adding labels if you don't provide a
       
   443     size parameter otherwise the sizes will be incorrect.
       
   444 */
       
   445 
       
   446 void Q3Header::setOrientation(Qt::Orientation orientation)
       
   447 {
       
   448     if (orient == orientation)
       
   449         return;
       
   450     orient = orientation;
       
   451     if (orient == Qt::Horizontal)
       
   452         setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
       
   453     else
       
   454         setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred));
       
   455     update();
       
   456     updateGeometry();
       
   457 }
       
   458 
       
   459 
       
   460 /*
       
   461     Paints a rectangle starting at \a p, with length \s.
       
   462 */
       
   463 void Q3Header::paintRect(int p, int s)
       
   464 {
       
   465     QPainter paint(this);
       
   466     paint.setPen(QPen(Qt::black, 1, Qt::DotLine));
       
   467     if (reverse())
       
   468         paint.drawRect(p - s, 3, s, height() - 5);
       
   469     else if (orient == Qt::Horizontal)
       
   470         paint.drawRect(p, 3, s, height() - 5);
       
   471     else
       
   472         paint.drawRect(3, p, height() - 5, s);
       
   473 }
       
   474 
       
   475 /*
       
   476   Marks the division line at \a idx.
       
   477 */
       
   478 void Q3Header::markLine(int idx)
       
   479 {
       
   480     QPainter paint(this);
       
   481     paint.setPen(QPen(Qt::black, 1, Qt::DotLine));
       
   482     int MARKSIZE = style()->pixelMetric(QStyle::PM_HeaderMarkSize);
       
   483     int p = pPos(idx);
       
   484     int x = p - MARKSIZE/2;
       
   485     int y = 2;
       
   486     int x2 = p + MARKSIZE/2;
       
   487     int y2 = height() - 3;
       
   488     if (orient == Qt::Vertical) {
       
   489         int t = x; x = y; y = t;
       
   490         t = x2; x2 = y2; y2 = t;
       
   491     }
       
   492 
       
   493     paint.drawLine(x, y, x2, y);
       
   494     paint.drawLine(x, y+1, x2, y+1);
       
   495 
       
   496     paint.drawLine(x, y2, x2, y2);
       
   497     paint.drawLine(x, y2-1, x2, y2-1);
       
   498 
       
   499     paint.drawLine(x, y, x, y2);
       
   500     paint.drawLine(x+1, y, x+1, y2);
       
   501 
       
   502     paint.drawLine(x2, y, x2, y2);
       
   503     paint.drawLine(x2-1, y, x2-1, y2);
       
   504 }
       
   505 
       
   506 /*
       
   507   Removes the mark at the division line at \a idx.
       
   508 */
       
   509 void Q3Header::unMarkLine(int idx)
       
   510 {
       
   511     if (idx < 0)
       
   512         return;
       
   513     int MARKSIZE = style()->pixelMetric(QStyle::PM_HeaderMarkSize);
       
   514     int p = pPos(idx);
       
   515     int x = p - MARKSIZE/2;
       
   516     int y = 2;
       
   517     int x2 = p + MARKSIZE/2;
       
   518     int y2 = height() - 3;
       
   519     if (orient == Qt::Vertical) {
       
   520         int t = x; x = y; y = t;
       
   521         t = x2; x2 = y2; y2 = t;
       
   522     }
       
   523     repaint(x, y, x2-x+1, y2-y+1);
       
   524 }
       
   525 
       
   526 /*! \fn int Q3Header::cellAt(int) const
       
   527 
       
   528   Use sectionAt() instead.
       
   529 
       
   530   Returns the index at which the section is displayed, which contains
       
   531   \a pos in widget coordinates, or -1 if \a pos is outside the header
       
   532   sections.
       
   533 */
       
   534 
       
   535 /*
       
   536   Tries to find a line that is not a neighbor of  \c handleIdx.
       
   537 */
       
   538 int Q3Header::findLine(int c)
       
   539 {
       
   540     int i = 0;
       
   541     if (c > d->lastPos || (reverse() && c < 0)) {
       
   542         return d->count;
       
   543     } else {
       
   544         int section = sectionAt(c);
       
   545         if (section < 0)
       
   546             return handleIdx;
       
   547         i = d->s2i[section];
       
   548     }
       
   549     int MARKSIZE = style()->pixelMetric(QStyle::PM_HeaderMarkSize);
       
   550     if (i == handleIdx)
       
   551         return i;
       
   552     if (i == handleIdx - 1 &&  pPos(handleIdx) - c > MARKSIZE/2)
       
   553         return i;
       
   554     if (i == handleIdx + 1 && c - pPos(i) > MARKSIZE/2)
       
   555         return i + 1;
       
   556     if (c - pPos(i) > pSize(i) / 2)
       
   557         return i + 1;
       
   558     else
       
   559         return i;
       
   560 }
       
   561 
       
   562 /*!
       
   563     Returns the handle at position \a p, or -1 if there is no handle at \a p.
       
   564 */
       
   565 int Q3Header::handleAt(int p)
       
   566 {
       
   567     int section = d->sectionAt(p);
       
   568     if (section >= 0) {
       
   569         int GripMargin = (bool)d->resize[section] ?
       
   570             style()->pixelMetric(QStyle::PM_HeaderGripMargin) : 0;
       
   571         int index = d->s2i[section];
       
   572         if ((index > 0 && p < d->positions[index] + GripMargin) ||
       
   573             (p > d->positions[index] + d->sizes[section] - GripMargin)) {
       
   574             if (index > 0 && p < d->positions[index]  + GripMargin)
       
   575                 section = d->i2s[--index];
       
   576             // don't show icon if streaching is enabled it is at the end of the last section
       
   577             if (d->resize.testBit(section) && (d->fullSize == -2 || index != count() - 1)) {
       
   578                 return section;
       
   579             }
       
   580         }
       
   581     }
       
   582 
       
   583     return -1;
       
   584 }
       
   585 
       
   586 /*!
       
   587   Use moveSection() instead.
       
   588 
       
   589   Moves the section that is currently displayed at index \a fromIdx
       
   590   to index \a toIdx.
       
   591 */
       
   592 
       
   593 void Q3Header::moveCell(int fromIdx, int toIdx)
       
   594 {
       
   595     moveSection(mapToSection(fromIdx), toIdx);
       
   596 }
       
   597 
       
   598 
       
   599 
       
   600 /*!
       
   601   Move and signal and repaint.
       
   602  */
       
   603 
       
   604 void Q3Header::handleColumnMove(int fromIdx, int toIdx)
       
   605 {
       
   606     int s = d->i2s[fromIdx];
       
   607     if (fromIdx < toIdx)
       
   608         toIdx++; //Convert to
       
   609     QRect r = sRect(fromIdx);
       
   610     r |= sRect(toIdx);
       
   611     moveSection(s, toIdx);
       
   612     update(r);
       
   613     emit moved(fromIdx, toIdx);
       
   614     emit indexChange(s, fromIdx, toIdx);
       
   615 }
       
   616 
       
   617 /*!
       
   618   \reimp
       
   619 */
       
   620 void Q3Header::keyPressEvent(QKeyEvent *e)
       
   621 {
       
   622     int i = d->focusIdx;
       
   623     if (e->key() == Qt::Key_Space) {
       
   624         //don't do it if we're doing something with the mouse
       
   625         if (state == Idle && d->clicks[d->i2s[d->focusIdx] ]) {
       
   626             handleIdx = i;
       
   627             state = Pressed;
       
   628             repaint(sRect(handleIdx));
       
   629             emit pressed(d->i2s[i]);
       
   630         }
       
   631     } else if ((orientation() == Qt::Horizontal && (e->key() == Qt::Key_Right || e->key() == Qt::Key_Left))
       
   632                || (orientation() == Qt::Vertical && (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down))) {
       
   633         int dir = e->key() == Qt::Key_Right || e->key() == Qt::Key_Down ? 1 : -1;
       
   634         int s = d->i2s[i];
       
   635         if (e->state() & Qt::ControlButton  && d->resize[s]) {
       
   636             //resize
       
   637             int step = e->state() & Qt::ShiftButton ? dir : 10*dir;
       
   638             int c = d->positions[i] + d->sizes[s] +  step;
       
   639             handleColumnResize(i, c, true);
       
   640         } else         if (e->state() & (Qt::AltButton|Qt::MetaButton) && d->move) {
       
   641             //move section
       
   642             int i2 = (i + count() + dir) % count();
       
   643             d->focusIdx = i2;
       
   644             handleColumnMove(i, i2);
       
   645         } else {
       
   646             //focus on different section
       
   647             QRect r = sRect(d->focusIdx);
       
   648             d->focusIdx = (d->focusIdx + count() + dir) % count();
       
   649             r |= sRect(d->focusIdx);
       
   650             update(r);
       
   651         }
       
   652     } else {
       
   653         e->ignore();
       
   654     }
       
   655 }
       
   656 
       
   657 /*!
       
   658   \reimp
       
   659 */
       
   660 void Q3Header::keyReleaseEvent(QKeyEvent *e)
       
   661 {
       
   662     switch (e->key()) {
       
   663     case Qt::Key_Space:
       
   664         //double check that this wasn't started with the mouse
       
   665         if (state == Pressed && handleIdx == d->focusIdx) {
       
   666             repaint(sRect(handleIdx));
       
   667             int section = d->i2s[d->focusIdx];
       
   668             emit released(section);
       
   669             emit sectionClicked(handleIdx);
       
   670             emit clicked(section);
       
   671             state = Idle;
       
   672             handleIdx = -1;
       
   673         }
       
   674         break;
       
   675     default:
       
   676         e->ignore();
       
   677     }
       
   678 }
       
   679 
       
   680 
       
   681 /*!
       
   682   \reimp
       
   683 */
       
   684 void Q3Header::mousePressEvent(QMouseEvent *e)
       
   685 {
       
   686     if (e->button() != Qt::LeftButton || state != Idle)
       
   687         return;
       
   688     oldHIdxSize = handleIdx;
       
   689     handleIdx = 0;
       
   690     int c = orient == Qt::Horizontal ? e->pos().x() : e->pos().y();
       
   691     c += offset();
       
   692     if (reverse())
       
   693         c = d->lastPos - c;
       
   694 
       
   695     int section = d->sectionAt(c);
       
   696     if (section < 0)
       
   697         return;
       
   698     int GripMargin = (bool)d->resize[section] ?
       
   699         style()->pixelMetric(QStyle::PM_HeaderGripMargin) : 0;
       
   700     int index = d->s2i[section];
       
   701 
       
   702     if ((index > 0 && c < d->positions[index] + GripMargin) ||
       
   703          (c > d->positions[index] + d->sizes[section] - GripMargin)) {
       
   704         if (c < d->positions[index] + GripMargin)
       
   705             handleIdx = index-1;
       
   706         else
       
   707             handleIdx = index;
       
   708         if (d->lastPos <= (orient == Qt::Horizontal ? width() :
       
   709                              height()) && d->fullSize != -2 && handleIdx == count() - 1) {
       
   710             handleIdx = -1;
       
   711             return;
       
   712         }
       
   713         oldHIdxSize = d->sizes[d->i2s[handleIdx]];
       
   714         state = d->resize[d->i2s[handleIdx] ] ? Sliding : Blocked;
       
   715     } else if (index >= 0) {
       
   716         oldHandleIdx = handleIdx = index;
       
   717         moveToIdx = -1;
       
   718         state = d->clicks[d->i2s[handleIdx] ] ? Pressed : Blocked;
       
   719         clickPos = c;
       
   720         repaint(sRect(handleIdx));
       
   721         if(oldHandleIdx != handleIdx)
       
   722             repaint(sRect(oldHandleIdx));
       
   723         emit pressed(section);
       
   724     }
       
   725 
       
   726     d->pressDelta = c - (d->positions[handleIdx] + d->sizes[d->i2s[handleIdx]]);
       
   727 }
       
   728 
       
   729 /*!
       
   730   \reimp
       
   731 */
       
   732 void Q3Header::mouseReleaseEvent(QMouseEvent *e)
       
   733 {
       
   734     if (e->button() != Qt::LeftButton)
       
   735         return;
       
   736     int oldOldHandleIdx = oldHandleIdx;
       
   737     State oldState = state;
       
   738     state = Idle;
       
   739     switch (oldState) {
       
   740     case Pressed: {
       
   741         int section = d->i2s[handleIdx];
       
   742         emit released(section);
       
   743         if (sRect(handleIdx).contains(e->pos())) {
       
   744             oldHandleIdx = handleIdx;
       
   745             emit sectionClicked(handleIdx);
       
   746             emit clicked(section);
       
   747         } else {
       
   748             handleIdx = oldHandleIdx;
       
   749         }
       
   750         repaint(sRect(handleIdx));
       
   751         if (oldOldHandleIdx != handleIdx)
       
   752             repaint(sRect(oldOldHandleIdx));
       
   753         } break;
       
   754     case Sliding: {
       
   755         int c = orient == Qt::Horizontal ? e->pos().x() : e->pos().y();
       
   756         c += offset();
       
   757         if (reverse())
       
   758             c = d->lastPos - c;
       
   759         handleColumnResize(handleIdx, c - d->pressDelta, true);
       
   760     } break;
       
   761     case Moving: {
       
   762 #ifndef QT_NO_CURSOR
       
   763         unsetCursor();
       
   764 #endif
       
   765         int section = d->i2s[handleIdx];
       
   766         if (handleIdx != moveToIdx && moveToIdx != -1) {
       
   767             moveSection(section, moveToIdx);
       
   768             handleIdx = oldHandleIdx;
       
   769             emit moved(handleIdx, moveToIdx);
       
   770             emit indexChange(section, handleIdx, moveToIdx);
       
   771             emit released(section);
       
   772             repaint(); // a bit overkill, but removes the handle as well
       
   773         } else {
       
   774             if (sRect(handleIdx).contains(e->pos())) {
       
   775                 oldHandleIdx = handleIdx;
       
   776                 emit released(section);
       
   777                 emit sectionClicked(handleIdx);
       
   778                 emit clicked(section);
       
   779             } else {
       
   780                 handleIdx = oldHandleIdx;
       
   781             }
       
   782             repaint(sRect(handleIdx));
       
   783             if(oldOldHandleIdx != handleIdx)
       
   784                 repaint(sRect(oldOldHandleIdx));
       
   785         }
       
   786         break;
       
   787     }
       
   788     case Blocked:
       
   789         //nothing
       
   790         break;
       
   791     default:
       
   792         // empty, probably.  Idle, at any rate.
       
   793         break;
       
   794     }
       
   795 }
       
   796 
       
   797 /*!
       
   798   \reimp
       
   799 */
       
   800 void Q3Header::mouseMoveEvent(QMouseEvent *e)
       
   801 {
       
   802     int c = orient == Qt::Horizontal ? e->pos().x() : e->pos().y();
       
   803     c += offset();
       
   804 
       
   805     int pos = c;
       
   806     if(reverse())
       
   807         c = d->lastPos - c;
       
   808 
       
   809     switch(state) {
       
   810     case Idle:
       
   811 #ifndef QT_NO_CURSOR
       
   812         if (handleAt(c) < 0)
       
   813             unsetCursor();
       
   814         else if (orient == Qt::Horizontal)
       
   815             setCursor(Qt::splitHCursor);
       
   816         else
       
   817             setCursor(Qt::splitVCursor);
       
   818 #endif
       
   819         break;
       
   820     case Blocked:
       
   821         break;
       
   822     case Pressed:
       
   823         if (QABS(c - clickPos) > 4 && d->move) {
       
   824             state = Moving;
       
   825             moveToIdx = -1;
       
   826 #ifndef QT_NO_CURSOR
       
   827             if (orient == Qt::Horizontal)
       
   828                 setCursor(Qt::SizeHorCursor);
       
   829             else
       
   830                 setCursor(Qt::SizeVerCursor);
       
   831 #endif
       
   832         }
       
   833         break;
       
   834     case Sliding:
       
   835         handleColumnResize(handleIdx, c, false, false);
       
   836         break;
       
   837     case Moving: {
       
   838         int newPos = findLine(pos);
       
   839         if (newPos != moveToIdx) {
       
   840             if (moveToIdx == handleIdx || moveToIdx == handleIdx + 1)
       
   841                 repaint(sRect(handleIdx));
       
   842             else
       
   843                 unMarkLine(moveToIdx);
       
   844             moveToIdx = newPos;
       
   845             if (moveToIdx == handleIdx || moveToIdx == handleIdx + 1)
       
   846                 paintRect(pPos(handleIdx), pSize(handleIdx));
       
   847             else
       
   848                 markLine(moveToIdx);
       
   849         }
       
   850         break;
       
   851     }
       
   852     default:
       
   853         qWarning("Q3Header::mouseMoveEvent: (%s) unknown state", objectName().toLocal8Bit().data());
       
   854         break;
       
   855     }
       
   856 }
       
   857 
       
   858 /*! \reimp */
       
   859 
       
   860 void Q3Header::mouseDoubleClickEvent(QMouseEvent *e)
       
   861 {
       
   862     int p = orient == Qt::Horizontal ? e->pos().x() : e->pos().y();
       
   863     p += offset();
       
   864     if(reverse())
       
   865         p = d->lastPos - p;
       
   866 
       
   867     int header = handleAt(p);
       
   868     if (header >= 0)
       
   869         emit sectionHandleDoubleClicked(header);
       
   870 }
       
   871 
       
   872 /*
       
   873   Handles resizing of sections. This means it redraws the relevant parts
       
   874   of the header.
       
   875 */
       
   876 
       
   877 void Q3Header::handleColumnResize(int index, int c, bool final, bool recalcAll)
       
   878 {
       
   879     int section = d->i2s[index];
       
   880     int GripMargin = (bool)d->resize[section] ?
       
   881         style()->pixelMetric(QStyle::PM_HeaderGripMargin) : 0;
       
   882     int lim = d->positions[index] + 2*GripMargin;
       
   883     if (c == lim)
       
   884         return;
       
   885     if (c < lim)
       
   886         c = lim;
       
   887     int oldSize = d->sizes[section];
       
   888     int newSize = c - d->positions[index];
       
   889     d->sizes[section] = newSize;
       
   890 
       
   891     calculatePositions(!recalcAll, !recalcAll ? section : 0);
       
   892 
       
   893     int pos = d->positions[index]-offset();
       
   894     if(reverse()) // repaint the whole thing. Could be optimized (lars)
       
   895         repaint(0, 0, width(), height());
       
   896     else if (orient == Qt::Horizontal)
       
   897         repaint(pos, 0, width() - pos, height());
       
   898     else
       
   899         repaint(0, pos, width(), height() - pos);
       
   900 
       
   901     int os = 0, ns = 0;
       
   902     if (tracking() && oldSize != newSize) {
       
   903         os = oldSize;
       
   904         ns = newSize;
       
   905         emit sizeChange(section, oldSize, newSize);
       
   906     } else if (!tracking() && final && oldHIdxSize != newSize) {
       
   907         os = oldHIdxSize;
       
   908         ns = newSize;
       
   909         emit sizeChange(section, oldHIdxSize, newSize);
       
   910     }
       
   911 
       
   912     if (os != ns) {
       
   913         if (d->fullSize == -1) {
       
   914             d->fullSize = count() - 1;
       
   915             adjustHeaderSize();
       
   916             d->fullSize = -1;
       
   917         } else if (d->fullSize >= 0) {
       
   918             int old = d->fullSize;
       
   919             d->fullSize = count() - 1;
       
   920             adjustHeaderSize();
       
   921             d->fullSize = old;
       
   922         }
       
   923     }
       
   924 }
       
   925 
       
   926 /*!
       
   927     Returns the rectangle covered by the section at index \a index.
       
   928 */
       
   929 
       
   930 QRect Q3Header::sRect(int index)
       
   931 {
       
   932 
       
   933     int section = mapToSection(index);
       
   934     if (count() > 0 && index >= count()) {
       
   935         int s = d->positions[count() - 1] - offset() +
       
   936                 d->sizes[mapToSection(count() - 1)];
       
   937         if (orient == Qt::Horizontal)
       
   938             return QRect(s, 0, width() - s + 10, height());
       
   939         else
       
   940             return QRect(0, s, width(), height() - s + 10);
       
   941     }
       
   942     if (section < 0)
       
   943         return rect(); // ### eeeeevil
       
   944 
       
   945     if (reverse())
       
   946         return QRect( d->lastPos - d->positions[index] - d->sizes[section] -offset(),
       
   947                        0, d->sizes[section], height());
       
   948     else if (orient == Qt::Horizontal)
       
   949         return QRect( d->positions[index]-offset(), 0, d->sizes[section], height());
       
   950     else
       
   951         return QRect(0, d->positions[index]-offset(), width(), d->sizes[section]);
       
   952 }
       
   953 
       
   954 /*!
       
   955     Returns the rectangle covered by section \a section.
       
   956 */
       
   957 
       
   958 QRect Q3Header::sectionRect(int section) const
       
   959 {
       
   960     int index = mapToIndex(section);
       
   961     if (section < 0)
       
   962         return rect(); // ### eeeeevil
       
   963 
       
   964     if (reverse())
       
   965         return QRect( d->lastPos - d->positions[index] - d->sizes[section] -offset(),
       
   966                        0, d->sizes[section], height());
       
   967     else if (orient == Qt::Horizontal)
       
   968         return QRect( d->positions[index]-offset(), 0, d->sizes[section], height());
       
   969     else
       
   970         return QRect(0, d->positions[index]-offset(), width(), d->sizes[section]);
       
   971 }
       
   972 
       
   973 /*!
       
   974     \overload
       
   975 
       
   976     Sets the icon for section \a section to \a icon and the text to
       
   977     \a s. The section's width is set to \a size if \a size \>= 0;
       
   978     otherwise it is left unchanged.
       
   979 
       
   980     If the section does not exist, nothing happens.
       
   981 */
       
   982 
       
   983 void Q3Header::setLabel(int section, const QIcon& icon,
       
   984                         const QString &s, int size)
       
   985 {
       
   986     if (section < 0 || section >= count())
       
   987         return;
       
   988     delete d->icons[section];
       
   989     d->icons[section] = new QIcon(icon);
       
   990     setLabel(section, s, size);
       
   991 }
       
   992 
       
   993 /*!
       
   994     Sets the text of section \a section to \a s. The section's width
       
   995     is set to \a size if \a size \>= 0; otherwise it is left
       
   996     unchanged. Any icon set that has been set for this section remains
       
   997     unchanged.
       
   998 
       
   999     If the section does not exist, nothing happens.
       
  1000 */
       
  1001 void Q3Header::setLabel(int section, const QString &s, int size)
       
  1002 {
       
  1003     if (section < 0 || section >= count())
       
  1004         return;
       
  1005     d->labels[section] = s;
       
  1006     d->nullStringLabels.setBit(section, s.isNull());
       
  1007 
       
  1008     setSectionSizeAndHeight(section, size);
       
  1009 
       
  1010     if (updatesEnabled()) {
       
  1011         updateGeometry();
       
  1012         calculatePositions();
       
  1013         update();
       
  1014     }
       
  1015 }
       
  1016 
       
  1017 
       
  1018 bool qt_qheader_label_return_null_strings = false;
       
  1019 /*!
       
  1020     Returns the text for section \a section. If the section does not
       
  1021     exist, returns an empty string.
       
  1022 */
       
  1023 QString Q3Header::label(int section) const
       
  1024 {
       
  1025     if (section < 0 || section >= count())
       
  1026         return QString();
       
  1027     QString l = d->labels.value(section);
       
  1028     if (!l.isNull())
       
  1029         return l;
       
  1030     if (d->nullStringLabels.testBit(section) || qt_qheader_label_return_null_strings)
       
  1031         return l;
       
  1032     else
       
  1033         return QString::number(section + 1);
       
  1034 }
       
  1035 
       
  1036 /*!
       
  1037     Returns the icon set for section \a section. If the section does
       
  1038     not exist, 0 is returned.
       
  1039 */
       
  1040 
       
  1041 QIcon *Q3Header::iconSet(int section) const
       
  1042 {
       
  1043     if (section < 0 || section >= count())
       
  1044         return 0;
       
  1045     return d->icons[section];
       
  1046 }
       
  1047 
       
  1048 
       
  1049 /*!
       
  1050     \overload
       
  1051 
       
  1052     Adds a new section with icon \a icon and label text \a s.
       
  1053     Returns the index position where the section was added (at the
       
  1054     right for horizontal headers, at the bottom for vertical headers).
       
  1055     The section's width is set to \a size, unless size is negative in
       
  1056     which case the size is calculated taking account of the size of
       
  1057     the text.
       
  1058 */
       
  1059 int Q3Header::addLabel(const QIcon& icon, const QString &s, int size)
       
  1060 {
       
  1061     int n = count() + 1;
       
  1062     d->icons.resize(n + 1);
       
  1063     d->icons.insert(n - 1, new QIcon(icon));
       
  1064     return addLabel(s, size);
       
  1065 }
       
  1066 
       
  1067 /*!
       
  1068     Removes section \a section. If the section does not exist, nothing
       
  1069     happens.
       
  1070 */
       
  1071 void Q3Header::removeLabel(int section)
       
  1072 {
       
  1073     if (section < 0 || section > count() - 1)
       
  1074         return;
       
  1075 
       
  1076     int index = d->s2i[section];
       
  1077     int n = --d->count;
       
  1078     int i;
       
  1079     for (i = section; i < n; ++i) {
       
  1080         d->sizes[i] = d->sizes[i+1];
       
  1081         d->labels[i] = d->labels[i+1];
       
  1082         d->labels[i+1] = QString();
       
  1083         d->nullStringLabels[i] = d->nullStringLabels[i+1];
       
  1084         d->nullStringLabels[i+1] = 0;
       
  1085         d->icons[i] = d->icons[i+1];
       
  1086         d->icons[i+1] = 0;
       
  1087     }
       
  1088 
       
  1089     d->sizes.resize(n);
       
  1090     d->positions.resize(n);
       
  1091     d->labels.resize(n);
       
  1092     d->nullStringLabels.resize(n);
       
  1093     d->icons.resize(n);
       
  1094 
       
  1095     for (i = section; i < n; ++i)
       
  1096         d->s2i[i] = d->s2i[i+1];
       
  1097     d->s2i.resize(n);
       
  1098 
       
  1099     if (updatesEnabled()) {
       
  1100         for (i = 0; i < n; ++i)
       
  1101             if (d->s2i[i] > index)
       
  1102                 --d->s2i[i];
       
  1103     }
       
  1104 
       
  1105     for (i = index; i < n; ++i)
       
  1106         d->i2s[i] = d->i2s[i+1];
       
  1107     d->i2s.resize(n);
       
  1108 
       
  1109     if (updatesEnabled()) {
       
  1110         for (i = 0; i < n; ++i)
       
  1111             if (d->i2s[i] > section)
       
  1112                 --d->i2s[i];
       
  1113     }
       
  1114 
       
  1115     if (updatesEnabled()) {
       
  1116         updateGeometry();
       
  1117         calculatePositions();
       
  1118         update();
       
  1119     }
       
  1120 }
       
  1121 
       
  1122 QSize Q3Header::sectionSizeHint(int section, const QFontMetrics& fm) const
       
  1123 {
       
  1124     int iw = 0;
       
  1125     int ih = 0;
       
  1126     if (d->icons[section] != 0) {
       
  1127         QSize isize = d->icons[section]->pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize),
       
  1128                                                     QIcon::Normal).size();
       
  1129         iw = isize.width() + 2;
       
  1130         ih = isize.height();
       
  1131     }
       
  1132 
       
  1133     QRect bound;
       
  1134     QString label = d->labels[section];
       
  1135     if (!label.isNull() || d->nullStringLabels.testBit(section)) {
       
  1136         int lines = label.count(QLatin1Char('\n')) + 1;
       
  1137         int w = 0;
       
  1138         if (lines > 1) {
       
  1139             bound.setHeight(fm.height() + fm.lineSpacing() * (lines - 1));
       
  1140             QStringList list = label.split(QLatin1Char('\n'));
       
  1141             for (int i=0; i < list.count(); ++i) {
       
  1142                 int tmpw = fm.width(list.at(i));
       
  1143                 w = QMAX(w, tmpw);
       
  1144             }
       
  1145         } else {
       
  1146             bound.setHeight(fm.height());
       
  1147             w = fm.width(label);
       
  1148         }
       
  1149         bound.setWidth(w);
       
  1150     }
       
  1151     int arrowWidth = 0;
       
  1152     if (d->sortSection == section)
       
  1153         arrowWidth = ((orient == Qt::Horizontal ? height() : width()) / 2) + 8;
       
  1154     int height = qMax(bound.height() + 2, ih) + 4;
       
  1155     int width = bound.width() + style()->pixelMetric(QStyle::PM_HeaderMargin) * 4
       
  1156         + iw + arrowWidth;
       
  1157     return QSize(width, height);
       
  1158 }
       
  1159 
       
  1160 /*
       
  1161     Sets d->sizes[\a section] to a bounding rect based on its size
       
  1162     hint and font metrics, but constrained by \a size. It also updates
       
  1163     d->height.
       
  1164 */
       
  1165 void Q3Header::setSectionSizeAndHeight(int section, int size)
       
  1166 {
       
  1167     QSize sz = sectionSizeHint(section, fontMetrics());
       
  1168 
       
  1169     if (size < 0) {
       
  1170         if (d->sizes[section] < 0)
       
  1171             d->sizes[section] = (orient == Qt::Horizontal) ? sz.width()
       
  1172                                                          : sz.height();
       
  1173     } else {
       
  1174         d->sizes[section] = size;
       
  1175     }
       
  1176 
       
  1177     int newHeight = (orient == Qt::Horizontal) ? sz.height() : sz.width();
       
  1178     if (newHeight > d->height) {
       
  1179         d->height = newHeight;
       
  1180     } else if (newHeight < d->height) {
       
  1181         /*
       
  1182           We could be smarter, but we aren't. This makes a difference
       
  1183           only for users with many columns and '\n's in their headers
       
  1184           at the same time.
       
  1185         */
       
  1186         d->heightDirty = true;
       
  1187     }
       
  1188 }
       
  1189 
       
  1190 /*!
       
  1191     Adds a new section with label text \a s. Returns the index
       
  1192     position where the section was added (at the right for horizontal
       
  1193     headers, at the bottom for vertical headers). The section's width
       
  1194     is set to \a size. If \a size \< 0, an appropriate size for the
       
  1195     text \a s is chosen.
       
  1196 */
       
  1197 int Q3Header::addLabel(const QString &s, int size)
       
  1198 {
       
  1199     int n = ++d->count;
       
  1200     if ((int)d->icons.size() < n )
       
  1201         d->icons.resize(n);
       
  1202     if ((int)d->sizes.size() < n ) {
       
  1203         d->labels.resize(n);
       
  1204         d->nullStringLabels.resize(n);
       
  1205         d->sizes.resize(n);
       
  1206         d->positions.resize(n);
       
  1207         d->i2s.resize(n);
       
  1208         d->s2i.resize(n);
       
  1209         d->clicks.resize(n);
       
  1210         d->resize.resize(n);
       
  1211     }
       
  1212     int section = d->count - 1;
       
  1213     if (!d->is_a_table_header || !s.isNull()) {
       
  1214         d->labels.insert(section, s);
       
  1215         d->nullStringLabels.setBit(section, s.isNull());
       
  1216     }
       
  1217 
       
  1218     if (size >= 0 && s.isNull() && d->is_a_table_header) {
       
  1219         d->sizes[section] = size;
       
  1220     } else {
       
  1221         d->sizes[section] = -1;
       
  1222         setSectionSizeAndHeight(section, size);
       
  1223     }
       
  1224 
       
  1225     int index = section;
       
  1226     d->positions[index] = d->lastPos;
       
  1227 
       
  1228     d->s2i[section] = index;
       
  1229     d->i2s[index] = section;
       
  1230     d->clicks.setBit(section, d->clicks_default);
       
  1231     d->resize.setBit(section, d->resize_default);
       
  1232 
       
  1233     if (updatesEnabled()) {
       
  1234         updateGeometry();
       
  1235         calculatePositions();
       
  1236         update();
       
  1237     }
       
  1238     return index;
       
  1239 }
       
  1240 
       
  1241 void Q3Header::resizeArrays(int size)
       
  1242 {
       
  1243     d->icons.resize(size);
       
  1244     d->labels.resize(size);
       
  1245     d->nullStringLabels.resize(size);
       
  1246     d->sizes.resize(size);
       
  1247     d->positions.resize(size);
       
  1248     d->i2s.resize(size);
       
  1249     d->s2i.resize(size);
       
  1250     d->clicks.resize(size);
       
  1251     d->resize.resize(size);
       
  1252 }
       
  1253 
       
  1254 void Q3Header::setIsATableHeader(bool b)
       
  1255 {
       
  1256     d->is_a_table_header = b;
       
  1257 }
       
  1258 
       
  1259 /*! \reimp */
       
  1260 QSize Q3Header::sizeHint() const
       
  1261 {
       
  1262     int width;
       
  1263     int height;
       
  1264 
       
  1265     ensurePolished();
       
  1266     QFontMetrics fm = fontMetrics();
       
  1267 
       
  1268     if (d->heightDirty) {
       
  1269         d->height = fm.lineSpacing() + 6;
       
  1270         for (int i = 0; i < count(); i++) {
       
  1271             int h = orient == Qt::Horizontal ?
       
  1272                     sectionSizeHint(i, fm).height() : sectionSizeHint(i, fm).width();
       
  1273             d->height = qMax(d->height, h);
       
  1274         }
       
  1275         d->heightDirty = false;
       
  1276     }
       
  1277 
       
  1278     if (orient == Qt::Horizontal) {
       
  1279         height = fm.lineSpacing() + 6;
       
  1280         width = 0;
       
  1281         height = qMax(height, d->height);
       
  1282         for (int i = 0; i < count(); i++)
       
  1283             width += d->sizes[i];
       
  1284     } else {
       
  1285         width = fm.width(QLatin1Char(' '));
       
  1286         height = 0;
       
  1287         width = qMax(width, d->height);
       
  1288         for (int i = 0; i < count(); i++)
       
  1289             height += d->sizes[i];
       
  1290     }
       
  1291     QStyleOptionHeader opt = getStyleOption(this, 0);
       
  1292     return style()->sizeFromContents(QStyle::CT_Q3Header, &opt, QSize(width, height),
       
  1293                                     this).expandedTo(QApplication::globalStrut());
       
  1294 }
       
  1295 
       
  1296 /*!
       
  1297     \property Q3Header::offset
       
  1298     \brief the header's left-most (or top-most) visible pixel
       
  1299 
       
  1300     Setting this property will scroll the header so that \e offset
       
  1301     becomes the left-most (or top-most for vertical headers) visible
       
  1302     pixel.
       
  1303 */
       
  1304 int Q3Header::offset() const
       
  1305 {
       
  1306     if (reverse())
       
  1307         return d->lastPos - width() - offs;
       
  1308     return offs;
       
  1309 }
       
  1310 
       
  1311 void Q3Header::setOffset(int x)
       
  1312 {
       
  1313     int oldOff = offset();
       
  1314     offs = x;
       
  1315     if(d->lastPos < (orient == Qt::Horizontal ? width() : height()))
       
  1316         offs = 0;
       
  1317     else if (reverse())
       
  1318         offs = d->lastPos - width() - x;
       
  1319     if (orient == Qt::Horizontal)
       
  1320         scroll(oldOff-offset(), 0);
       
  1321     else
       
  1322         scroll(0, oldOff-offset());
       
  1323 }
       
  1324 
       
  1325 
       
  1326 
       
  1327 /*
       
  1328   Returns the position of actual division line \a i in widget
       
  1329   coordinates. May return a position outside the widget.
       
  1330 
       
  1331   Note that the last division line is numbered count(). (There is one
       
  1332   more line than the number of sections).
       
  1333 */
       
  1334 int Q3Header::pPos(int i) const
       
  1335 {
       
  1336     int pos;
       
  1337     if (i == count())
       
  1338         pos = d->lastPos;
       
  1339     else
       
  1340         pos = d->positions[i];
       
  1341     if (reverse())
       
  1342         pos = d->lastPos - pos;
       
  1343     return pos - offset();
       
  1344 }
       
  1345 
       
  1346 
       
  1347 /*
       
  1348   Returns the size of the section at index position \a i.
       
  1349 */
       
  1350 int Q3Header::pSize(int i) const
       
  1351 {
       
  1352     return d->sizes[d->i2s[i]];
       
  1353 }
       
  1354 
       
  1355 /*!
       
  1356   Use mapToSection() instead.
       
  1357 
       
  1358   Translates from actual index \a a (index at which the section is displayed)  to
       
  1359   logical index of the section.  Returns -1 if \a a is outside the legal range.
       
  1360 
       
  1361   \sa mapToActual()
       
  1362 */
       
  1363 
       
  1364 int Q3Header::mapToLogical(int a) const
       
  1365 {
       
  1366     return mapToSection(a);
       
  1367 }
       
  1368 
       
  1369 
       
  1370 /*!
       
  1371   Use mapToIndex() instead.
       
  1372 
       
  1373   Translates from logical index \a l to actual index (index at which the section \a l is displayed) .
       
  1374   Returns -1 if \a l is outside the legal range.
       
  1375 
       
  1376   \sa mapToLogical()
       
  1377 */
       
  1378 
       
  1379 int Q3Header::mapToActual(int l) const
       
  1380 {
       
  1381     return mapToIndex(l);
       
  1382 }
       
  1383 
       
  1384 
       
  1385 /*!
       
  1386   Use resizeSection() instead.
       
  1387 
       
  1388   Sets the size of the section \a section to \a s pixels.
       
  1389 
       
  1390   \warning does not repaint or send out signals
       
  1391 */
       
  1392 
       
  1393 void Q3Header::setCellSize(int section, int s)
       
  1394 {
       
  1395     if (section < 0 || section >= count())
       
  1396         return;
       
  1397     d->sizes[section] = s;
       
  1398     if (updatesEnabled())
       
  1399         calculatePositions();
       
  1400     else
       
  1401         d->positionsDirty = true;
       
  1402 }
       
  1403 
       
  1404 
       
  1405 /*!
       
  1406     If \a enable is true the user may resize section \a section;
       
  1407     otherwise the section may not be manually resized.
       
  1408 
       
  1409     If \a section is negative (the default) then the \a enable value
       
  1410     is set for all existing sections and will be applied to any new
       
  1411     sections that are added.
       
  1412     Example:
       
  1413     \snippet doc/src/snippets/code/src_qt3support_widgets_q3header.cpp 0
       
  1414 
       
  1415     If the user resizes a section, a sizeChange() signal is emitted.
       
  1416 
       
  1417     \sa setMovingEnabled() setClickEnabled() setTracking()
       
  1418 */
       
  1419 
       
  1420 void Q3Header::setResizeEnabled(bool enable, int section)
       
  1421 {
       
  1422     if (section < 0) {
       
  1423         d->resize.fill(enable);
       
  1424         // and future ones...
       
  1425         d->resize_default = enable;
       
  1426     } else if (section < count()) {
       
  1427         d->resize[section] = enable;
       
  1428     }
       
  1429 }
       
  1430 
       
  1431 
       
  1432 /*!
       
  1433     \property Q3Header::moving
       
  1434     \brief whether the header sections can be moved
       
  1435 
       
  1436     If this property is true (the default) the user can move sections.
       
  1437     If the user moves a section the indexChange() signal is emitted.
       
  1438 
       
  1439     \sa setClickEnabled(), setResizeEnabled()
       
  1440 */
       
  1441 
       
  1442 void Q3Header::setMovingEnabled(bool enable)
       
  1443 {
       
  1444     d->move = enable;
       
  1445 }
       
  1446 
       
  1447 
       
  1448 /*!
       
  1449     If \a enable is true, any clicks on section \a section will result
       
  1450     in clicked() signals being emitted; otherwise the section will
       
  1451     ignore clicks.
       
  1452 
       
  1453     If \a section is -1 (the default) then the \a enable value is set
       
  1454     for all existing sections and will be applied to any new sections
       
  1455     that are added.
       
  1456 
       
  1457     \sa setMovingEnabled(), setResizeEnabled()
       
  1458 */
       
  1459 
       
  1460 void Q3Header::setClickEnabled(bool enable, int section)
       
  1461 {
       
  1462     if (section < 0) {
       
  1463         d->clicks.fill(enable);
       
  1464         // and future ones...
       
  1465         d->clicks_default = enable;
       
  1466     } else if (section < count()) {
       
  1467         d->clicks[section] = enable;
       
  1468     }
       
  1469 }
       
  1470 
       
  1471 
       
  1472 /*!
       
  1473     Paints the section at position \a index, inside rectangle \a fr
       
  1474     (which uses widget coordinates) using painter \a p.
       
  1475 
       
  1476     Calls paintSectionLabel().
       
  1477 */
       
  1478 
       
  1479 void Q3Header::paintSection(QPainter *p, int index, const QRect& fr)
       
  1480 {
       
  1481     int section = mapToSection(index);
       
  1482     QStyleOptionHeader opt = getStyleOption(this, section);
       
  1483     opt.state |= QStyle::State_Raised;
       
  1484     opt.rect = fr;
       
  1485 
       
  1486     if (section < 0) {
       
  1487         style()->drawControl(QStyle::CE_Header, &opt, p, this);
       
  1488         return;
       
  1489     }
       
  1490 
       
  1491     if (sectionSize(section) <= 0)
       
  1492         return;
       
  1493 
       
  1494     opt.state = (orient == Qt::Horizontal ? QStyle::State_Horizontal : QStyle::State_None);
       
  1495     if (d->sortSection == section)
       
  1496         opt.sortIndicator = d->sortDirection ? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;
       
  1497 
       
  1498     if (isEnabled())
       
  1499         opt.state |= QStyle::State_Enabled;
       
  1500     if (isClickEnabled(section) && (state == Pressed || state == Moving) && index == handleIdx)
       
  1501         opt.state |= QStyle::State_Sunken; //currently pressed
       
  1502     if (!(opt.state & QStyle::State_Sunken))
       
  1503         opt.state |= QStyle::State_Raised;
       
  1504     p->setBrushOrigin(fr.topLeft());
       
  1505     if (d->clicks[section]) {
       
  1506         style()->drawControl(QStyle::CE_Header, &opt, p, this);
       
  1507     } else {
       
  1508         p->save();
       
  1509         p->setClipRect(fr); // hack to keep styles working
       
  1510         opt.rect.setRect(fr.x() + 1, fr.y(), fr.width(), fr.height());
       
  1511         style()->drawControl(QStyle::CE_Header, &opt, p, this);
       
  1512         if (orient == Qt::Horizontal) {
       
  1513             p->setPen(palette().color(QPalette::Mid));
       
  1514             p->drawLine(fr.x() - 1, fr.y() + fr.height() - 1,
       
  1515                          fr.x() + fr.width() - 1, fr.y() + fr.height() - 1);
       
  1516             p->drawLine(fr.x() + fr.width() - 1, fr.y(),
       
  1517                          fr.x() + fr.width() - 1, fr.y() + fr.height() - 1);
       
  1518         } else {
       
  1519             p->setPen(palette().color(QPalette::Mid));
       
  1520             p->drawLine(fr.x() + width() - 1, fr.y(),
       
  1521                          fr.x() + fr.width() - 1, fr.y() + fr.height() - 1);
       
  1522             p->drawLine(fr.x(), fr.y() + fr.height() - 1,
       
  1523                          fr.x() + fr.width() - 1, fr.y() + fr.height() - 1);
       
  1524             p->setPen(palette().color(QPalette::Light));
       
  1525             if (index > 0)
       
  1526                 p->drawLine(fr.x(), fr.y(), fr.x() + fr.width() - 1, fr.y());
       
  1527             if (index == count() - 1) {
       
  1528                 p->drawLine(fr.x(), fr.y() + fr.height() - 1,
       
  1529                              fr.x() + fr.width() - 1, fr.y() + fr.height() - 1);
       
  1530                 p->setPen(palette().color(QPalette::Mid));
       
  1531                 p->drawLine(fr.x(), fr.y() + fr.height() - 2,
       
  1532                              fr.x() + fr.width() - 1, fr.y() + fr.height() - 2);
       
  1533             }
       
  1534         }
       
  1535         p->restore();
       
  1536     }
       
  1537 }
       
  1538 
       
  1539 /*!
       
  1540     Paints the label of the section at position \a index, inside
       
  1541     rectangle \a fr (which uses widget coordinates) using painter \a
       
  1542     p.
       
  1543 
       
  1544     Called by paintSection()
       
  1545 */
       
  1546 void Q3Header::paintSectionLabel(QPainter *p, int index, const QRect& fr)
       
  1547 {
       
  1548     int section = mapToSection(index);
       
  1549     if (section < 0)
       
  1550         return;
       
  1551 
       
  1552     int dx = 0, dy = 0;
       
  1553     QStyleOptionHeader opt = getStyleOption(this, section);
       
  1554     if (d->sortSection == section)
       
  1555         opt.sortIndicator = d->sortDirection ? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;
       
  1556     if (index == handleIdx && (state == Pressed || state == Moving)) {
       
  1557         dx = style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, &opt, this);
       
  1558         dy = style()->pixelMetric(QStyle::PM_ButtonShiftVertical, &opt, this);
       
  1559         opt.state |= QStyle::State_Sunken;
       
  1560     }
       
  1561     if (isEnabled())
       
  1562         opt.state |= QStyle::State_Enabled;
       
  1563 
       
  1564 
       
  1565     opt.rect.setRect(fr.x() + style()->pixelMetric(QStyle::PM_HeaderMargin) + dx, fr.y() + 2 + dy,
       
  1566                      fr.width() - 6, fr.height() - 4);
       
  1567 
       
  1568     style()->drawControl(QStyle::CE_HeaderLabel, &opt, p, this);
       
  1569 
       
  1570     int arrowWidth = (orient == Qt::Horizontal ? height() : width()) / 2;
       
  1571     int arrowHeight = fr.height() - 6;
       
  1572     QSize ssh = sectionSizeHint(section, p->fontMetrics());
       
  1573     int tw = (orient == Qt::Horizontal ? ssh.width() : ssh.height());
       
  1574     int ew = 0;
       
  1575 
       
  1576     if (style()->styleHint(QStyle::SH_Header_ArrowAlignment, 0, this) & Qt::AlignRight)
       
  1577         ew = fr.width() - tw - 8;
       
  1578     if (d->sortSection == section && tw <= fr.width()) {
       
  1579         if (reverse()) {
       
  1580             tw = fr.width() - tw;
       
  1581             ew = fr.width() - ew - tw;
       
  1582         }
       
  1583         opt.state = QStyle::State_None;
       
  1584         if (isEnabled())
       
  1585             opt.state |= QStyle::State_Enabled;
       
  1586         if (d->sortDirection)
       
  1587             opt.state |= QStyle::State_DownArrow;
       
  1588         else
       
  1589             opt.state |= QStyle::State_UpArrow;
       
  1590         QRect ar(fr.x() + tw - arrowWidth - 6 + ew, 4, arrowWidth, arrowHeight);
       
  1591         if (label(section).isRightToLeft())
       
  1592             ar.moveBy( 2*(fr.right() - ar.right()) + ar.width() - fr.width(), 0 );
       
  1593         opt.rect = ar;
       
  1594         style()->drawPrimitive(QStyle::PE_IndicatorHeaderArrow, &opt, p, this);
       
  1595     }
       
  1596 }
       
  1597 
       
  1598 
       
  1599 /*! \reimp */
       
  1600 void Q3Header::paintEvent(QPaintEvent *e)
       
  1601 {
       
  1602     QPainter p(this);
       
  1603     p.setPen(palette().buttonText().color());
       
  1604     int pos = orient == Qt::Horizontal ? e->rect().left() : e->rect().top();
       
  1605     int id = mapToIndex(sectionAt(pos + offset()));
       
  1606     if (id < 0) {
       
  1607         if (pos > 0)
       
  1608             id = d->count;
       
  1609         else if (reverse())
       
  1610             id = d->count - 1;
       
  1611         else
       
  1612             id = 0;
       
  1613     }
       
  1614     if (reverse()) {
       
  1615         for (int i = id; i >= 0; i--) {
       
  1616             QRect r = sRect(i);
       
  1617             paintSection(&p, i, r);
       
  1618             if (r.right() >= e->rect().right())
       
  1619                 return;
       
  1620         }
       
  1621     } else {
       
  1622         if (count() > 0) {
       
  1623             for (int i = id; i <= count(); i++) {
       
  1624                 QRect r = sRect(i);
       
  1625                 /*
       
  1626                   If the last section is clickable (and thus is
       
  1627                   painted raised), draw the virtual section count()
       
  1628                   as well. Otherwise it looks ugly.
       
  1629                 */
       
  1630                 if (i < count() || d->clicks[mapToSection(count() - 1)])
       
  1631                     paintSection(&p, i, r);
       
  1632                 if (hasFocus() && d->focusIdx == i) {
       
  1633                     QStyleOptionFocusRect opt;
       
  1634                     opt.rect.setRect(r.x()+2, r.y()+2, r.width()-4, r.height()-4);
       
  1635                     opt.palette = palette();
       
  1636                     opt.state = QStyle::State_None;
       
  1637                     style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, &p, this);
       
  1638                 }
       
  1639                 if ((orient == Qt::Horizontal && r. right() >= e->rect().right())
       
  1640                     || (orient == Qt::Vertical && r. bottom() >= e->rect().bottom()))
       
  1641                     return;
       
  1642             }
       
  1643         }
       
  1644     }
       
  1645 }
       
  1646 
       
  1647 /*!
       
  1648     \overload
       
  1649 
       
  1650     Sets the sort indicator to \a ascending. Use the other overload instead.
       
  1651 */
       
  1652 
       
  1653 void Q3Header::setSortIndicator(int section, bool ascending)
       
  1654 {
       
  1655     d->sortSection = section;
       
  1656     if (section != -1)
       
  1657         oldHandleIdx = section;
       
  1658     d->sortDirection = ascending;
       
  1659     update();
       
  1660     updateGeometry();
       
  1661 }
       
  1662 
       
  1663 /*!
       
  1664   \fn void Q3Header::setSortIndicator(int section, Qt::SortOrder order)
       
  1665 
       
  1666   Sets a sort indicator onto the specified \a section. The indicator's
       
  1667   \a order is either Ascending or Descending.
       
  1668 
       
  1669   Only one section can show a sort indicator at any one time. If you
       
  1670   don't want any section to show a sort indicator pass a \a section
       
  1671   number of -1.
       
  1672 
       
  1673   \sa sortIndicatorSection(), sortIndicatorOrder()
       
  1674 */
       
  1675 
       
  1676 /*!
       
  1677     Returns the section showing the sort indicator or -1 if there is no sort indicator.
       
  1678 
       
  1679     \sa setSortIndicator(), sortIndicatorOrder()
       
  1680 */
       
  1681 
       
  1682 int Q3Header::sortIndicatorSection() const
       
  1683 {
       
  1684     return d->sortSection;
       
  1685 }
       
  1686 
       
  1687 /*!
       
  1688     Returns the implied sort order of the Q3Headers sort indicator.
       
  1689 
       
  1690     \sa setSortIndicator(), sortIndicatorSection()
       
  1691 */
       
  1692 
       
  1693 Qt::SortOrder Q3Header::sortIndicatorOrder() const
       
  1694 {
       
  1695     return d->sortDirection ? Qt::AscendingOrder : Qt::DescendingOrder;
       
  1696 }
       
  1697 
       
  1698 /*!
       
  1699     Resizes section \a section to \a s pixels wide (or high).
       
  1700 */
       
  1701 
       
  1702 void Q3Header::resizeSection(int section, int s)
       
  1703 {
       
  1704     setCellSize(section, s);
       
  1705     update();
       
  1706 }
       
  1707 
       
  1708 /*!
       
  1709     Returns the width (or height) of the \a section in pixels.
       
  1710 */
       
  1711 
       
  1712 int Q3Header::sectionSize(int section) const
       
  1713 {
       
  1714     if (section < 0 || section >= count())
       
  1715         return 0;
       
  1716     return d->sizes[section];
       
  1717 }
       
  1718 
       
  1719 /*!
       
  1720     Returns the position (in pixels) at which the \a section starts.
       
  1721 
       
  1722     \sa offset()
       
  1723 */
       
  1724 
       
  1725 int Q3Header::sectionPos(int section) const
       
  1726 {
       
  1727     if (d->positionsDirty)
       
  1728         ((Q3Header *)this)->calculatePositions();
       
  1729     if (section < 0 || section >= count() )
       
  1730         return 0;
       
  1731     return d->positions[d->s2i[section]];
       
  1732 }
       
  1733 
       
  1734 /*!
       
  1735     Returns the index of the section which contains the position \a
       
  1736     pos given in pixels from the left (or top).
       
  1737 
       
  1738     \sa offset()
       
  1739 */
       
  1740 
       
  1741 int Q3Header::sectionAt(int pos) const
       
  1742 {
       
  1743     if (reverse())
       
  1744         pos = d->lastPos - pos;
       
  1745     return d->sectionAt(pos);
       
  1746 }
       
  1747 
       
  1748 /*!
       
  1749     Returns the number of the section that is displayed at index
       
  1750     position \a index.
       
  1751 */
       
  1752 
       
  1753 int Q3Header::mapToSection(int index) const
       
  1754 {
       
  1755     return (index >= 0 && index < count()) ? d->i2s[index] : -1;
       
  1756 }
       
  1757 
       
  1758 /*!
       
  1759     Returns the index position at which section \a section is
       
  1760     displayed.
       
  1761 */
       
  1762 
       
  1763 int Q3Header::mapToIndex(int section) const
       
  1764 {
       
  1765     return (section >= 0 && section < count()) ? d->s2i[section] : -1;
       
  1766 }
       
  1767 
       
  1768 /*!
       
  1769     Moves section \a section to index position \a toIndex.
       
  1770 */
       
  1771 
       
  1772 void Q3Header::moveSection(int section, int toIndex)
       
  1773 {
       
  1774     int fromIndex = mapToIndex(section);
       
  1775     if (fromIndex == toIndex ||
       
  1776          fromIndex < 0 || fromIndex > count() ||
       
  1777          toIndex < 0 || toIndex > count())
       
  1778         return;
       
  1779     int i;
       
  1780     int idx = d->i2s[fromIndex];
       
  1781     if (fromIndex < toIndex) {
       
  1782         for (i = fromIndex; i < toIndex - 1; i++) {
       
  1783             int t;
       
  1784             d->i2s[i] = t = d->i2s[i+1];
       
  1785             d->s2i[t] = i;
       
  1786         }
       
  1787         d->i2s[toIndex-1] = idx;
       
  1788         d->s2i[idx] = toIndex-1;
       
  1789     } else {
       
  1790         for (i = fromIndex; i > toIndex; i--) {
       
  1791             int t;
       
  1792             d->i2s[i] = t = d->i2s[i-1];
       
  1793             d->s2i[t] = i;
       
  1794         }
       
  1795         d->i2s[toIndex] = idx;
       
  1796         d->s2i[idx] = toIndex;
       
  1797     }
       
  1798     calculatePositions();
       
  1799 }
       
  1800 
       
  1801 /*!
       
  1802     Returns true if section \a section is clickable; otherwise returns
       
  1803     false.
       
  1804 
       
  1805     If \a section is out of range (negative or larger than count() -
       
  1806     1): returns true if all sections are clickable; otherwise returns
       
  1807     false.
       
  1808 
       
  1809     \sa setClickEnabled()
       
  1810 */
       
  1811 
       
  1812 bool Q3Header::isClickEnabled(int section) const
       
  1813 {
       
  1814     if (section >= 0 && section < count()) {
       
  1815         return (bool)d->clicks[section];
       
  1816     }
       
  1817 
       
  1818     for (int i = 0; i < count(); ++i) {
       
  1819         if (!d->clicks[i])
       
  1820             return false;
       
  1821     }
       
  1822     return true;
       
  1823 }
       
  1824 
       
  1825 /*!
       
  1826     Returns true if section \a section is resizeable; otherwise
       
  1827     returns false.
       
  1828 
       
  1829     If \a section is -1 then this function applies to all sections,
       
  1830     i.e. returns true if all sections are resizeable; otherwise
       
  1831     returns false.
       
  1832 
       
  1833     \sa setResizeEnabled()
       
  1834 */
       
  1835 
       
  1836 bool Q3Header::isResizeEnabled(int section) const
       
  1837 {
       
  1838     if (section >= 0 && section < count()) {
       
  1839         return (bool)d->resize[section];
       
  1840     }
       
  1841 
       
  1842     for (int i = 0; i < count();++i) {
       
  1843         if (!d->resize[i])
       
  1844             return false;
       
  1845     }
       
  1846     return true;
       
  1847 }
       
  1848 
       
  1849 bool Q3Header::isMovingEnabled() const
       
  1850 {
       
  1851     return d->move;
       
  1852 }
       
  1853 
       
  1854 /*! \internal */
       
  1855 
       
  1856 void Q3Header::setUpdatesEnabled(bool enable)
       
  1857 {
       
  1858     if (enable)
       
  1859         calculatePositions();
       
  1860     QWidget::setUpdatesEnabled(enable);
       
  1861 }
       
  1862 
       
  1863 
       
  1864 bool Q3Header::reverse () const
       
  1865 {
       
  1866 #if 0
       
  1867     return (orient == Qt::Horizontal && QApplication::reverseLayout());
       
  1868 #else
       
  1869     return false;
       
  1870 #endif
       
  1871 }
       
  1872 
       
  1873 /*! \reimp */
       
  1874 void Q3Header::resizeEvent(QResizeEvent *e)
       
  1875 {
       
  1876     if (e)
       
  1877         QWidget::resizeEvent(e);
       
  1878 
       
  1879     if(d->lastPos < width()) {
       
  1880             offs = 0;
       
  1881     }
       
  1882 
       
  1883     if (e) {
       
  1884         adjustHeaderSize(orientation() == Qt::Horizontal ?
       
  1885                           width() - e->oldSize().width() : height() - e->oldSize().height());
       
  1886         if ((orientation() == Qt::Horizontal && height() != e->oldSize().height())
       
  1887              || (orientation() == Qt::Vertical && width() != e->oldSize().width()))
       
  1888             update();
       
  1889     } else
       
  1890         adjustHeaderSize();
       
  1891 }
       
  1892 
       
  1893 /*!
       
  1894     \fn void Q3Header::adjustHeaderSize()
       
  1895 
       
  1896     Adjusts the size of the sections to fit the size of the header as
       
  1897     completely as possible. Only sections for which isStretchEnabled()
       
  1898     is true will be resized.
       
  1899 */
       
  1900 
       
  1901 void Q3Header::adjustHeaderSize(int diff)
       
  1902 {
       
  1903     if (!count())
       
  1904         return;
       
  1905 
       
  1906     // we skip the adjustHeaderSize when trying to resize the last column which is set to stretchable
       
  1907     if (d->fullSize == (count() -1) &&
       
  1908          (d->lastPos - d->sizes[count() -1]) > (orient == Qt::Horizontal ? width() : height()))
       
  1909         return;
       
  1910 
       
  1911     if (d->fullSize >= 0) {
       
  1912         int sec = mapToSection(d->fullSize);
       
  1913         int lsec = mapToSection(count() - 1);
       
  1914         int ns = sectionSize(sec) +
       
  1915                  (orientation() == Qt::Horizontal ?
       
  1916                    width() : height()) - (sectionPos(lsec) + sectionSize(lsec));
       
  1917         int os = sectionSize(sec);
       
  1918         if (ns < 20)
       
  1919             ns = 20;
       
  1920         setCellSize(sec, ns);
       
  1921         repaint();
       
  1922         emit sizeChange(sec, os, ns);
       
  1923     } else if (d->fullSize == -1) {
       
  1924         int df = diff / count();
       
  1925         int part = orientation() == Qt::Horizontal ? width() / count() : height() / count();
       
  1926         for (int i = 0; i < count() - 1; ++i) {
       
  1927             int sec = mapToIndex(i);
       
  1928             int os = sectionSize(sec);
       
  1929             int ns = diff != -1 ? os + df : part;
       
  1930             if (ns < 20)
       
  1931                 ns = 20;
       
  1932             setCellSize(sec, ns);
       
  1933             emit sizeChange(sec, os, ns);
       
  1934         }
       
  1935         int sec = mapToIndex(count() - 1);
       
  1936         int ns = (orientation() == Qt::Horizontal ? width() : height()) - sectionPos(sec);
       
  1937         int os = sectionSize(sec);
       
  1938         if (ns < 20)
       
  1939             ns = 20;
       
  1940         setCellSize(sec, ns);
       
  1941         repaint();
       
  1942         emit sizeChange(sec, os, ns);
       
  1943     }
       
  1944 }
       
  1945 
       
  1946 /*!
       
  1947     Returns the total width of all the header columns.
       
  1948 */
       
  1949 int Q3Header::headerWidth() const
       
  1950 {
       
  1951     if (d->pos_dirty) {
       
  1952         ((Q3Header*)this)->calculatePositions();
       
  1953         d->pos_dirty = false;
       
  1954     }
       
  1955     return d->lastPos;
       
  1956 }
       
  1957 
       
  1958 void Q3Header::calculatePositions(bool onlyVisible, int start)
       
  1959 {
       
  1960     d->positionsDirty = false;
       
  1961     d->lastPos = count() > 0 ? d->positions[start] : 0;
       
  1962     for (int i = start; i < count(); i++) {
       
  1963         d->positions[i] = d->lastPos;
       
  1964         d->lastPos += d->sizes[d->i2s[i]];
       
  1965         if (onlyVisible && d->lastPos > offset() +
       
  1966              (orientation() == Qt::Horizontal ? width() : height()))
       
  1967             break;
       
  1968     }
       
  1969     d->pos_dirty = onlyVisible;
       
  1970 }
       
  1971 
       
  1972 
       
  1973 /*!
       
  1974     \property Q3Header::stretching
       
  1975     \brief whether the header sections always take up the full width
       
  1976     (or height) of the header
       
  1977 */
       
  1978 
       
  1979 
       
  1980 /*!
       
  1981     If \a b is true, section \a section will be resized when the
       
  1982     header is resized, so that the sections take up the full width (or
       
  1983     height for vertical headers) of the header; otherwise section \a
       
  1984     section will be set to be unstretchable and will not resize when
       
  1985     the header is resized.
       
  1986 
       
  1987     If \a section is -1, and if \a b is true, then all sections will
       
  1988     be resized equally when the header is resized so that they take up
       
  1989     the full width (or height for vertical headers) of the header;
       
  1990     otherwise all the sections will be set to be unstretchable and
       
  1991     will not resize when the header is resized.
       
  1992 
       
  1993     \sa adjustHeaderSize()
       
  1994 */
       
  1995 
       
  1996 void Q3Header::setStretchEnabled(bool b, int section)
       
  1997 {
       
  1998     if (b)
       
  1999         d->fullSize = section;
       
  2000     else
       
  2001         d->fullSize = -2;
       
  2002     adjustHeaderSize();
       
  2003 }
       
  2004 
       
  2005 bool Q3Header::isStretchEnabled() const
       
  2006 {
       
  2007     return d->fullSize == -1;
       
  2008 }
       
  2009 
       
  2010 /*!
       
  2011     \overload
       
  2012 
       
  2013     Returns true if section \a section will resize to take up the full
       
  2014     width (or height) of the header; otherwise returns false. If at
       
  2015     least one section has stretch enabled the sections will always
       
  2016     take up the full width of the header.
       
  2017 
       
  2018     \sa setStretchEnabled()
       
  2019 */
       
  2020 
       
  2021 bool Q3Header::isStretchEnabled(int section) const
       
  2022 {
       
  2023     return d->fullSize == section;
       
  2024 }
       
  2025 
       
  2026 /*!
       
  2027   \reimp
       
  2028 */
       
  2029 void Q3Header::changeEvent(QEvent *ev)
       
  2030 {
       
  2031     if(ev->type() == QEvent::FontChange) {
       
  2032         QFontMetrics fm = fontMetrics();
       
  2033         d->height = (orient == Qt::Horizontal) ? fm.lineSpacing() + 6 : fm.width(QLatin1Char(' '));
       
  2034     }
       
  2035     QWidget::changeEvent(ev);
       
  2036 }
       
  2037 
       
  2038 QT_END_NAMESPACE
       
  2039 
       
  2040 #endif // QT_NO_HEADER