util/src/gui/widgets/qsplitter.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 "qsplitter.h"
       
    43 #ifndef QT_NO_SPLITTER
       
    44 
       
    45 #include "qapplication.h"
       
    46 #include "qcursor.h"
       
    47 #include "qdrawutil.h"
       
    48 #include "qevent.h"
       
    49 #include "qlayout.h"
       
    50 #include "qlist.h"
       
    51 #include "qpainter.h"
       
    52 #include "qrubberband.h"
       
    53 #include "qstyle.h"
       
    54 #include "qstyleoption.h"
       
    55 #include "qtextstream.h"
       
    56 #include "qvarlengtharray.h"
       
    57 #include "qvector.h"
       
    58 #include "private/qlayoutengine_p.h"
       
    59 #include "private/qsplitter_p.h"
       
    60 #include "qtimer.h"
       
    61 #include "qdebug.h"
       
    62 
       
    63 #include <ctype.h>
       
    64 
       
    65 QT_BEGIN_NAMESPACE
       
    66 
       
    67 //#define QSPLITTER_DEBUG
       
    68 
       
    69 /*!
       
    70     \class QSplitterHandle
       
    71     \brief The QSplitterHandle class provides handle functionality of the splitter.
       
    72 
       
    73     \ingroup organizers
       
    74 
       
    75     QSplitterHandle is typically what people think about when they think about
       
    76     a splitter. It is the handle that is used to resize the widgets.
       
    77 
       
    78     A typical developer using QSplitter will never have to worry about
       
    79     QSplitterHandle. It is provided for developers who want splitter handles
       
    80     that provide extra features, such as popup menus.
       
    81 
       
    82     The typical way one would create splitter handles is to subclass QSplitter then
       
    83     reimplement QSplitter::createHandle() to instantiate the custom splitter
       
    84     handle. For example, a minimum QSplitter subclass might look like this:
       
    85 
       
    86     \snippet doc/src/snippets/splitterhandle/splitter.h 0
       
    87 
       
    88     The \l{QSplitter::}{createHandle()} implementation simply constructs a
       
    89     custom splitter handle, called \c Splitter in this example:
       
    90 
       
    91     \snippet doc/src/snippets/splitterhandle/splitter.cpp 1
       
    92 
       
    93     Information about a given handle can be obtained using functions like
       
    94     orientation() and opaqueResize(), and is retrieved from its parent splitter.
       
    95     Details like these can be used to give custom handles different appearances
       
    96     depending on the splitter's orientation.
       
    97 
       
    98     The complexity of a custom handle subclass depends on the tasks that it
       
    99     needs to perform. A simple subclass might only provide a paintEvent()
       
   100     implementation:
       
   101 
       
   102     \snippet doc/src/snippets/splitterhandle/splitter.cpp 0
       
   103 
       
   104     In this example, a predefined gradient is set up differently depending on
       
   105     the orientation of the handle. QSplitterHandle provides a reasonable
       
   106     size hint for the handle, so the subclass does not need to provide a
       
   107     reimplementation of sizeHint() unless the handle has special size
       
   108     requirements.
       
   109 
       
   110     \sa QSplitter
       
   111 */
       
   112 
       
   113 /*!
       
   114     Creates a QSplitter handle with the given \a orientation and
       
   115     QSplitter \a parent.
       
   116 */
       
   117 QSplitterHandle::QSplitterHandle(Qt::Orientation orientation, QSplitter *parent)
       
   118     : QWidget(*new QSplitterHandlePrivate, parent, 0)
       
   119 {
       
   120     Q_D(QSplitterHandle);
       
   121     d->s = parent;
       
   122     setOrientation(orientation);
       
   123 }
       
   124 
       
   125 /*!
       
   126     Sets the orientation of the splitter handle to \a orientation.
       
   127     This is usually propogated from the QSplitter.
       
   128 
       
   129     \sa QSplitter::setOrientation()
       
   130 */
       
   131 void QSplitterHandle::setOrientation(Qt::Orientation orientation)
       
   132 {
       
   133     Q_D(QSplitterHandle);
       
   134     d->orient = orientation;
       
   135 #ifndef QT_NO_CURSOR
       
   136     setCursor(orientation == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor);
       
   137 #endif
       
   138 }
       
   139 
       
   140 /*!
       
   141    Returns the handle's orientation. This is usually propagated from the QSplitter.
       
   142 
       
   143    \sa QSplitter::orientation()
       
   144 */
       
   145 Qt::Orientation QSplitterHandle::orientation() const
       
   146 {
       
   147     Q_D(const QSplitterHandle);
       
   148     return d->orient;
       
   149 }
       
   150 
       
   151 
       
   152 /*!
       
   153     Returns true if widgets are resized dynamically (opaquely), otherwise
       
   154     returns false. This value is controlled by the QSplitter.
       
   155 
       
   156     \sa QSplitter::opaqueResize()
       
   157 
       
   158 */
       
   159 bool QSplitterHandle::opaqueResize() const
       
   160 {
       
   161     Q_D(const QSplitterHandle);
       
   162     return d->s->opaqueResize();
       
   163 }
       
   164 
       
   165 
       
   166 /*!
       
   167     Returns the splitter associated with this splitter handle.
       
   168 
       
   169     \sa QSplitter::handle()
       
   170 */
       
   171 QSplitter *QSplitterHandle::splitter() const
       
   172 {
       
   173     return d_func()->s;
       
   174 }
       
   175 
       
   176 /*!
       
   177     Tells the splitter to move this handle to position \a pos, which is
       
   178     the distance from the left or top edge of the widget.
       
   179 
       
   180     Note that \a pos is also measured from the left (or top) for
       
   181     right-to-left languages. This function will map \a pos to the
       
   182     appropriate position before calling QSplitter::moveSplitter().
       
   183 
       
   184     \sa QSplitter::moveSplitter() closestLegalPosition()
       
   185 */
       
   186 void QSplitterHandle::moveSplitter(int pos)
       
   187 {
       
   188     Q_D(QSplitterHandle);
       
   189     if (d->s->isRightToLeft() && d->orient == Qt::Horizontal)
       
   190         pos = d->s->contentsRect().width() - pos;
       
   191     d->s->moveSplitter(pos, d->s->indexOf(this));
       
   192 }
       
   193 
       
   194 /*!
       
   195    Returns the closest legal position to \a pos of the splitter
       
   196    handle. The positions are measured from the left or top edge of
       
   197    the splitter, even for right-to-left languages.
       
   198 
       
   199    \sa QSplitter::closestLegalPosition(), moveSplitter()
       
   200 */
       
   201 
       
   202 int QSplitterHandle::closestLegalPosition(int pos)
       
   203 {
       
   204     Q_D(QSplitterHandle);
       
   205     QSplitter *s = d->s;
       
   206     if (s->isRightToLeft() && d->orient == Qt::Horizontal) {
       
   207         int w = s->contentsRect().width();
       
   208         return w - s->closestLegalPosition(w - pos, s->indexOf(this));
       
   209     }
       
   210     return s->closestLegalPosition(pos, s->indexOf(this));
       
   211 }
       
   212 
       
   213 /*!
       
   214     \reimp
       
   215 */
       
   216 QSize QSplitterHandle::sizeHint() const
       
   217 {
       
   218     Q_D(const QSplitterHandle);
       
   219     int hw = d->s->handleWidth();
       
   220     QStyleOption opt(0);
       
   221     opt.init(d->s);
       
   222     opt.state = QStyle::State_None;
       
   223     return parentWidget()->style()->sizeFromContents(QStyle::CT_Splitter, &opt, QSize(hw, hw), d->s)
       
   224         .expandedTo(QApplication::globalStrut());
       
   225 }
       
   226 
       
   227 /*!
       
   228     \reimp
       
   229 */
       
   230 bool QSplitterHandle::event(QEvent *event)
       
   231 {
       
   232     Q_D(QSplitterHandle);
       
   233     switch(event->type()) {
       
   234     case QEvent::HoverEnter:
       
   235         d->hover = true;
       
   236         update();
       
   237         break;
       
   238     case QEvent::HoverLeave:
       
   239         d->hover = false;
       
   240         update();
       
   241         break;
       
   242     default:
       
   243         break;
       
   244     }
       
   245     return QWidget::event(event);
       
   246 }
       
   247 
       
   248 /*!
       
   249     \reimp
       
   250 */
       
   251 void QSplitterHandle::mouseMoveEvent(QMouseEvent *e)
       
   252 {
       
   253     Q_D(QSplitterHandle);
       
   254     if (!(e->buttons() & Qt::LeftButton))
       
   255         return;
       
   256     int pos = d->pick(parentWidget()->mapFromGlobal(e->globalPos()))
       
   257                  - d->mouseOffset;
       
   258     if (opaqueResize()) {
       
   259         moveSplitter(pos);
       
   260     } else {
       
   261         d->s->setRubberBand(closestLegalPosition(pos));
       
   262     }
       
   263 }
       
   264 
       
   265 /*!
       
   266    \reimp
       
   267 */
       
   268 void QSplitterHandle::mousePressEvent(QMouseEvent *e)
       
   269 {
       
   270     Q_D(QSplitterHandle);
       
   271     if (e->button() == Qt::LeftButton) {
       
   272         d->mouseOffset = d->pick(e->pos());
       
   273         d->pressed = true;
       
   274         update();
       
   275     }
       
   276 }
       
   277 
       
   278 /*!
       
   279    \reimp
       
   280 */
       
   281 void QSplitterHandle::mouseReleaseEvent(QMouseEvent *e)
       
   282 {
       
   283     Q_D(QSplitterHandle);
       
   284     if (!opaqueResize() && e->button() == Qt::LeftButton) {
       
   285         int pos = d->pick(parentWidget()->mapFromGlobal(e->globalPos()))
       
   286                      - d->mouseOffset;
       
   287         d->s->setRubberBand(-1);
       
   288         moveSplitter(pos);
       
   289     }
       
   290     if (e->button() == Qt::LeftButton) {
       
   291         d->pressed = false;
       
   292         update();
       
   293     }
       
   294 }
       
   295 
       
   296 /*!
       
   297    \reimp
       
   298 */
       
   299 void QSplitterHandle::paintEvent(QPaintEvent *)
       
   300 {
       
   301     Q_D(QSplitterHandle);
       
   302     QPainter p(this);
       
   303     QStyleOption opt(0);
       
   304     opt.rect = rect();
       
   305     opt.palette = palette();
       
   306     if (orientation() == Qt::Horizontal)
       
   307         opt.state = QStyle::State_Horizontal;
       
   308     else
       
   309         opt.state = QStyle::State_None;
       
   310     if (d->hover)
       
   311         opt.state |= QStyle::State_MouseOver;
       
   312     if (d->pressed)
       
   313         opt.state |= QStyle::State_Sunken;
       
   314     if (isEnabled())
       
   315         opt.state |= QStyle::State_Enabled;
       
   316     parentWidget()->style()->drawControl(QStyle::CE_Splitter, &opt, &p, d->s);
       
   317 }
       
   318 
       
   319 
       
   320 int QSplitterLayoutStruct::getWidgetSize(Qt::Orientation orient)
       
   321 {
       
   322     if (sizer == -1) {
       
   323         QSize s = widget->sizeHint();
       
   324         const int presizer = pick(s, orient);
       
   325         const int realsize = pick(widget->size(), orient);
       
   326         if (!s.isValid() || (widget->testAttribute(Qt::WA_Resized) && (realsize > presizer))) {
       
   327             sizer = pick(widget->size(), orient);
       
   328         } else {
       
   329             sizer = presizer;
       
   330         }
       
   331         QSizePolicy p = widget->sizePolicy();
       
   332         int sf = (orient == Qt::Horizontal) ? p.horizontalStretch() : p.verticalStretch();
       
   333         if (sf > 1)
       
   334             sizer *= sf;
       
   335     }
       
   336     return sizer;
       
   337 }
       
   338 
       
   339 int QSplitterLayoutStruct::getHandleSize(Qt::Orientation orient)
       
   340 {
       
   341     return pick(handle->sizeHint(), orient);
       
   342 }
       
   343 
       
   344 void QSplitterPrivate::init()
       
   345 {
       
   346     Q_Q(QSplitter);
       
   347     QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Preferred);
       
   348     if (orient == Qt::Vertical)
       
   349         sp.transpose();
       
   350     q->setSizePolicy(sp);
       
   351     q->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
       
   352 }
       
   353 
       
   354 void QSplitterPrivate::recalc(bool update)
       
   355 {
       
   356     Q_Q(QSplitter);
       
   357     int n = list.count();
       
   358     /*
       
   359       Splitter handles before the first visible widget or right
       
   360       before a hidden widget must be hidden.
       
   361     */
       
   362     bool first = true;
       
   363     bool allInvisible = n != 0;
       
   364     for (int i = 0; i < n ; ++i) {
       
   365         QSplitterLayoutStruct *s = list.at(i);
       
   366         bool widgetHidden = s->widget->isHidden();
       
   367         if (allInvisible && !widgetHidden && !s->collapsed)
       
   368             allInvisible = false;
       
   369         s->handle->setHidden(first || widgetHidden);
       
   370         if (!widgetHidden)
       
   371             first = false;
       
   372     }
       
   373 
       
   374     if (allInvisible)
       
   375         for (int i = 0; i < n ; ++i) {
       
   376             QSplitterLayoutStruct *s = list.at(i);
       
   377             if (!s->widget->isHidden()) {
       
   378                 s->collapsed = false;
       
   379                 break;
       
   380             }
       
   381         }
       
   382 
       
   383     int fi = 2 * q->frameWidth();
       
   384     int maxl = fi;
       
   385     int minl = fi;
       
   386     int maxt = QWIDGETSIZE_MAX;
       
   387     int mint = fi;
       
   388     /*
       
   389       calculate min/max sizes for the whole splitter
       
   390     */
       
   391     bool empty = true;
       
   392     for (int j = 0; j < n; j++) {
       
   393         QSplitterLayoutStruct *s = list.at(j);
       
   394 
       
   395         if (!s->widget->isHidden()) {
       
   396             empty = false;
       
   397             if (!s->handle->isHidden()) {
       
   398                 minl += s->getHandleSize(orient);
       
   399                 maxl += s->getHandleSize(orient);
       
   400             }
       
   401 
       
   402             QSize minS = qSmartMinSize(s->widget);
       
   403             minl += pick(minS);
       
   404             maxl += pick(s->widget->maximumSize());
       
   405             mint = qMax(mint, trans(minS));
       
   406             int tm = trans(s->widget->maximumSize());
       
   407             if (tm > 0)
       
   408                 maxt = qMin(maxt, tm);
       
   409         }
       
   410     }
       
   411 
       
   412     if (empty) {
       
   413         if (qobject_cast<QSplitter *>(parent)) {
       
   414             // nested splitters; be nice
       
   415             maxl = maxt = 0;
       
   416         } else {
       
   417             // QSplitter with no children yet
       
   418             maxl = QWIDGETSIZE_MAX;
       
   419         }
       
   420     } else {
       
   421         maxl = qMin<int>(maxl, QWIDGETSIZE_MAX);
       
   422     }
       
   423     if (maxt < mint)
       
   424         maxt = mint;
       
   425 
       
   426     if (update) {
       
   427         if (orient == Qt::Horizontal) {
       
   428             q->setMaximumSize(maxl, maxt);
       
   429             if (q->isWindow())
       
   430                 q->setMinimumSize(minl,mint);
       
   431         } else {
       
   432             q->setMaximumSize(maxt, maxl);
       
   433             if (q->isWindow())
       
   434                 q->setMinimumSize(mint,minl);
       
   435         }
       
   436         doResize();
       
   437         q->updateGeometry();
       
   438     } else {
       
   439         firstShow = true;
       
   440     }
       
   441 }
       
   442 
       
   443 void QSplitterPrivate::doResize()
       
   444 {
       
   445     Q_Q(QSplitter);
       
   446     QRect r = q->contentsRect();
       
   447     int n = list.count();
       
   448     QVector<QLayoutStruct> a(n*2);
       
   449     int i;
       
   450 
       
   451     bool noStretchFactorsSet = true;
       
   452     for (i = 0; i < n; ++i) {
       
   453         QSizePolicy p = list.at(i)->widget->sizePolicy();
       
   454         int sf = orient == Qt::Horizontal ? p.horizontalStretch() : p.verticalStretch();
       
   455         if (sf != 0) {
       
   456             noStretchFactorsSet = false;
       
   457             break;
       
   458         }
       
   459     }
       
   460 
       
   461     int j=0;
       
   462     for (i = 0; i < n; ++i) {
       
   463         QSplitterLayoutStruct *s = list.at(i);
       
   464 #ifdef QSPLITTER_DEBUG
       
   465         qDebug("widget %d hidden: %d collapsed: %d handle hidden: %d", i, s->widget->isHidden(),
       
   466                s->collapsed, s->handle->isHidden());
       
   467 #endif
       
   468 
       
   469         a[j].init();
       
   470         if (s->handle->isHidden()) {
       
   471             a[j].maximumSize = 0;
       
   472         } else {
       
   473             a[j].sizeHint = a[j].minimumSize = a[j].maximumSize = s->getHandleSize(orient);
       
   474             a[j].empty = false;
       
   475         }
       
   476         ++j;
       
   477 
       
   478         a[j].init();
       
   479         if (s->widget->isHidden() || s->collapsed) {
       
   480             a[j].maximumSize = 0;
       
   481         } else {
       
   482             a[j].minimumSize = pick(qSmartMinSize(s->widget));
       
   483             a[j].maximumSize = pick(s->widget->maximumSize());
       
   484             a[j].empty = false;
       
   485 
       
   486             bool stretch = noStretchFactorsSet;
       
   487             if (!stretch) {
       
   488                 QSizePolicy p = s->widget->sizePolicy();
       
   489                 int sf = orient == Qt::Horizontal ? p.horizontalStretch() : p.verticalStretch();
       
   490                 stretch = (sf != 0);
       
   491             }
       
   492             if (stretch) {
       
   493                 a[j].stretch = s->getWidgetSize(orient);
       
   494                 a[j].sizeHint = a[j].minimumSize;
       
   495                 a[j].expansive = true;
       
   496             } else {
       
   497                 a[j].sizeHint = qMax(s->getWidgetSize(orient), a[j].minimumSize);
       
   498             }
       
   499         }
       
   500         ++j;
       
   501     }
       
   502 
       
   503     qGeomCalc(a, 0, n*2, pick(r.topLeft()), pick(r.size()), 0);
       
   504 
       
   505 #ifdef QSPLITTER_DEBUG
       
   506     for (i = 0; i < n*2; ++i) {
       
   507         qDebug("%*s%d: stretch %d, sh %d, minS %d, maxS %d, exp %d, emp %d -> %d, %d",
       
   508                i, "", i,
       
   509                a[i].stretch,
       
   510                a[i].sizeHint,
       
   511                a[i].minimumSize,
       
   512                a[i].maximumSize,
       
   513                a[i].expansive,
       
   514                a[i].empty,
       
   515                a[i].pos,
       
   516                a[i].size);
       
   517     }
       
   518 #endif
       
   519 
       
   520     for (i = 0; i < n; ++i) {
       
   521         QSplitterLayoutStruct *s = list.at(i);
       
   522         setGeo(s, a[i*2+1].pos, a[i*2+1].size, false);
       
   523     }
       
   524 }
       
   525 
       
   526 void QSplitterPrivate::storeSizes()
       
   527 {
       
   528     for (int i = 0; i < list.size(); ++i) {
       
   529         QSplitterLayoutStruct *sls = list.at(i);
       
   530         sls->sizer = pick(sls->rect.size());
       
   531     }
       
   532 }
       
   533 
       
   534 void QSplitterPrivate::addContribution(int index, int *min, int *max, bool mayCollapse) const
       
   535 {
       
   536     QSplitterLayoutStruct *s = list.at(index);
       
   537     if (!s->widget->isHidden()) {
       
   538         if (!s->handle->isHidden()) {
       
   539             *min += s->getHandleSize(orient);
       
   540             *max += s->getHandleSize(orient);
       
   541         }
       
   542         if (mayCollapse || !s->collapsed)
       
   543             *min += pick(qSmartMinSize(s->widget));
       
   544 
       
   545         *max += pick(s->widget->maximumSize());
       
   546     }
       
   547 }
       
   548 
       
   549 int QSplitterPrivate::findWidgetJustBeforeOrJustAfter(int index, int delta, int &collapsibleSize) const
       
   550 {
       
   551     if (delta < 0)
       
   552         index += delta;
       
   553     do {
       
   554         QWidget *w = list.at(index)->widget;
       
   555         if (!w->isHidden()) {
       
   556             if (collapsible(list.at(index)))
       
   557                 collapsibleSize = pick(qSmartMinSize(w));
       
   558             return index;
       
   559         }
       
   560         index += delta;
       
   561     } while (index >= 0 && index < list.count());
       
   562 
       
   563     return -1;
       
   564 }
       
   565 
       
   566 /*
       
   567   For the splitter handle with index \a index, \a min and \a max give the range without collapsing any widgets,
       
   568   and \a farMin and farMax give the range with collapsing included.
       
   569 */
       
   570 void QSplitterPrivate::getRange(int index, int *farMin, int *min, int *max, int *farMax) const
       
   571 {
       
   572     Q_Q(const QSplitter);
       
   573     int n = list.count();
       
   574     if (index <= 0 || index >= n)
       
   575         return;
       
   576 
       
   577     int collapsibleSizeBefore = 0;
       
   578     int idJustBefore = findWidgetJustBeforeOrJustAfter(index, -1, collapsibleSizeBefore);
       
   579 
       
   580     int collapsibleSizeAfter = 0;
       
   581     int idJustAfter = findWidgetJustBeforeOrJustAfter(index, +1, collapsibleSizeAfter);
       
   582 
       
   583     int minBefore = 0;
       
   584     int minAfter = 0;
       
   585     int maxBefore = 0;
       
   586     int maxAfter = 0;
       
   587     int i;
       
   588 
       
   589     for (i = 0; i < index; ++i)
       
   590         addContribution(i, &minBefore, &maxBefore, i == idJustBefore);
       
   591     for (i = index; i < n; ++i)
       
   592         addContribution(i, &minAfter, &maxAfter, i == idJustAfter);
       
   593 
       
   594     QRect r = q->contentsRect();
       
   595     int farMinVal;
       
   596     int minVal;
       
   597     int maxVal;
       
   598     int farMaxVal;
       
   599 
       
   600     int smartMinBefore = qMax(minBefore, pick(r.size()) - maxAfter);
       
   601     int smartMaxBefore = qMin(maxBefore, pick(r.size()) - minAfter);
       
   602 
       
   603     minVal = pick(r.topLeft()) + smartMinBefore;
       
   604     maxVal = pick(r.topLeft()) + smartMaxBefore;
       
   605 
       
   606     farMinVal = minVal;
       
   607     if (minBefore - collapsibleSizeBefore >= pick(r.size()) - maxAfter)
       
   608         farMinVal -= collapsibleSizeBefore;
       
   609     farMaxVal = maxVal;
       
   610     if (pick(r.size()) - (minAfter - collapsibleSizeAfter) <= maxBefore)
       
   611         farMaxVal += collapsibleSizeAfter;
       
   612 
       
   613     if (farMin)
       
   614         *farMin = farMinVal;
       
   615     if (min)
       
   616         *min = minVal;
       
   617     if (max)
       
   618         *max = maxVal;
       
   619     if (farMax)
       
   620         *farMax = farMaxVal;
       
   621 }
       
   622 
       
   623 int QSplitterPrivate::adjustPos(int pos, int index, int *farMin, int *min, int *max, int *farMax) const
       
   624 {
       
   625     const int Threshold = 40;
       
   626 
       
   627     getRange(index, farMin, min, max, farMax);
       
   628 
       
   629     if (pos >= *min) {
       
   630         if (pos <= *max) {
       
   631             return pos;
       
   632         } else {
       
   633             int delta = pos - *max;
       
   634             int width = *farMax - *max;
       
   635 
       
   636             if (delta > width / 2 && delta >= qMin(Threshold, width)) {
       
   637                 return *farMax;
       
   638             } else {
       
   639                 return *max;
       
   640             }
       
   641         }
       
   642     } else {
       
   643         int delta = *min - pos;
       
   644         int width = *min - *farMin;
       
   645 
       
   646         if (delta > width / 2 && delta >= qMin(Threshold, width)) {
       
   647             return *farMin;
       
   648         } else {
       
   649             return *min;
       
   650         }
       
   651     }
       
   652 }
       
   653 
       
   654 bool QSplitterPrivate::collapsible(QSplitterLayoutStruct *s) const
       
   655 {
       
   656     if (s->collapsible != Default) {
       
   657         return (bool)s->collapsible;
       
   658     } else {
       
   659         return childrenCollapsible;
       
   660     }
       
   661 }
       
   662 
       
   663 void QSplitterPrivate::updateHandles()
       
   664 {
       
   665     Q_Q(QSplitter);
       
   666     recalc(q->isVisible());
       
   667 }
       
   668 
       
   669 void QSplitterPrivate::setSizes_helper(const QList<int> &sizes, bool clampNegativeSize)
       
   670 {
       
   671     int j = 0;
       
   672 
       
   673     for (int i = 0; i < list.size(); ++i) {
       
   674         QSplitterLayoutStruct *s = list.at(i);
       
   675 
       
   676         s->collapsed = false;
       
   677         s->sizer = sizes.value(j++);
       
   678         if (clampNegativeSize && s->sizer < 0)
       
   679             s->sizer = 0;
       
   680         int smartMinSize = pick(qSmartMinSize(s->widget));
       
   681 
       
   682         // Make sure that we reset the collapsed state.
       
   683         if (s->sizer == 0) {
       
   684             if (collapsible(s) && smartMinSize > 0) {
       
   685                 s->collapsed = true;
       
   686             } else {
       
   687                 s->sizer = smartMinSize;
       
   688             }
       
   689         } else {
       
   690             if (s->sizer < smartMinSize)
       
   691                 s->sizer = smartMinSize;
       
   692         }
       
   693     }
       
   694     doResize();
       
   695 }
       
   696 
       
   697 void QSplitterPrivate::setGeo(QSplitterLayoutStruct *sls, int p, int s, bool allowCollapse)
       
   698 {
       
   699     Q_Q(QSplitter);
       
   700     QWidget *w = sls->widget;
       
   701     QRect r;
       
   702     QRect contents = q->contentsRect();
       
   703     if (orient == Qt::Horizontal) {
       
   704         r.setRect(p, contents.y(), s, contents.height());
       
   705     } else {
       
   706         r.setRect(contents.x(), p, contents.width(), s);
       
   707     }
       
   708     sls->rect = r;
       
   709 
       
   710     int minSize = pick(qSmartMinSize(w));
       
   711 
       
   712     if (orient == Qt::Horizontal && q->isRightToLeft())
       
   713         r.moveRight(contents.width() - r.left());
       
   714 
       
   715     if (allowCollapse)
       
   716         sls->collapsed = s <= 0 && minSize > 0 && !w->isHidden();
       
   717 
       
   718     //   Hide the child widget, but without calling hide() so that
       
   719     //   the splitter handle is still shown.
       
   720     if (sls->collapsed)
       
   721         r.moveTopLeft(QPoint(-r.width()-1, -r.height()-1));
       
   722 
       
   723     w->setGeometry(r);
       
   724 
       
   725     if (!sls->handle->isHidden()) {
       
   726         QSplitterHandle *h = sls->handle;
       
   727         QSize hs = h->sizeHint();
       
   728         int left, top, right, bottom;
       
   729         h->getContentsMargins(&left, &top, &right, &bottom);
       
   730         if (orient==Qt::Horizontal) {
       
   731             if (q->isRightToLeft())
       
   732                 p = contents.width() - p + hs.width();
       
   733             h->setGeometry(p-hs.width() - left, contents.y(), hs.width() + left + right, contents.height());
       
   734         } else {
       
   735             h->setGeometry(contents.x(), p-hs.height() - top, contents.width(), hs.height() + top + bottom);
       
   736         }
       
   737     }
       
   738 }
       
   739 
       
   740 void QSplitterPrivate::doMove(bool backwards, int hPos, int index, int delta, bool mayCollapse,
       
   741                               int *positions, int *widths)
       
   742 {
       
   743     if (index < 0 || index >= list.count())
       
   744         return;
       
   745 
       
   746 #ifdef QSPLITTER_DEBUG
       
   747     qDebug() << "QSplitterPrivate::doMove" << backwards << hPos << index << delta << mayCollapse;
       
   748 #endif
       
   749 
       
   750     QSplitterLayoutStruct *s = list.at(index);
       
   751     QWidget *w = s->widget;
       
   752 
       
   753     int nextId = backwards ? index - delta : index + delta;
       
   754 
       
   755     if (w->isHidden()) {
       
   756         doMove(backwards, hPos, nextId, delta, collapsible(nextId), positions, widths);
       
   757     } else {
       
   758         int hs =s->handle->isHidden() ? 0 : s->getHandleSize(orient);
       
   759 
       
   760         int  ws = backwards ? hPos - pick(s->rect.topLeft())
       
   761                  : pick(s->rect.bottomRight()) - hPos -hs + 1;
       
   762         if (ws > 0 || (!s->collapsed && !mayCollapse)) {
       
   763             ws = qMin(ws, pick(w->maximumSize()));
       
   764             ws = qMax(ws, pick(qSmartMinSize(w)));
       
   765         } else {
       
   766             ws = 0;
       
   767         }
       
   768         positions[index] = backwards ? hPos - ws : hPos + hs;
       
   769         widths[index] = ws;
       
   770         doMove(backwards, backwards ? hPos - ws - hs : hPos + hs + ws, nextId, delta,
       
   771                collapsible(nextId), positions, widths);
       
   772     }
       
   773 
       
   774 }
       
   775 
       
   776 QSplitterLayoutStruct *QSplitterPrivate::findWidget(QWidget *w) const
       
   777 {
       
   778     for (int i = 0; i < list.size(); ++i) {
       
   779         if (list.at(i)->widget == w)
       
   780             return list.at(i);
       
   781     }
       
   782     return 0;
       
   783 }
       
   784 
       
   785 #ifdef QT3_SUPPORT
       
   786 static void setStretch(QWidget *w, int sf)
       
   787 {
       
   788     QSizePolicy sp = w->sizePolicy();
       
   789     sp.setHorizontalStretch(sf);
       
   790     sp.setVerticalStretch(sf);
       
   791     w->setSizePolicy(sp);
       
   792 }
       
   793 
       
   794 static int getStretch(const QWidget *w)
       
   795 {
       
   796     QSizePolicy sp = w->sizePolicy();
       
   797     return qMax(sp.horizontalStretch(), sp.verticalStretch());
       
   798 }
       
   799 
       
   800 void QSplitter::setResizeMode(QWidget *w, ResizeMode mode)
       
   801 {
       
   802     /*
       
   803         Internal comment:
       
   804 
       
   805         This function tries to simulate the Qt 3.x ResizeMode
       
   806         behavior using QSizePolicy stretch factors. This isn't easy,
       
   807         because the default \l ResizeMode was \l Stretch, not \l
       
   808         KeepSize, whereas the default stetch factor is 0.
       
   809 
       
   810         So what we do is this: When the user calls setResizeMode()
       
   811         the first time, we iterate through all the child widgets and
       
   812         set their stretch factors to 1. Later on, if children are
       
   813         added (using addWidget()), their stretch factors are also set
       
   814         to 1.
       
   815 
       
   816         There is just one problem left: Often, setResizeMode() is
       
   817         called \e{before} addWidget(), because addWidget() is called
       
   818         from the event loop. In that case, we use a special value,
       
   819         243, instead of 0 to prevent 0 from being overwritten with 1
       
   820         in addWidget(). This is a wicked hack, but fortunately it
       
   821         only occurs as a result of calling a \c QT3_SUPPORT function.
       
   822     */
       
   823 
       
   824     Q_D(QSplitter);
       
   825     bool metWidget = false;
       
   826     if (!d->compatMode) {
       
   827         d->compatMode = true;
       
   828         for (int i = 0; i < d->list.size(); ++i) {
       
   829             QSplitterLayoutStruct *s = d->list.at(i);
       
   830             if (s->widget == w)
       
   831                 metWidget = true;
       
   832             if (getStretch(s->widget) == 0)
       
   833                 setStretch(s->widget, 1);
       
   834         }
       
   835     }
       
   836     int sf;
       
   837     if (mode == KeepSize)
       
   838         sf = metWidget ? 0 : 243;
       
   839     else
       
   840         sf = 1;
       
   841     setStretch(w, sf);
       
   842 }
       
   843 
       
   844 /*!
       
   845     Use one of the constructors that doesn't take the \a name
       
   846     argument and then use setObjectName() instead.
       
   847 */
       
   848 QSplitter::QSplitter(QWidget *parent, const char *name)
       
   849     : QFrame(*new QSplitterPrivate, parent)
       
   850 {
       
   851     Q_D(QSplitter);
       
   852     setObjectName(QString::fromAscii(name));
       
   853     d->orient = Qt::Horizontal;
       
   854     d->init();
       
   855 }
       
   856 
       
   857 
       
   858 /*!
       
   859     Use one of the constructors that don't take the \a name argument
       
   860     and then use setObjectName() instead.
       
   861 */
       
   862 QSplitter::QSplitter(Qt::Orientation orientation, QWidget *parent, const char *name)
       
   863     : QFrame(*new QSplitterPrivate, parent)
       
   864 {
       
   865     Q_D(QSplitter);
       
   866     setObjectName(QString::fromAscii(name));
       
   867     d->orient = orientation;
       
   868     d->init();
       
   869 }
       
   870 #endif
       
   871 
       
   872 /*!
       
   873     \internal
       
   874 */
       
   875 void QSplitterPrivate::insertWidget_helper(int index, QWidget *widget, bool show)
       
   876 {
       
   877     Q_Q(QSplitter);
       
   878     QBoolBlocker b(blockChildAdd);
       
   879     bool needShow = show && q->isVisible() &&
       
   880                     !(widget->isHidden() && widget->testAttribute(Qt::WA_WState_ExplicitShowHide));
       
   881     if (widget->parentWidget() != q)
       
   882         widget->setParent(q);
       
   883     if (needShow)
       
   884         widget->show();
       
   885     insertWidget(index, widget);
       
   886     recalc(q->isVisible());
       
   887 }
       
   888 
       
   889 /*
       
   890     Inserts the widget \a w at position \a index in the splitter's list of widgets.
       
   891 
       
   892     If \a w is already in the splitter, it will be moved to the new position.
       
   893 */
       
   894 
       
   895 QSplitterLayoutStruct *QSplitterPrivate::insertWidget(int index, QWidget *w)
       
   896 {
       
   897     Q_Q(QSplitter);
       
   898     QSplitterLayoutStruct *sls = 0;
       
   899     int i;
       
   900     int last = list.count();
       
   901     for (i = 0; i < list.size(); ++i) {
       
   902         QSplitterLayoutStruct *s = list.at(i);
       
   903         if (s->widget == w) {
       
   904             sls = s;
       
   905             --last;
       
   906             break;
       
   907         }
       
   908     }
       
   909     if (index < 0 || index > last)
       
   910         index = last;
       
   911 
       
   912     if (sls) {
       
   913         list.move(i,index);
       
   914     } else {
       
   915         QSplitterHandle *newHandle = 0;
       
   916         sls = new QSplitterLayoutStruct;
       
   917         QString tmp = QLatin1String("qt_splithandle_");
       
   918         tmp += w->objectName();
       
   919         newHandle = q->createHandle();
       
   920         newHandle->setObjectName(tmp);
       
   921         sls->handle = newHandle;
       
   922         sls->widget = w;
       
   923         w->lower();
       
   924         list.insert(index,sls);
       
   925 
       
   926         if (newHandle && q->isVisible())
       
   927             newHandle->show(); // will trigger sending of post events
       
   928 
       
   929 #ifdef QT3_SUPPORT
       
   930         if (compatMode) {
       
   931             int sf = getStretch(sls->widget);
       
   932             if (sf == 243)
       
   933                 setStretch(sls->widget, 0);
       
   934             else if (sf == 0)
       
   935                 setStretch(sls->widget, 1);
       
   936         }
       
   937 #endif
       
   938     }
       
   939     return sls;
       
   940 }
       
   941 
       
   942 /*!
       
   943     \class QSplitter
       
   944     \brief The QSplitter class implements a splitter widget.
       
   945 
       
   946     \ingroup organizers
       
   947 
       
   948 
       
   949     A splitter lets the user control the size of child widgets by dragging the
       
   950     boundary between the children. Any number of widgets may be controlled by a
       
   951     single splitter. The typical use of a QSplitter is to create several
       
   952     widgets and add them using insertWidget() or addWidget().
       
   953 
       
   954     The following example will show a QListView, QTreeView, and
       
   955     QTextEdit side by side, with two splitter handles:
       
   956 
       
   957     \snippet doc/src/snippets/splitter/splitter.cpp 0
       
   958 
       
   959     If a widget is already inside a QSplitter when insertWidget() or
       
   960     addWidget() is called, it will move to the new position. This can be used
       
   961     to reorder widgets in the splitter later. You can use indexOf(),
       
   962     widget(), and count() to get access to the widgets inside the splitter.
       
   963 
       
   964     A default QSplitter lays out its children horizontally (side by side); you
       
   965     can use setOrientation(Qt::Vertical) to lay its
       
   966     children out vertically.
       
   967 
       
   968     By default, all widgets can be as large or as small as the user
       
   969     wishes, between the \l minimumSizeHint() (or \l minimumSize())
       
   970     and \l maximumSize() of the widgets.
       
   971 
       
   972     QSplitter resizes its children dynamically by default. If you
       
   973     would rather have QSplitter resize the children only at the end of
       
   974     a resize operation, call setOpaqueResize(false).
       
   975 
       
   976     The initial distribution of size between the widgets is determined by
       
   977     multiplying the initial size with the stretch factor.
       
   978     You can also use setSizes() to set the sizes
       
   979     of all the widgets. The function sizes() returns the sizes set by the user.
       
   980     Alternatively, you can save and restore the sizes of the widgets from a
       
   981     QByteArray using saveState() and restoreState() respectively.
       
   982 
       
   983     When you hide() a child its space will be distributed among the
       
   984     other children. It will be reinstated when you show() it again.
       
   985 
       
   986     \sa QSplitterHandle, QHBoxLayout, QVBoxLayout, QTabWidget
       
   987 */
       
   988 
       
   989 
       
   990 /*!
       
   991     Constructs a horizontal splitter with the \a parent
       
   992     arguments is passed on to the QFrame constructor.
       
   993 
       
   994     \sa setOrientation()
       
   995 */
       
   996 QSplitter::QSplitter(QWidget *parent)
       
   997     : QFrame(*new QSplitterPrivate, parent)
       
   998 {
       
   999     Q_D(QSplitter);
       
  1000     d->orient = Qt::Horizontal;
       
  1001     d->init();
       
  1002 }
       
  1003 
       
  1004 
       
  1005 /*!
       
  1006     Constructs a splitter with the given \a orientation and \a parent.
       
  1007 
       
  1008     \sa setOrientation()
       
  1009 */
       
  1010 QSplitter::QSplitter(Qt::Orientation orientation, QWidget *parent)
       
  1011     : QFrame(*new QSplitterPrivate, parent)
       
  1012 {
       
  1013     Q_D(QSplitter);
       
  1014     d->orient = orientation;
       
  1015     d->init();
       
  1016 }
       
  1017 
       
  1018 
       
  1019 /*!
       
  1020     Destroys the splitter. All children are deleted.
       
  1021 */
       
  1022 
       
  1023 QSplitter::~QSplitter()
       
  1024 {
       
  1025     Q_D(QSplitter);
       
  1026     delete d->rubberBand;
       
  1027     while (!d->list.isEmpty())
       
  1028         delete d->list.takeFirst();
       
  1029 }
       
  1030 
       
  1031 /*!
       
  1032     Updates the splitter's state. You should not need to call this
       
  1033     function.
       
  1034 */
       
  1035 void QSplitter::refresh()
       
  1036 {
       
  1037     Q_D(QSplitter);
       
  1038     d->recalc(true);
       
  1039 }
       
  1040 
       
  1041 /*!
       
  1042     \property QSplitter::orientation
       
  1043     \brief the orientation of the splitter
       
  1044 
       
  1045     By default the orientation is horizontal (i.e., the widgets are
       
  1046     laid out side by side). The possible orientations are
       
  1047     Qt::Horizontal and Qt::Vertical.
       
  1048 
       
  1049     \sa QSplitterHandle::orientation()
       
  1050 */
       
  1051 
       
  1052 void QSplitter::setOrientation(Qt::Orientation orientation)
       
  1053 {
       
  1054     Q_D(QSplitter);
       
  1055     if (d->orient == orientation)
       
  1056         return;
       
  1057 
       
  1058     if (!testAttribute(Qt::WA_WState_OwnSizePolicy)) {
       
  1059         QSizePolicy sp = sizePolicy();
       
  1060         sp.transpose();
       
  1061         setSizePolicy(sp);
       
  1062         setAttribute(Qt::WA_WState_OwnSizePolicy, false);
       
  1063     }
       
  1064 
       
  1065     d->orient = orientation;
       
  1066 
       
  1067     for (int i = 0; i < d->list.size(); ++i) {
       
  1068         QSplitterLayoutStruct *s = d->list.at(i);
       
  1069         s->handle->setOrientation(orientation);
       
  1070     }
       
  1071     d->recalc(isVisible());
       
  1072 }
       
  1073 
       
  1074 Qt::Orientation QSplitter::orientation() const
       
  1075 {
       
  1076     Q_D(const QSplitter);
       
  1077     return d->orient;
       
  1078 }
       
  1079 
       
  1080 /*!
       
  1081     \property QSplitter::childrenCollapsible
       
  1082     \brief whether child widgets can be resized down to size 0 by the user
       
  1083 
       
  1084     By default, children are collapsible. It is possible to enable
       
  1085     and disable the collapsing of individual children using
       
  1086     setCollapsible().
       
  1087 
       
  1088     \sa setCollapsible()
       
  1089 */
       
  1090 
       
  1091 void QSplitter::setChildrenCollapsible(bool collapse)
       
  1092 {
       
  1093     Q_D(QSplitter);
       
  1094     d->childrenCollapsible = collapse;
       
  1095 }
       
  1096 
       
  1097 bool QSplitter::childrenCollapsible() const
       
  1098 {
       
  1099     Q_D(const QSplitter);
       
  1100     return d->childrenCollapsible;
       
  1101 }
       
  1102 
       
  1103 /*!
       
  1104     Sets whether the child widget at index \a index is collapsible to \a collapse.
       
  1105 
       
  1106     By default, children are collapsible, meaning that the user can
       
  1107     resize them down to size 0, even if they have a non-zero
       
  1108     minimumSize() or minimumSizeHint(). This behavior can be changed
       
  1109     on a per-widget basis by calling this function, or globally for
       
  1110     all the widgets in the splitter by setting the \l
       
  1111     childrenCollapsible property.
       
  1112 
       
  1113     \sa childrenCollapsible
       
  1114 */
       
  1115 
       
  1116 void QSplitter::setCollapsible(int index, bool collapse)
       
  1117 {
       
  1118     Q_D(QSplitter);
       
  1119 
       
  1120     if (index < 0 || index >= d->list.size()) {
       
  1121         qWarning("QSplitter::setCollapsible: Index %d out of range", index);
       
  1122         return;
       
  1123     }
       
  1124     d->list.at(index)->collapsible = collapse ? 1 : 0;
       
  1125 }
       
  1126 
       
  1127 /*!
       
  1128     Returns true if the widget at \a index is collapsible, otherwise returns false
       
  1129 */
       
  1130 bool QSplitter::isCollapsible(int index) const
       
  1131 {
       
  1132     Q_D(const QSplitter);
       
  1133     if (index < 0 || index >= d->list.size()) {
       
  1134         qWarning("QSplitter::isCollapsible: Index %d out of range", index);
       
  1135         return false;
       
  1136     }
       
  1137     return d->list.at(index)->collapsible;
       
  1138 }
       
  1139 
       
  1140 /*!
       
  1141     \reimp
       
  1142 */
       
  1143 void QSplitter::resizeEvent(QResizeEvent *)
       
  1144 {
       
  1145     Q_D(QSplitter);
       
  1146     d->doResize();
       
  1147 }
       
  1148 
       
  1149 /*!
       
  1150     Adds the given \a widget to the splitter's layout after all the other
       
  1151     items.
       
  1152 
       
  1153     If \a widget is already in the splitter, it will be moved to the new position.
       
  1154 
       
  1155     \sa insertWidget() widget() indexOf()
       
  1156 */
       
  1157 void QSplitter::addWidget(QWidget *widget)
       
  1158 {
       
  1159     Q_D(QSplitter);
       
  1160     insertWidget(d->list.count(), widget);
       
  1161 }
       
  1162 
       
  1163 /*!
       
  1164     Inserts the \a widget specified into the splitter's layout at the
       
  1165     given \a index.
       
  1166 
       
  1167     If \a widget is already in the splitter, it will be moved to the new position.
       
  1168 
       
  1169     if \a index is an invalid index, then the widget will be inserted at the end.
       
  1170 
       
  1171     \sa addWidget() indexOf() widget()
       
  1172 */
       
  1173 void QSplitter::insertWidget(int index, QWidget *widget)
       
  1174 {
       
  1175     Q_D(QSplitter);
       
  1176     d->insertWidget_helper(index, widget, true);
       
  1177 }
       
  1178 
       
  1179 /*!
       
  1180     \fn int QSplitter::indexOf(QWidget *widget) const
       
  1181 
       
  1182     Returns the index in the splitter's layout of the specified \a widget. This
       
  1183     also works for handles.
       
  1184 
       
  1185     Handles are numbered from 0. There are as many handles as there
       
  1186     are child widgets, but the handle at position 0 is always hidden.
       
  1187 
       
  1188 
       
  1189     \sa count(), widget()
       
  1190 */
       
  1191 int QSplitter::indexOf(QWidget *w) const
       
  1192 {
       
  1193     Q_D(const QSplitter);
       
  1194     for (int i = 0; i < d->list.size(); ++i) {
       
  1195         QSplitterLayoutStruct *s = d->list.at(i);
       
  1196         if (s->widget == w || s->handle == w)
       
  1197             return i;
       
  1198     }
       
  1199     return -1;
       
  1200 }
       
  1201 
       
  1202 /*!
       
  1203     Returns a new splitter handle as a child widget of this splitter.
       
  1204     This function can be reimplemented in subclasses to provide support
       
  1205     for custom handles.
       
  1206 
       
  1207     \sa handle(), indexOf()
       
  1208 */
       
  1209 QSplitterHandle *QSplitter::createHandle()
       
  1210 {
       
  1211     Q_D(QSplitter);
       
  1212     return new QSplitterHandle(d->orient, this);
       
  1213 }
       
  1214 
       
  1215 /*!
       
  1216     Returns the handle to the left (or above) for the item in the
       
  1217     splitter's layout at the given \a index. The handle at index 0 is
       
  1218     always hidden.
       
  1219 
       
  1220     For right-to-left languages such as Arabic and Hebrew, the layout
       
  1221     of horizontal splitters is reversed. The handle will be to the
       
  1222     right of the widget at \a index.
       
  1223 
       
  1224     \sa count(), widget(), indexOf(), createHandle(), setHandleWidth()
       
  1225 */
       
  1226 QSplitterHandle *QSplitter::handle(int index) const
       
  1227 {
       
  1228     Q_D(const QSplitter);
       
  1229     if (index < 0 || index >= d->list.size())
       
  1230         return 0;
       
  1231     return d->list.at(index)->handle;
       
  1232 }
       
  1233 
       
  1234 /*!
       
  1235     Returns the widget at the given \a index in the splitter's layout.
       
  1236 
       
  1237     \sa count(), handle(), indexOf(), insertWidget()
       
  1238 */
       
  1239 QWidget *QSplitter::widget(int index) const
       
  1240 {
       
  1241     Q_D(const QSplitter);
       
  1242     if (index < 0 || index >= d->list.size())
       
  1243         return 0;
       
  1244     return d->list.at(index)->widget;
       
  1245 }
       
  1246 
       
  1247 /*!
       
  1248     Returns the number of widgets contained in the splitter's layout.
       
  1249 
       
  1250     \sa widget(), handle()
       
  1251 */
       
  1252 int QSplitter::count() const
       
  1253 {
       
  1254     Q_D(const QSplitter);
       
  1255     return d->list.count();
       
  1256 }
       
  1257 
       
  1258 /*!
       
  1259     \reimp
       
  1260 
       
  1261     Tells the splitter that the child widget described by \a c has been
       
  1262     inserted or removed.
       
  1263 
       
  1264     This method is also used to handle the situation where a widget is created
       
  1265     with the splitter as a parent but not explicitly added with insertWidget()
       
  1266     or addWidget(). This is for compatibility and not the recommended way of
       
  1267     putting widgets into a splitter in new code. Please use insertWidget() or
       
  1268     addWidget() in new code.
       
  1269 
       
  1270     \sa addWidget() insertWidget()
       
  1271 */
       
  1272 
       
  1273 void QSplitter::childEvent(QChildEvent *c)
       
  1274 {
       
  1275     Q_D(QSplitter);
       
  1276     if (!c->child()->isWidgetType())
       
  1277         return;
       
  1278     QWidget *w = static_cast<QWidget*>(c->child());
       
  1279 
       
  1280     if (c->added() && !d->blockChildAdd && !w->isWindow() && !d->findWidget(w)) {
       
  1281         d->insertWidget_helper(d->list.count(), w, false);
       
  1282     } else if (c->polished() && !d->blockChildAdd) {
       
  1283         if (isVisible() && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide)))
       
  1284             w->show();
       
  1285     } else if (c->type() == QEvent::ChildRemoved) {
       
  1286         for (int i = 0; i < d->list.size(); ++i) {
       
  1287             QSplitterLayoutStruct *s = d->list.at(i);
       
  1288             if (s->widget == w) {
       
  1289                 d->list.removeAt(i);
       
  1290                 delete s;
       
  1291                 d->recalc(isVisible());
       
  1292                 return;
       
  1293             }
       
  1294         }
       
  1295     }
       
  1296 }
       
  1297 
       
  1298 
       
  1299 /*!
       
  1300     Displays a rubber band at position \a pos. If \a pos is negative, the
       
  1301     rubber band is removed.
       
  1302 */
       
  1303 
       
  1304 void QSplitter::setRubberBand(int pos)
       
  1305 {
       
  1306     Q_D(QSplitter);
       
  1307     if (pos < 0) {
       
  1308         if (d->rubberBand)
       
  1309             QTimer::singleShot(0, d->rubberBand, SLOT(deleteLater()));
       
  1310         return;
       
  1311     }
       
  1312     QRect r = contentsRect();
       
  1313     const int rBord = 3; // customizable?
       
  1314     int hw = handleWidth();
       
  1315     if (!d->rubberBand) {
       
  1316         d->rubberBand = new QRubberBand(QRubberBand::Line);
       
  1317         // For accessibility to identify this special widget.
       
  1318         d->rubberBand->setObjectName(QLatin1String("qt_rubberband"));
       
  1319     }
       
  1320     if (d->orient == Qt::Horizontal)
       
  1321         d->rubberBand->setGeometry(QRect(QPoint(pos + hw / 2 - rBord, r.y()),
       
  1322                                          QSize(2 * rBord, r.height())).translated(mapToGlobal(QPoint())));
       
  1323     else
       
  1324         d->rubberBand->setGeometry(QRect(QPoint(r.x(), pos + hw / 2 - rBord),
       
  1325                                    QSize(r.width(), 2 * rBord)).translated(mapToGlobal(QPoint())));
       
  1326     if (!d->rubberBand->isVisible())
       
  1327         d->rubberBand->show();
       
  1328 }
       
  1329 
       
  1330 /*!
       
  1331     \reimp
       
  1332 */
       
  1333 
       
  1334 bool QSplitter::event(QEvent *e)
       
  1335 {
       
  1336     Q_D(QSplitter);
       
  1337     switch (e->type()) {
       
  1338     case QEvent::Hide:
       
  1339         // Reset firstShow to false here since things can be done to the splitter in between
       
  1340         if (!d->firstShow)
       
  1341             d->firstShow = true;
       
  1342         break;
       
  1343     case QEvent::Show:
       
  1344         if (!d->firstShow)
       
  1345             break;
       
  1346         d->firstShow = false;
       
  1347         // fall through
       
  1348     case QEvent::HideToParent:
       
  1349     case QEvent::ShowToParent:
       
  1350     case QEvent::LayoutRequest:
       
  1351 #ifdef QT3_SUPPORT
       
  1352     case QEvent::LayoutHint:
       
  1353 #endif
       
  1354         d->recalc(isVisible());
       
  1355         break;
       
  1356     default:
       
  1357         ;
       
  1358     }
       
  1359     return QWidget::event(e);
       
  1360 }
       
  1361 
       
  1362 /*!
       
  1363     \fn QSplitter::splitterMoved(int pos, int index)
       
  1364 
       
  1365     This signal is emitted when the splitter handle at a particular \a
       
  1366     index has been moved to position \a pos.
       
  1367 
       
  1368     For right-to-left languages such as Arabic and Hebrew, the layout
       
  1369     of horizontal splitters is reversed. \a pos is then the
       
  1370     distance from the right edge of the widget.
       
  1371 
       
  1372     \sa moveSplitter()
       
  1373 */
       
  1374 
       
  1375 /*!
       
  1376     Moves the left or top edge of the splitter handle at \a index as
       
  1377     close as possible to position \a pos, which is the distance from the
       
  1378     left or top edge of the widget.
       
  1379 
       
  1380     For right-to-left languages such as Arabic and Hebrew, the layout
       
  1381     of horizontal splitters is reversed. \a pos is then the distance
       
  1382     from the right edge of the widget.
       
  1383 
       
  1384     \sa splitterMoved(), closestLegalPosition(), getRange()
       
  1385 */
       
  1386 void QSplitter::moveSplitter(int pos, int index)
       
  1387 {
       
  1388     Q_D(QSplitter);
       
  1389     QSplitterLayoutStruct *s = d->list.at(index);
       
  1390     int farMin;
       
  1391     int min;
       
  1392     int max;
       
  1393     int farMax;
       
  1394 
       
  1395 #ifdef QSPLITTER_DEBUG
       
  1396     int debugp = pos;
       
  1397 #endif
       
  1398 
       
  1399     pos = d->adjustPos(pos, index, &farMin, &min, &max, &farMax);
       
  1400     int oldP = d->pick(s->rect.topLeft());
       
  1401 #ifdef QSPLITTER_DEBUG
       
  1402     qDebug() << "QSplitter::moveSplitter" << debugp << index << "adjusted" << pos << "oldP" << oldP;
       
  1403 #endif
       
  1404 
       
  1405     QVarLengthArray<int, 32> poss(d->list.count());
       
  1406     QVarLengthArray<int, 32> ws(d->list.count());
       
  1407     bool upLeft;
       
  1408 
       
  1409     d->doMove(false, pos, index, +1, (d->collapsible(s) && (pos > max)), poss.data(), ws.data());
       
  1410     d->doMove(true, pos, index - 1, +1, (d->collapsible(index - 1) && (pos < min)), poss.data(), ws.data());
       
  1411     upLeft = (pos < oldP);
       
  1412 
       
  1413     int wid, delta, count = d->list.count();
       
  1414     if (upLeft) {
       
  1415         wid = 0;
       
  1416         delta = 1;
       
  1417     } else {
       
  1418         wid = count - 1;
       
  1419         delta = -1;
       
  1420     }
       
  1421     for (; wid >= 0 && wid < count; wid += delta) {
       
  1422         QSplitterLayoutStruct *sls = d->list.at( wid );
       
  1423         if (!sls->widget->isHidden())
       
  1424             d->setGeo(sls, poss[wid], ws[wid], true);
       
  1425     }
       
  1426     d->storeSizes();
       
  1427 
       
  1428     emit splitterMoved(pos, index);
       
  1429 }
       
  1430 
       
  1431 
       
  1432 /*!
       
  1433     Returns the valid range of the splitter with index \a index in
       
  1434     *\a{min} and *\a{max} if \a min and \a max are not 0.
       
  1435 */
       
  1436 
       
  1437 void QSplitter::getRange(int index, int *min, int *max) const
       
  1438 {
       
  1439     Q_D(const QSplitter);
       
  1440     d->getRange(index, min, 0, 0, max);
       
  1441 }
       
  1442 
       
  1443 
       
  1444 /*!
       
  1445     Returns the closest legal position to \a pos of the widget with index
       
  1446     \a index.
       
  1447 
       
  1448     For right-to-left languages such as Arabic and Hebrew, the layout
       
  1449     of horizontal splitters is reversed. Positions are then measured
       
  1450     from the right edge of the widget.
       
  1451 
       
  1452     \sa getRange()
       
  1453 */
       
  1454 
       
  1455 int QSplitter::closestLegalPosition(int pos, int index)
       
  1456 {
       
  1457     Q_D(QSplitter);
       
  1458     int x, i, n, u;
       
  1459     return d->adjustPos(pos, index, &u, &n, &i, &x);
       
  1460 }
       
  1461 
       
  1462 /*!
       
  1463     \property QSplitter::opaqueResize
       
  1464     \brief whether resizing is opaque
       
  1465 
       
  1466     Opaque resizing is on by default.
       
  1467 */
       
  1468 
       
  1469 bool QSplitter::opaqueResize() const
       
  1470 {
       
  1471     Q_D(const QSplitter);
       
  1472     return d->opaque;
       
  1473 }
       
  1474 
       
  1475 
       
  1476 void QSplitter::setOpaqueResize(bool on)
       
  1477 {
       
  1478     Q_D(QSplitter);
       
  1479     d->opaque = on;
       
  1480 }
       
  1481 
       
  1482 #ifdef QT3_SUPPORT
       
  1483 /*!
       
  1484     \fn void QSplitter::moveToFirst(QWidget *widget)
       
  1485 
       
  1486     Use insertWidget(0, \a widget) instead.
       
  1487 */
       
  1488 
       
  1489 
       
  1490 /*!
       
  1491     \fn void QSplitter::moveToLast(QWidget *widget)
       
  1492 
       
  1493     Use addWidget(\a widget) instead.
       
  1494 */
       
  1495 
       
  1496 /*!
       
  1497     \fn void QSplitter::setResizeMode(QWidget *widget, ResizeMode mode)
       
  1498 
       
  1499     Use setStretchFactor() instead.
       
  1500 
       
  1501     \oldcode
       
  1502         splitter->setResizeMode(firstChild, QSplitter::KeepSize);
       
  1503         splitter->setResizeMode(secondChild, QSplitter::Stretch);
       
  1504     \newcode
       
  1505         splitter->setStretchFactor(splitter->indexOf(firstChild), 0);
       
  1506         splitter->setStretchFactor(splitter->indexOf(secondChild), 1);
       
  1507     \endcode
       
  1508 */
       
  1509 
       
  1510 /*!
       
  1511     \enum QSplitter::ResizeMode
       
  1512     \compat
       
  1513 
       
  1514     This enum describes the different resizing behaviors child
       
  1515     widgets can have:
       
  1516 
       
  1517     \value Auto   The widget will be resized according to the stretch factors set in its sizePolicy().
       
  1518     \value Stretch  The widget will be resized when the splitter itself is resized.
       
  1519     \value KeepSize  QSplitter will try to keep the widget's size unchanged.
       
  1520     \value FollowSizeHint  QSplitter will resize the widget when the widget's size hint changes.
       
  1521 
       
  1522     Use setStretchFactor() instead.
       
  1523 */
       
  1524 
       
  1525 /*!
       
  1526     \fn void QSplitter::setCollapsible(QWidget *widget, bool collapsible)
       
  1527 
       
  1528     Use setCollapsible(indexOf(\a widget, \a collapsible)) instead.
       
  1529 */
       
  1530 
       
  1531 /*!
       
  1532     \fn void QSplitter::setMargin(int margin)
       
  1533     Sets the width of the margin around the contents of the widget to \a margin.
       
  1534 
       
  1535     Use QWidget::setContentsMargins() instead.
       
  1536     \sa margin(), QWidget::setContentsMargins()
       
  1537 */
       
  1538 
       
  1539 /*!
       
  1540     \fn int QSplitter::margin() const
       
  1541     Returns the width of the margin around the contents of the widget.
       
  1542 
       
  1543     Use QWidget::getContentsMargins() instead.
       
  1544     \sa setMargin(), QWidget::getContentsMargins()
       
  1545 */
       
  1546 
       
  1547 #endif
       
  1548 
       
  1549 /*!
       
  1550     \reimp
       
  1551 */
       
  1552 QSize QSplitter::sizeHint() const
       
  1553 {
       
  1554     Q_D(const QSplitter);
       
  1555     ensurePolished();
       
  1556     int l = 0;
       
  1557     int t = 0;
       
  1558     QObjectList childList = children();
       
  1559     for (int i = 0; i < childList.size(); ++i) {
       
  1560         if (QWidget *w = qobject_cast<QWidget *>(childList.at(i))) {
       
  1561             if (w->isHidden())
       
  1562                 continue;
       
  1563             QSize s = w->sizeHint();
       
  1564             if (s.isValid()) {
       
  1565                 l += d->pick(s);
       
  1566                 t = qMax(t, d->trans(s));
       
  1567             }
       
  1568         }
       
  1569     }
       
  1570     return orientation() == Qt::Horizontal ? QSize(l, t) : QSize(t, l);
       
  1571 }
       
  1572 
       
  1573 
       
  1574 /*!
       
  1575     \reimp
       
  1576 */
       
  1577 
       
  1578 QSize QSplitter::minimumSizeHint() const
       
  1579 {
       
  1580     Q_D(const QSplitter);
       
  1581     ensurePolished();
       
  1582     int l = 0;
       
  1583     int t = 0;
       
  1584 
       
  1585     for (int i = 0; i < d->list.size(); ++i) {
       
  1586         QSplitterLayoutStruct *s = d->list.at(i);
       
  1587         if (!s || !s->widget)
       
  1588             continue;
       
  1589         if (s->widget->isHidden())
       
  1590             continue;
       
  1591         QSize widgetSize = qSmartMinSize(s->widget);
       
  1592         if (widgetSize.isValid()) {
       
  1593             l += d->pick(widgetSize);
       
  1594             t = qMax(t, d->trans(widgetSize));
       
  1595         }
       
  1596         if (!s->handle || s->handle->isHidden())
       
  1597             continue;
       
  1598         QSize splitterSize = s->handle->sizeHint();
       
  1599         if (splitterSize.isValid()) {
       
  1600             l += d->pick(splitterSize);
       
  1601             t = qMax(t, d->trans(splitterSize));
       
  1602         }
       
  1603     }
       
  1604     return orientation() == Qt::Horizontal ? QSize(l, t) : QSize(t, l);
       
  1605 }
       
  1606 
       
  1607 
       
  1608 /*!
       
  1609     Returns a list of the size parameters of all the widgets in this splitter.
       
  1610 
       
  1611     If the splitter's orientation is horizontal, the list contains the
       
  1612     widgets width in pixels, from left to right; if the orientation is
       
  1613     vertical, the list contains the widgets height in pixels,
       
  1614     from top to bottom.
       
  1615 
       
  1616     Giving the values to another splitter's setSizes() function will
       
  1617     produce a splitter with the same layout as this one.
       
  1618 
       
  1619     Note that invisible widgets have a size of 0.
       
  1620 
       
  1621     \sa setSizes()
       
  1622 */
       
  1623 
       
  1624 QList<int> QSplitter::sizes() const
       
  1625 {
       
  1626     Q_D(const QSplitter);
       
  1627     ensurePolished();
       
  1628 
       
  1629     QList<int> list;
       
  1630     for (int i = 0; i < d->list.size(); ++i) {
       
  1631         QSplitterLayoutStruct *s = d->list.at(i);
       
  1632         list.append(d->pick(s->rect.size()));
       
  1633     }
       
  1634     return list;
       
  1635 }
       
  1636 
       
  1637 /*!
       
  1638     Sets the child widgets respective sizes to the values given in the \a list.
       
  1639 
       
  1640     If the splitter is horizontal, the values set the widths of each
       
  1641     widget in pixels, from left to right. If the splitter is vertical, the
       
  1642     heights of each widget is set, from top to bottom.
       
  1643 
       
  1644     Extra values in the \a list are ignored. If \a list contains too few
       
  1645     values, the result is undefined but the program will still be well-behaved.
       
  1646 
       
  1647     The overall size of the splitter widget is not affected.
       
  1648     Instead, any additional/missing space is distributed amongst the
       
  1649     widgets according to the relative weight of the sizes.
       
  1650 
       
  1651     If you specify a size of 0, the widget will be invisible. The size policies
       
  1652     of the widgets are preserved. That is, a value smaller then the minimal size
       
  1653     hint of the respective widget will be replaced by the value of the hint.
       
  1654 
       
  1655     \sa sizes()
       
  1656 */
       
  1657 
       
  1658 void QSplitter::setSizes(const QList<int> &list)
       
  1659 {
       
  1660     Q_D(QSplitter);
       
  1661     d->setSizes_helper(list, true);
       
  1662 }
       
  1663 
       
  1664 /*!
       
  1665     \property QSplitter::handleWidth
       
  1666     \brief the width of the splitter handles
       
  1667 
       
  1668     By default, this property contains a value that depends on the user's platform
       
  1669     and style preferences.
       
  1670 */
       
  1671 
       
  1672 int QSplitter::handleWidth() const
       
  1673 {
       
  1674     Q_D(const QSplitter);
       
  1675     if (d->handleWidth > 0) {
       
  1676         return d->handleWidth;
       
  1677     } else {
       
  1678         return style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this);
       
  1679     }
       
  1680 }
       
  1681 
       
  1682 void QSplitter::setHandleWidth(int width)
       
  1683 {
       
  1684     Q_D(QSplitter);
       
  1685     d->handleWidth = width;
       
  1686     d->updateHandles();
       
  1687 }
       
  1688 
       
  1689 /*!
       
  1690     \reimp
       
  1691 */
       
  1692 void QSplitter::changeEvent(QEvent *ev)
       
  1693 {
       
  1694     Q_D(QSplitter);
       
  1695     if(ev->type() == QEvent::StyleChange)
       
  1696         d->updateHandles();
       
  1697     QFrame::changeEvent(ev);
       
  1698 }
       
  1699 
       
  1700 static const qint32 SplitterMagic = 0xff;
       
  1701 
       
  1702 /*!
       
  1703     Saves the state of the splitter's layout.
       
  1704 
       
  1705     Typically this is used in conjunction with QSettings to remember the size
       
  1706     for a future session. A version number is stored as part of the data.
       
  1707     Here is an example:
       
  1708 
       
  1709     \snippet doc/src/snippets/splitter/splitter.cpp 1
       
  1710 
       
  1711     \sa restoreState()
       
  1712 */
       
  1713 QByteArray QSplitter::saveState() const
       
  1714 {
       
  1715     Q_D(const QSplitter);
       
  1716     int version = 0;
       
  1717     QByteArray data;
       
  1718     QDataStream stream(&data, QIODevice::WriteOnly);
       
  1719 
       
  1720     stream << qint32(SplitterMagic);
       
  1721     stream << qint32(version);
       
  1722     QList<int> list;
       
  1723     for (int i = 0; i < d->list.size(); ++i) {
       
  1724         QSplitterLayoutStruct *s = d->list.at(i);
       
  1725         list.append(s->sizer);
       
  1726     }
       
  1727     stream << list;
       
  1728     stream << childrenCollapsible();
       
  1729     stream << qint32(handleWidth());
       
  1730     stream << opaqueResize();
       
  1731     stream << qint32(orientation());
       
  1732     return data;
       
  1733 }
       
  1734 
       
  1735 /*!
       
  1736     Restores the splitter's layout to the \a state specified.
       
  1737     Returns true if the state is restored; otherwise returns false.
       
  1738 
       
  1739     Typically this is used in conjunction with QSettings to restore the size
       
  1740     from a past session. Here is an example:
       
  1741 
       
  1742     Restore the splitters's state:
       
  1743 
       
  1744     \snippet doc/src/snippets/splitter/splitter.cpp 2
       
  1745 
       
  1746     A failure to restore the splitter's layout may result from either
       
  1747     invalid or out-of-date data in the supplied byte array.
       
  1748 
       
  1749     \sa saveState()
       
  1750 */
       
  1751 bool QSplitter::restoreState(const QByteArray &state)
       
  1752 {
       
  1753     Q_D(QSplitter);
       
  1754     int version = 0;
       
  1755     QByteArray sd = state;
       
  1756     QDataStream stream(&sd, QIODevice::ReadOnly);
       
  1757     QList<int> list;
       
  1758     bool b;
       
  1759     qint32 i;
       
  1760     qint32 marker;
       
  1761     qint32 v;
       
  1762 
       
  1763     stream >> marker;
       
  1764     stream >> v;
       
  1765     if (marker != SplitterMagic || v != version)
       
  1766         return false;
       
  1767 
       
  1768     stream >> list;
       
  1769     d->setSizes_helper(list, false);
       
  1770 
       
  1771     stream >> b;
       
  1772     setChildrenCollapsible(b);
       
  1773 
       
  1774     stream >> i;
       
  1775     setHandleWidth(i);
       
  1776 
       
  1777     stream >> b;
       
  1778     setOpaqueResize(b);
       
  1779 
       
  1780     stream >> i;
       
  1781     setOrientation(Qt::Orientation(i));
       
  1782     d->doResize();
       
  1783 
       
  1784     return true;
       
  1785 }
       
  1786 
       
  1787 /*!
       
  1788     Updates the size policy of the widget at position \a index to
       
  1789     have a stretch factor of \a stretch.
       
  1790 
       
  1791     \a stretch is not the effective stretch factor; the effective
       
  1792     stretch factor is calculated by taking the initial size of the 
       
  1793     widget and multiplying it with \a stretch.
       
  1794 
       
  1795     This function is provided for convenience. It is equivalent to
       
  1796 
       
  1797     \snippet doc/src/snippets/code/src_gui_widgets_qsplitter.cpp 0
       
  1798 
       
  1799     \sa setSizes(), widget()
       
  1800 */
       
  1801 void QSplitter::setStretchFactor(int index, int stretch)
       
  1802 {
       
  1803     Q_D(QSplitter);
       
  1804     if (index <= -1 || index >= d->list.count())
       
  1805         return;
       
  1806 
       
  1807     QWidget *widget = d->list.at(index)->widget;
       
  1808     QSizePolicy sp = widget->sizePolicy();
       
  1809     sp.setHorizontalStretch(stretch);
       
  1810     sp.setVerticalStretch(stretch);
       
  1811     widget->setSizePolicy(sp);
       
  1812 }
       
  1813 
       
  1814 
       
  1815 //#ifdef QT3_SUPPORT
       
  1816 #ifndef QT_NO_TEXTSTREAM
       
  1817 /*!
       
  1818     \relates QSplitter
       
  1819     \obsolete
       
  1820 
       
  1821     Use \a ts << \a{splitter}.saveState() instead.
       
  1822 */
       
  1823 
       
  1824 QTextStream& operator<<(QTextStream& ts, const QSplitter& splitter)
       
  1825 {
       
  1826     ts << splitter.saveState() << endl;
       
  1827     return ts;
       
  1828 }
       
  1829 
       
  1830 /*!
       
  1831     \relates QSplitter
       
  1832     \obsolete
       
  1833 
       
  1834     Use \a ts >> \a{splitter}.restoreState() instead.
       
  1835 */
       
  1836 
       
  1837 QTextStream& operator>>(QTextStream& ts, QSplitter& splitter)
       
  1838 {
       
  1839     QString line = ts.readLine();
       
  1840     line = line.simplified();
       
  1841     line.replace(QLatin1Char(' '), QString());
       
  1842     line = line.toUpper();
       
  1843 
       
  1844     splitter.restoreState(line.toAscii());
       
  1845     return ts;
       
  1846 }
       
  1847 #endif // QT_NO_TEXTSTREAM
       
  1848 //#endif // QT3_SUPPORT
       
  1849 
       
  1850 QT_END_NAMESPACE
       
  1851 
       
  1852 #endif // QT_NO_SPLITTER