util/src/gui/kernel/qlayout.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 "qlayout.h"
       
    43 
       
    44 #include "qapplication.h"
       
    45 #include "qlayoutengine_p.h"
       
    46 #include "qmenubar.h"
       
    47 #include "qtoolbar.h"
       
    48 #include "qsizegrip.h"
       
    49 #include "qevent.h"
       
    50 #include "qstyle.h"
       
    51 #include "qvariant.h"
       
    52 #include "qwidget_p.h"
       
    53 #include "qlayout_p.h"
       
    54 #include "qformlayout.h"
       
    55 
       
    56 QT_BEGIN_NAMESPACE
       
    57 
       
    58 static int menuBarHeightForWidth(QWidget *menubar, int w)
       
    59 {
       
    60     if (menubar && !menubar->isHidden() && !menubar->isWindow()) {
       
    61         int result = menubar->heightForWidth(qMax(w, menubar->minimumWidth()));
       
    62         if (result != -1)
       
    63             return result;
       
    64         result = menubar->sizeHint()
       
    65             .expandedTo(menubar->minimumSize())
       
    66             .expandedTo(menubar->minimumSizeHint())
       
    67             .boundedTo(menubar->maximumSize()).height();
       
    68         if (result != -1)
       
    69             return result;
       
    70     }
       
    71     return 0;
       
    72 }
       
    73 
       
    74 /*!
       
    75     \class QLayout
       
    76     \brief The QLayout class is the base class of geometry managers.
       
    77 
       
    78     \ingroup geomanagement
       
    79 
       
    80     This is an abstract base class inherited by the concrete classes
       
    81     QBoxLayout, QGridLayout, QFormLayout, and QStackedLayout.
       
    82 
       
    83     For users of QLayout subclasses or of QMainWindow there is seldom
       
    84     any need to use the basic functions provided by QLayout, such as
       
    85     setSizeConstraint() or setMenuBar(). See \l{Layout Management}
       
    86     for more information.
       
    87 
       
    88     To make your own layout manager, implement the functions
       
    89     addItem(), sizeHint(), setGeometry(), itemAt() and takeAt(). You
       
    90     should also implement minimumSize() to ensure your layout isn't
       
    91     resized to zero size if there is too little space. To support
       
    92     children whose heights depend on their widths, implement
       
    93     hasHeightForWidth() and heightForWidth(). See the
       
    94     \l{layouts/borderlayout}{Border Layout} and
       
    95     \l{layouts/flowlayout}{Flow Layout} examples for
       
    96     more information about implementing custom layout managers.
       
    97 
       
    98     Geometry management stops when the layout manager is deleted.
       
    99 
       
   100     \sa QLayoutItem, {Layout Management}, {Basic Layouts Example},
       
   101         {Border Layout Example}, {Flow Layout Example}
       
   102 */
       
   103 
       
   104 
       
   105 /*!
       
   106     Constructs a new top-level QLayout, with parent \a parent.
       
   107     \a parent may not be 0.
       
   108 
       
   109     There can be only one top-level layout for a widget. It is
       
   110     returned by QWidget::layout().
       
   111 */
       
   112 QLayout::QLayout(QWidget *parent)
       
   113     : QObject(*new QLayoutPrivate, parent)
       
   114 {
       
   115     if (!parent)
       
   116         return;
       
   117     parent->setLayout(this);
       
   118 }
       
   119 
       
   120 /*!
       
   121     Constructs a new child QLayout.
       
   122 
       
   123     This layout has to be inserted into another layout before geometry
       
   124     management will work.
       
   125 */
       
   126 QLayout::QLayout()
       
   127     : QObject(*new QLayoutPrivate, 0)
       
   128 {
       
   129 }
       
   130 
       
   131 
       
   132 /*! \internal
       
   133  */
       
   134 QLayout::QLayout(QLayoutPrivate &dd, QLayout *lay, QWidget *w)
       
   135     : QObject(dd, lay ? static_cast<QObject*>(lay) : static_cast<QObject*>(w))
       
   136 {
       
   137     Q_D(QLayout);
       
   138     if (lay) {
       
   139         lay->addItem(this);
       
   140     } else if (w) {
       
   141         if (w->layout()) {
       
   142             qWarning("QLayout: Attempting to add QLayout \"%s\" to %s \"%s\", which"
       
   143                      " already has a layout",
       
   144                      qPrintable(QObject::objectName()), w->metaObject()->className(),
       
   145                      w->objectName().toLocal8Bit().data());
       
   146             setParent(0);
       
   147         } else {
       
   148             d->topLevel = true;
       
   149             w->d_func()->layout = this;
       
   150             QT_TRY {
       
   151                 invalidate();
       
   152             } QT_CATCH(...) {
       
   153                 w->d_func()->layout = 0;
       
   154                 QT_RETHROW;
       
   155             }
       
   156         }
       
   157     }
       
   158 }
       
   159 
       
   160 QLayoutPrivate::QLayoutPrivate()
       
   161     : QObjectPrivate(), insideSpacing(-1), userLeftMargin(-1), userTopMargin(-1), userRightMargin(-1),
       
   162       userBottomMargin(-1), topLevel(false), enabled(true), activated(true), autoNewChild(false),
       
   163       constraint(QLayout::SetDefaultConstraint), menubar(0)
       
   164 {
       
   165 }
       
   166 
       
   167 void QLayoutPrivate::getMargin(int *result, int userMargin, QStyle::PixelMetric pm) const
       
   168 {
       
   169     if (!result)
       
   170         return;
       
   171 
       
   172     Q_Q(const QLayout);
       
   173     if (userMargin >= 0) {
       
   174         *result = userMargin;
       
   175     } else if (!topLevel) {
       
   176         *result = 0;
       
   177     } else if (QWidget *pw = q->parentWidget()) {
       
   178         *result = pw->style()->pixelMetric(pm, 0, pw);
       
   179     } else {
       
   180         *result = 0;
       
   181     }
       
   182 }
       
   183 
       
   184 // Static item factory functions that allow for hooking things in Designer
       
   185 
       
   186 QLayoutPrivate::QWidgetItemFactoryMethod QLayoutPrivate::widgetItemFactoryMethod = 0;
       
   187 QLayoutPrivate::QSpacerItemFactoryMethod QLayoutPrivate::spacerItemFactoryMethod = 0;
       
   188 
       
   189 QWidgetItem *QLayoutPrivate::createWidgetItem(const QLayout *layout, QWidget *widget)
       
   190 {
       
   191     if (widgetItemFactoryMethod)
       
   192         if (QWidgetItem *wi = (*widgetItemFactoryMethod)(layout, widget))
       
   193             return wi;
       
   194     return new QWidgetItemV2(widget);
       
   195 }
       
   196 
       
   197 QSpacerItem *QLayoutPrivate::createSpacerItem(const QLayout *layout, int w, int h, QSizePolicy::Policy hPolicy, QSizePolicy::Policy vPolicy)
       
   198 {
       
   199     if (spacerItemFactoryMethod)
       
   200         if (QSpacerItem *si = (*spacerItemFactoryMethod)(layout, w, h, hPolicy, vPolicy))
       
   201             return si;
       
   202     return new QSpacerItem(w, h,  hPolicy, vPolicy);
       
   203 }
       
   204 
       
   205 #ifdef QT3_SUPPORT
       
   206 /*!
       
   207     Constructs a new top-level QLayout called \a name, with parent
       
   208     widget \a parent. \a parent may not be 0.
       
   209 
       
   210     The \a margin is the number of pixels between the edge of the
       
   211     widget and the managed children. The \a spacing sets the value of
       
   212     spacing(), which gives the spacing between the managed widgets. If
       
   213     \a spacing is -1 (the default), spacing is set to the value of \a
       
   214     margin.
       
   215 
       
   216     There can be only one top-level layout for a widget. It is
       
   217     returned by QWidget::layout()
       
   218 
       
   219     \sa QWidget::setLayout()
       
   220 */
       
   221 QLayout::QLayout(QWidget *parent, int margin, int spacing, const char *name)
       
   222     : QObject(*new QLayoutPrivate,parent)
       
   223 {
       
   224     Q_D(QLayout);
       
   225     setObjectName(QString::fromAscii(name));
       
   226     setMargin(margin);
       
   227     if (spacing < 0)
       
   228         d->insideSpacing = margin;
       
   229     else
       
   230         d->insideSpacing = spacing;
       
   231     if (parent) {
       
   232         if (parent->layout()) {
       
   233             qWarning("QLayout \"%s\" added to %s \"%s\", which already has a layout",
       
   234                      QObject::objectName().toLocal8Bit().data(), parent->metaObject()->className(),
       
   235                      parent->objectName().toLocal8Bit().data());
       
   236             parent->layout()->setParent(0);
       
   237         } else {
       
   238             d->topLevel = true;
       
   239             parent->d_func()->layout = this;
       
   240             QT_TRY {
       
   241                 invalidate();
       
   242             } QT_CATCH(...) {
       
   243                 parent->d_func()->layout = 0;
       
   244                 QT_RETHROW;
       
   245             }
       
   246         }
       
   247     }
       
   248 }
       
   249 
       
   250 /*!
       
   251     Constructs a new child QLayout called \a name, and places it
       
   252     inside \a parentLayout by using the default placement defined by
       
   253     addItem().
       
   254 
       
   255     If \a spacing is -1, this QLayout inherits \a parentLayout's
       
   256     spacing(), otherwise the value of \a spacing is used.
       
   257 */
       
   258 QLayout::QLayout(QLayout *parentLayout, int spacing, const char *name)
       
   259     : QObject(*new QLayoutPrivate,parentLayout)
       
   260 
       
   261 {
       
   262     Q_D(QLayout);
       
   263     setObjectName(QString::fromAscii(name));
       
   264     d->insideSpacing = spacing;
       
   265     parentLayout->addItem(this);
       
   266 }
       
   267 
       
   268 /*!
       
   269     Constructs a new child QLayout called \a name. If \a spacing is
       
   270     -1, this QLayout inherits its parent's spacing(); otherwise the
       
   271     value of \a spacing is used.
       
   272 
       
   273     This layout has to be inserted into another layout before geometry
       
   274     management will work.
       
   275 */
       
   276 QLayout::QLayout(int spacing, const char *name)
       
   277     : QObject(*new QLayoutPrivate, 0)
       
   278 {
       
   279     Q_D(QLayout);
       
   280     setObjectName(QString::fromAscii(name));
       
   281     d->insideSpacing = spacing;
       
   282 }
       
   283 
       
   284 /*!
       
   285     Automatically adding widgets is deprecated. Use addWidget() or
       
   286     addLayout() instead.
       
   287 */
       
   288 void QLayout::setAutoAdd(bool a) { Q_D(QLayout); d->autoNewChild = a; }
       
   289 
       
   290 /*!
       
   291     Automatically adding widgets is deprecated. Use addWidget() or
       
   292     addLayout() instead.
       
   293 */
       
   294 bool QLayout::autoAdd() const { Q_D(const QLayout); return d->autoNewChild; }
       
   295 #endif
       
   296 
       
   297 
       
   298 /*!
       
   299     \fn void QLayout::addItem(QLayoutItem *item)
       
   300 
       
   301     Implemented in subclasses to add an \a item. How it is added is
       
   302     specific to each subclass.
       
   303 
       
   304     This function is not usually called in application code. To add a widget
       
   305     to a layout, use the addWidget() function; to add a child layout, use the
       
   306     addLayout() function provided by the relevant QLayout subclass.
       
   307 
       
   308     \bold{Note:} The ownership of \a item is transferred to the layout, and it's
       
   309     the layout's responsibility to delete it.
       
   310 
       
   311     \sa addWidget(), QBoxLayout::addLayout(), QGridLayout::addLayout()
       
   312 */
       
   313 
       
   314 /*!
       
   315     Adds widget \a w to this layout in a manner specific to the
       
   316     layout. This function uses addItem().
       
   317 */
       
   318 void QLayout::addWidget(QWidget *w)
       
   319 {
       
   320     addChildWidget(w);
       
   321     addItem(QLayoutPrivate::createWidgetItem(this, w));
       
   322 }
       
   323 
       
   324 
       
   325 
       
   326 /*!
       
   327     Sets the alignment for widget \a w to \a alignment and returns
       
   328     true if \a w is found in this layout (not including child
       
   329     layouts); otherwise returns false.
       
   330 */
       
   331 bool QLayout::setAlignment(QWidget *w, Qt::Alignment alignment)
       
   332 {
       
   333     int i = 0;
       
   334     QLayoutItem *item = itemAt(i);
       
   335     while (item) {
       
   336         if (item->widget() == w) {
       
   337             item->setAlignment(alignment);
       
   338             invalidate();
       
   339             return true;
       
   340         }
       
   341         ++i;
       
   342         item = itemAt(i);
       
   343     }
       
   344     return false;
       
   345 }
       
   346 
       
   347 /*!
       
   348   \overload
       
   349 
       
   350   Sets the alignment for the layout \a l to \a alignment and
       
   351   returns true if \a l is found in this layout (not including child
       
   352   layouts); otherwise returns false.
       
   353 */
       
   354 bool QLayout::setAlignment(QLayout *l, Qt::Alignment alignment)
       
   355 {
       
   356     int i = 0;
       
   357     QLayoutItem *item = itemAt(i);
       
   358     while (item) {
       
   359         if (item->layout() == l) {
       
   360             item->setAlignment(alignment);
       
   361             invalidate();
       
   362             return true;
       
   363         }
       
   364         ++i;
       
   365         item = itemAt(i);
       
   366     }
       
   367     return false;
       
   368 }
       
   369 
       
   370 /*!
       
   371     \fn void QLayout::setAlignment(Qt::Alignment alignment)
       
   372 
       
   373     Sets the alignment of this item to \a alignment.
       
   374 
       
   375     \sa QLayoutItem::setAlignment()
       
   376 */
       
   377 
       
   378 /*!
       
   379     \fn bool QLayout::isTopLevel() const
       
   380 
       
   381     Returns true if this layout is a top-level layout, i.e. not a
       
   382     child of another layout; otherwise returns false.
       
   383 */
       
   384 
       
   385 /*!
       
   386     \property QLayout::margin
       
   387     \brief the width of the outside border of the layout
       
   388     \obsolete
       
   389 
       
   390     Use setContentsMargins() and getContentsMargins() instead.
       
   391 
       
   392     \sa contentsRect(), spacing
       
   393 */
       
   394 
       
   395 /*!
       
   396     \obsolete
       
   397 */
       
   398 int QLayout::margin() const
       
   399 {
       
   400     int left, top, right, bottom;
       
   401     getContentsMargins(&left, &top, &right, &bottom);
       
   402     if (left == top && top == right && right == bottom) {
       
   403         return left;
       
   404     } else {
       
   405         return -1;
       
   406     }
       
   407 }
       
   408 
       
   409 /*!
       
   410     \property QLayout::spacing
       
   411     \brief the spacing between widgets inside the layout
       
   412 
       
   413     If no value is explicitly set, the layout's spacing is inherited
       
   414     from the parent layout, or from the style settings for the parent
       
   415     widget.
       
   416 
       
   417     For QGridLayout and QFormLayout, it is possible to set different horizontal and
       
   418     vertical spacings using \l{QGridLayout::}{setHorizontalSpacing()}
       
   419     and \l{QGridLayout::}{setVerticalSpacing()}. In that case,
       
   420     spacing() returns -1.
       
   421 
       
   422     \sa contentsRect(), getContentsMargins(), QStyle::layoutSpacing(),
       
   423         QStyle::pixelMetric()
       
   424 */
       
   425 
       
   426 int QLayout::spacing() const
       
   427 {
       
   428     if (const QBoxLayout* boxlayout = qobject_cast<const QBoxLayout*>(this)) {
       
   429         return boxlayout->spacing();
       
   430     } else if (const QGridLayout* gridlayout = qobject_cast<const QGridLayout*>(this)) {
       
   431         return gridlayout->spacing();
       
   432     } else if (const QFormLayout* formlayout = qobject_cast<const QFormLayout*>(this)) {
       
   433         return formlayout->spacing();
       
   434     } else {
       
   435         Q_D(const QLayout);
       
   436         if (d->insideSpacing >=0) {
       
   437             return d->insideSpacing;
       
   438         } else {
       
   439             // arbitrarily prefer horizontal spacing to vertical spacing
       
   440             return qSmartSpacing(this, QStyle::PM_LayoutHorizontalSpacing);
       
   441         }
       
   442     }
       
   443 }
       
   444 
       
   445 /*!
       
   446     \obsolete
       
   447 */
       
   448 void QLayout::setMargin(int margin)
       
   449 {
       
   450     setContentsMargins(margin, margin, margin, margin);
       
   451 }
       
   452 
       
   453 void QLayout::setSpacing(int spacing)
       
   454 {
       
   455     if (QBoxLayout* boxlayout = qobject_cast<QBoxLayout*>(this)) {
       
   456         boxlayout->setSpacing(spacing);
       
   457     } else if (QGridLayout* gridlayout = qobject_cast<QGridLayout*>(this)) {
       
   458         gridlayout->setSpacing(spacing);
       
   459     } else if (QFormLayout* formlayout = qobject_cast<QFormLayout*>(this)) {
       
   460         formlayout->setSpacing(spacing);
       
   461     } else {
       
   462         Q_D(QLayout);
       
   463         d->insideSpacing = spacing;
       
   464         invalidate();
       
   465     }
       
   466 }
       
   467 
       
   468 /*!
       
   469     \since 4.3
       
   470 
       
   471     Sets the \a left, \a top, \a right, and \a bottom margins to use
       
   472     around the layout.
       
   473 
       
   474     By default, QLayout uses the values provided by the style. On
       
   475     most platforms, the margin is 11 pixels in all directions.
       
   476 
       
   477     \sa getContentsMargins(), QStyle::pixelMetric(),
       
   478         {QStyle::}{PM_LayoutLeftMargin},
       
   479         {QStyle::}{PM_LayoutTopMargin},
       
   480         {QStyle::}{PM_LayoutRightMargin},
       
   481         {QStyle::}{PM_LayoutBottomMargin}
       
   482 */
       
   483 void QLayout::setContentsMargins(int left, int top, int right, int bottom)
       
   484 {
       
   485     Q_D(QLayout);
       
   486 
       
   487     if (d->userLeftMargin == left && d->userTopMargin == top &&
       
   488         d->userRightMargin == right && d->userBottomMargin == bottom)
       
   489         return;
       
   490 
       
   491     d->userLeftMargin = left;
       
   492     d->userTopMargin = top;
       
   493     d->userRightMargin = right;
       
   494     d->userBottomMargin = bottom;
       
   495     invalidate();
       
   496 }
       
   497 
       
   498 /*!
       
   499     \since 4.6
       
   500 
       
   501     Sets the \a margins to use around the layout.
       
   502 
       
   503     By default, QLayout uses the values provided by the style. On
       
   504     most platforms, the margin is 11 pixels in all directions.
       
   505 
       
   506     \sa contentsMargins()
       
   507 */
       
   508 void QLayout::setContentsMargins(const QMargins &margins)
       
   509 {
       
   510     setContentsMargins(margins.left(), margins.top(), margins.right(), margins.bottom());
       
   511 }
       
   512 
       
   513 /*!
       
   514     \since 4.3
       
   515 
       
   516     Extracts the left, top, right, and bottom margins used around the
       
   517     layout, and assigns them to *\a left, *\a top, *\a right, and *\a
       
   518     bottom (unless they are null pointers).
       
   519 
       
   520     By default, QLayout uses the values provided by the style. On
       
   521     most platforms, the margin is 11 pixels in all directions.
       
   522 
       
   523     \sa setContentsMargins(), QStyle::pixelMetric(),
       
   524         {QStyle::}{PM_LayoutLeftMargin},
       
   525         {QStyle::}{PM_LayoutTopMargin},
       
   526         {QStyle::}{PM_LayoutRightMargin},
       
   527         {QStyle::}{PM_LayoutBottomMargin}
       
   528 */
       
   529 void QLayout::getContentsMargins(int *left, int *top, int *right, int *bottom) const
       
   530 {
       
   531     Q_D(const QLayout);
       
   532     d->getMargin(left, d->userLeftMargin, QStyle::PM_LayoutLeftMargin);
       
   533     d->getMargin(top, d->userTopMargin, QStyle::PM_LayoutTopMargin);
       
   534     d->getMargin(right, d->userRightMargin, QStyle::PM_LayoutRightMargin);
       
   535     d->getMargin(bottom, d->userBottomMargin, QStyle::PM_LayoutBottomMargin);
       
   536 }
       
   537 
       
   538 /*!
       
   539     \since 4.6
       
   540 
       
   541     Returns the margins used around the layout.
       
   542 
       
   543     By default, QLayout uses the values provided by the style. On
       
   544     most platforms, the margin is 11 pixels in all directions.
       
   545 
       
   546     \sa setContentsMargins()
       
   547 */
       
   548 QMargins QLayout::contentsMargins() const
       
   549 {
       
   550     int left, top, right, bottom;
       
   551     getContentsMargins(&left, &top, &right, &bottom);
       
   552     return QMargins(left, top, right, bottom);
       
   553 }
       
   554 
       
   555 /*!
       
   556     \since 4.3
       
   557 
       
   558     Returns the layout's geometry() rectangle, but taking into account the
       
   559     contents margins.
       
   560 
       
   561     \sa setContentsMargins(), getContentsMargins()
       
   562 */
       
   563 QRect QLayout::contentsRect() const
       
   564 {
       
   565     Q_D(const QLayout);
       
   566     int left, top, right, bottom;
       
   567     getContentsMargins(&left, &top, &right, &bottom);
       
   568     return d->rect.adjusted(+left, +top, -right, -bottom);
       
   569 }
       
   570 
       
   571 #ifdef QT3_SUPPORT
       
   572 bool QLayout::isTopLevel() const
       
   573 {
       
   574     Q_D(const QLayout);
       
   575     return d->topLevel;
       
   576 }
       
   577 #endif
       
   578 
       
   579 /*!
       
   580     Returns the parent widget of this layout, or 0 if this layout is
       
   581     not installed on any widget.
       
   582 
       
   583     If the layout is a sub-layout, this function returns the parent
       
   584     widget of the parent layout.
       
   585 
       
   586     \sa parent()
       
   587 */
       
   588 QWidget *QLayout::parentWidget() const
       
   589 {
       
   590     Q_D(const QLayout);
       
   591     if (!d->topLevel) {
       
   592         if (parent()) {
       
   593             QLayout *parentLayout = qobject_cast<QLayout*>(parent());
       
   594             if (!parentLayout) {
       
   595                 qWarning("QLayout::parentWidget: A layout can only have another layout as a parent.");
       
   596                 return 0;
       
   597             }
       
   598             return parentLayout->parentWidget();
       
   599         } else {
       
   600             return 0;
       
   601         }
       
   602     } else {
       
   603         Q_ASSERT(parent() && parent()->isWidgetType());
       
   604         return static_cast<QWidget *>(parent());
       
   605     }
       
   606 }
       
   607 
       
   608 /*!
       
   609     \reimp
       
   610 */
       
   611 bool QLayout::isEmpty() const
       
   612 {
       
   613     int i = 0;
       
   614     QLayoutItem *item = itemAt(i);
       
   615     while (item) {
       
   616         if (!item->isEmpty())
       
   617             return false;
       
   618         ++i;
       
   619         item = itemAt(i);
       
   620     }
       
   621     return true;
       
   622 }
       
   623 
       
   624 /*!
       
   625     \reimp
       
   626 */
       
   627 void QLayout::setGeometry(const QRect &r)
       
   628 {
       
   629     Q_D(QLayout);
       
   630     d->rect = r;
       
   631 }
       
   632 
       
   633 /*!
       
   634     \reimp
       
   635 */
       
   636 QRect QLayout::geometry() const
       
   637 {
       
   638     Q_D(const QLayout);
       
   639     return d->rect;
       
   640 }
       
   641 
       
   642 /*!
       
   643     \reimp
       
   644 */
       
   645 void QLayout::invalidate()
       
   646 {
       
   647     Q_D(QLayout);
       
   648     d->rect = QRect();
       
   649     update();
       
   650 }
       
   651 
       
   652 static bool removeWidgetRecursively(QLayoutItem *li, QWidget *w)
       
   653 {
       
   654     QLayout *lay = li->layout();
       
   655     if (!lay)
       
   656         return false;
       
   657     int i = 0;
       
   658     QLayoutItem *child;
       
   659     while ((child = lay->itemAt(i))) {
       
   660         if (child->widget() == w) {
       
   661             delete lay->takeAt(i);
       
   662             lay->invalidate();
       
   663             return true;
       
   664         } else if (removeWidgetRecursively(child, w)) {
       
   665             return true;
       
   666         } else {
       
   667             ++i;
       
   668         }
       
   669     }
       
   670     return false;
       
   671 }
       
   672 
       
   673 
       
   674 void QLayoutPrivate::doResize(const QSize &r)
       
   675 {
       
   676     Q_Q(QLayout);
       
   677     int mbh = menuBarHeightForWidth(menubar, r.width());
       
   678     QWidget *mw = q->parentWidget();
       
   679     QRect rect = mw->testAttribute(Qt::WA_LayoutOnEntireRect) ? mw->rect() : mw->contentsRect();
       
   680     rect.setTop(rect.top() + mbh);
       
   681     q->setGeometry(rect);
       
   682 #ifndef QT_NO_MENUBAR
       
   683     if (menubar)
       
   684         menubar->setGeometry(0,0,r.width(), mbh);
       
   685 #endif
       
   686 }
       
   687 
       
   688 
       
   689 /*!
       
   690     \internal
       
   691     Performs child widget layout when the parent widget is
       
   692     resized.  Also handles removal of widgets. \a e is the
       
   693     event
       
   694 */
       
   695 void QLayout::widgetEvent(QEvent *e)
       
   696 {
       
   697     Q_D(QLayout);
       
   698     if (!d->enabled)
       
   699         return;
       
   700 
       
   701     switch (e->type()) {
       
   702     case QEvent::Resize:
       
   703         if (d->activated) {
       
   704             QResizeEvent *r = (QResizeEvent *)e;
       
   705             d->doResize(r->size());
       
   706         } else {
       
   707             activate();
       
   708         }
       
   709         break;
       
   710     case QEvent::ChildRemoved:
       
   711         {
       
   712             QChildEvent *c = (QChildEvent *)e;
       
   713             if (c->child()->isWidgetType()) {
       
   714                 QWidget *w = (QWidget *)c->child();
       
   715 #ifndef QT_NO_MENUBAR
       
   716                 if (w == d->menubar)
       
   717                     d->menubar = 0;
       
   718 #endif
       
   719                 removeWidgetRecursively(this, w);
       
   720             }
       
   721         }
       
   722         break;
       
   723 #ifdef QT3_SUPPORT
       
   724     case QEvent::ChildInserted:
       
   725         if (d->topLevel && d->autoNewChild) {
       
   726             QChildEvent *c = (QChildEvent *)e;
       
   727             if (c->child()->isWidgetType()) {
       
   728                 QWidget *w = (QWidget *)c->child();
       
   729                 if (!w->isWindow()) {
       
   730 #if !defined(QT_NO_MENUBAR) && !defined(QT_NO_TOOLBAR)
       
   731                     if (qobject_cast<QMenuBar*>(w) && !qobject_cast<QToolBar*>(w->parentWidget())) {
       
   732                         d->menubar = (QMenuBar *)w;
       
   733                         invalidate();
       
   734                     } else
       
   735 #endif
       
   736 #ifndef QT_NO_SIZEGRIP
       
   737                     if (qobject_cast<QSizeGrip*>(w) ) {
       
   738                         //SizeGrip is handled by the dialog itself.
       
   739                     } else
       
   740 #endif
       
   741                         addItem(QLayoutPrivate::createWidgetItem(this, w));
       
   742                 }
       
   743             }
       
   744         }
       
   745         break;
       
   746     case QEvent::LayoutHint:
       
   747         d->activated = false;
       
   748         // fall through
       
   749 #endif
       
   750     case QEvent::LayoutRequest:
       
   751         if (static_cast<QWidget *>(parent())->isVisible())
       
   752             activate();
       
   753         break;
       
   754     default:
       
   755         break;
       
   756     }
       
   757 }
       
   758 
       
   759 /*!
       
   760     \reimp
       
   761 */
       
   762 void QLayout::childEvent(QChildEvent *e)
       
   763 {
       
   764     Q_D(QLayout);
       
   765     if (!d->enabled)
       
   766         return;
       
   767 
       
   768     if (e->type() == QEvent::ChildRemoved) {
       
   769         QChildEvent *c = (QChildEvent*)e;
       
   770         int i = 0;
       
   771 
       
   772         QLayoutItem *item;
       
   773         while ((item = itemAt(i))) {
       
   774             if (item == static_cast<QLayout*>(c->child())) {
       
   775                 takeAt(i);
       
   776                 invalidate();
       
   777                 break;
       
   778             } else {
       
   779                 ++i;
       
   780             }
       
   781         }
       
   782     }
       
   783 }
       
   784 
       
   785 /*!
       
   786   \internal
       
   787   Also takes contentsMargins and menu bar into account.
       
   788 */
       
   789 int QLayout::totalHeightForWidth(int w) const
       
   790 {
       
   791     Q_D(const QLayout);
       
   792     int side=0, top=0;
       
   793     if (d->topLevel) {
       
   794         QWidget *parent = parentWidget();
       
   795         parent->ensurePolished();
       
   796         QWidgetPrivate *wd = parent->d_func();
       
   797         side += wd->leftmargin + wd->rightmargin;
       
   798         top += wd->topmargin + wd->bottommargin;
       
   799     }
       
   800     int h = heightForWidth(w - side) + top;
       
   801 #ifndef QT_NO_MENUBAR
       
   802     h += menuBarHeightForWidth(d->menubar, w);
       
   803 #endif
       
   804     return h;
       
   805 }
       
   806 
       
   807 /*!
       
   808   \internal
       
   809   Also takes contentsMargins and menu bar into account.
       
   810 */
       
   811 QSize QLayout::totalMinimumSize() const
       
   812 {
       
   813     Q_D(const QLayout);
       
   814     int side=0, top=0;
       
   815     if (d->topLevel) {
       
   816         QWidget *pw = parentWidget();
       
   817         pw->ensurePolished();
       
   818         QWidgetPrivate *wd = pw->d_func();
       
   819         side += wd->leftmargin + wd->rightmargin;
       
   820         top += wd->topmargin + wd->bottommargin;
       
   821     }
       
   822 
       
   823     QSize s = minimumSize();
       
   824 #ifndef QT_NO_MENUBAR
       
   825     top += menuBarHeightForWidth(d->menubar, s.width() + side);
       
   826 #endif
       
   827     return s + QSize(side, top);
       
   828 }
       
   829 
       
   830 /*!
       
   831   \internal
       
   832   Also takes contentsMargins and menu bar into account.
       
   833 */
       
   834 QSize QLayout::totalSizeHint() const
       
   835 {
       
   836     Q_D(const QLayout);
       
   837     int side=0, top=0;
       
   838     if (d->topLevel) {
       
   839         QWidget *pw = parentWidget();
       
   840         pw->ensurePolished();
       
   841         QWidgetPrivate *wd = pw->d_func();
       
   842         side += wd->leftmargin + wd->rightmargin;
       
   843         top += wd->topmargin + wd->bottommargin;
       
   844     }
       
   845 
       
   846     QSize s = sizeHint();
       
   847     if (hasHeightForWidth())
       
   848         s.setHeight(heightForWidth(s.width() + side));
       
   849 #ifndef QT_NO_MENUBAR
       
   850     top += menuBarHeightForWidth(d->menubar, s.width());
       
   851 #endif
       
   852     return s + QSize(side, top);
       
   853 }
       
   854 
       
   855 /*!
       
   856   \internal
       
   857   Also takes contentsMargins and menu bar into account.
       
   858 */
       
   859 QSize QLayout::totalMaximumSize() const
       
   860 {
       
   861     Q_D(const QLayout);
       
   862     int side=0, top=0;
       
   863     if (d->topLevel) {
       
   864         QWidget *pw = parentWidget();
       
   865         pw->ensurePolished();
       
   866         QWidgetPrivate *wd = pw->d_func();
       
   867         side += wd->leftmargin + wd->rightmargin;
       
   868         top += wd->topmargin + wd->bottommargin;
       
   869     }
       
   870 
       
   871     QSize s = maximumSize();
       
   872 #ifndef QT_NO_MENUBAR
       
   873     top += menuBarHeightForWidth(d->menubar, s.width());
       
   874 #endif
       
   875 
       
   876     if (d->topLevel)
       
   877         s = QSize(qMin(s.width() + side, QLAYOUTSIZE_MAX),
       
   878                    qMin(s.height() + top, QLAYOUTSIZE_MAX));
       
   879     return s;
       
   880 }
       
   881 
       
   882 /*!
       
   883   \internal
       
   884   Destroys the layout, deleting all child layouts.
       
   885   Geometry management stops when a top-level layout is deleted.
       
   886 
       
   887   The layout classes will probably be fatally confused if you delete
       
   888   a sublayout.
       
   889 */
       
   890 QLayout::~QLayout()
       
   891 {
       
   892     Q_D(QLayout);
       
   893     /*
       
   894       This function may be called during the QObject destructor,
       
   895       when the parent no longer is a QWidget.
       
   896     */
       
   897     if (d->topLevel && parent() && parent()->isWidgetType() &&
       
   898          ((QWidget*)parent())->layout() == this)
       
   899         ((QWidget*)parent())->d_func()->layout = 0;
       
   900 }
       
   901 
       
   902 #ifdef QT3_SUPPORT
       
   903 /*!
       
   904     Removes and deletes all items in this layout.
       
   905 */
       
   906 void QLayout::deleteAllItems()
       
   907 {
       
   908     QLayoutItem *l;
       
   909     while ((l = takeAt(0)))
       
   910         delete l;
       
   911 }
       
   912 #endif
       
   913 
       
   914 /*!
       
   915     This function is called from \c addLayout() or \c insertLayout() functions in
       
   916     subclasses to add layout \a l as a sub-layout.
       
   917 
       
   918     The only scenario in which you need to call it directly is if you
       
   919     implement a custom layout that supports nested layouts.
       
   920 
       
   921     \sa QBoxLayout::addLayout(), QBoxLayout::insertLayout(), QGridLayout::addLayout()
       
   922 */
       
   923 void QLayout::addChildLayout(QLayout *l)
       
   924 {
       
   925     if (l->parent()) {
       
   926         qWarning("QLayout::addChildLayout: layout \"%s\" already has a parent",
       
   927                  l->objectName().toLocal8Bit().data());
       
   928         return;
       
   929     }
       
   930     l->setParent(this);
       
   931 
       
   932     if (QWidget *mw = parentWidget()) {
       
   933         l->d_func()->reparentChildWidgets(mw);
       
   934     }
       
   935 
       
   936 }
       
   937 
       
   938 #ifdef QT_DEBUG
       
   939 static bool layoutDebug()
       
   940 {
       
   941     static int checked_env = -1;
       
   942     if(checked_env == -1)
       
   943         checked_env = !!qgetenv("QT_LAYOUT_DEBUG").toInt();
       
   944 
       
   945     return checked_env;
       
   946 }
       
   947 #endif
       
   948 
       
   949 void QLayoutPrivate::reparentChildWidgets(QWidget *mw)
       
   950 {
       
   951     Q_Q(QLayout);
       
   952     int n =  q->count();
       
   953 
       
   954 #ifndef QT_NO_MENUBAR
       
   955     if (menubar && menubar->parentWidget() != mw) {
       
   956         menubar->setParent(mw);
       
   957     }
       
   958 #endif
       
   959     bool mwVisible = mw && mw->isVisible();
       
   960     for (int i = 0; i < n; ++i) {
       
   961         QLayoutItem *item = q->itemAt(i);
       
   962         if (QWidget *w = item->widget()) {
       
   963             QWidget *pw = w->parentWidget();
       
   964 #ifdef QT_DEBUG
       
   965             if (pw && pw != mw && layoutDebug()) {
       
   966                 qWarning("QLayout::addChildLayout: widget %s \"%s\" in wrong parent; moved to correct parent",
       
   967                          w->metaObject()->className(), w->objectName().toLocal8Bit().data());
       
   968             }
       
   969 #endif
       
   970             bool needShow = mwVisible && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
       
   971             if (pw != mw)
       
   972                 w->setParent(mw);
       
   973             if (needShow)
       
   974                 QMetaObject::invokeMethod(w, "_q_showIfNotHidden", Qt::QueuedConnection); //show later
       
   975         } else if (QLayout *l = item->layout()) {
       
   976             l->d_func()->reparentChildWidgets(mw);
       
   977         }
       
   978     }
       
   979 }
       
   980 
       
   981 /*!
       
   982     This function is called from \c addWidget() functions in
       
   983     subclasses to add \a w as a child widget.
       
   984 
       
   985     If \a w is already in a layout, this function will give a warning
       
   986     and remove \a w from the layout. This function must therefore be
       
   987     called before adding \a w to the layout's data structure.
       
   988 */
       
   989 void QLayout::addChildWidget(QWidget *w)
       
   990 {
       
   991     QWidget *mw = parentWidget();
       
   992     QWidget *pw = w->parentWidget();
       
   993 
       
   994     //Qt::WA_LaidOut is never reset. It only means that the widget at some point has
       
   995     //been in a layout.
       
   996     if (pw && w->testAttribute(Qt::WA_LaidOut)) {
       
   997         QLayout *l = pw->layout();
       
   998         if (l && removeWidgetRecursively(l, w)) {
       
   999 #ifdef QT_DEBUG
       
  1000             if (layoutDebug())
       
  1001                 qWarning("QLayout::addChildWidget: %s \"%s\" is already in a layout; moved to new layout",
       
  1002                          w->metaObject()->className(), w->objectName().toLocal8Bit().data());
       
  1003 #endif
       
  1004         }
       
  1005     }
       
  1006     if (pw && mw && pw != mw) {
       
  1007 #ifdef QT_DEBUG
       
  1008             if (layoutDebug())
       
  1009                 qWarning("QLayout::addChildWidget: %s \"%s\" in wrong parent; moved to correct parent",
       
  1010                          w->metaObject()->className(), w->objectName().toLocal8Bit().data());
       
  1011 #endif
       
  1012         pw = 0;
       
  1013     }
       
  1014     bool needShow = mw && mw->isVisible() && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
       
  1015     if (!pw && mw)
       
  1016         w->setParent(mw);
       
  1017     w->setAttribute(Qt::WA_LaidOut);
       
  1018     if (needShow)
       
  1019         QMetaObject::invokeMethod(w, "_q_showIfNotHidden", Qt::QueuedConnection); //show later
       
  1020 }
       
  1021 
       
  1022 #ifdef QT3_SUPPORT
       
  1023 /*!
       
  1024   \compat
       
  1025 
       
  1026     Sets this layout's parent widget to a fixed size with width \a w
       
  1027     and height \a h, stopping the user from resizing it, and also
       
  1028     prevents the layout from resizing it, even if the layout's size
       
  1029     hint should change. Does nothing if this is not a top-level
       
  1030     layout (i.e., if parent()->isWidgetType()).
       
  1031 
       
  1032     As a special case, if both \a w and \a h are 0, then the layout's
       
  1033     current sizeHint() is used.
       
  1034 
       
  1035     Use \c setResizeMode(Fixed) to stop the widget from being resized
       
  1036     by the user, while still allowing the layout to resize it when
       
  1037     the sizeHint() changes.
       
  1038 
       
  1039     Use \c setResizeMode(FreeResize) to allow the user to resize the
       
  1040     widget, while preventing the layout from resizing it.
       
  1041 
       
  1042 */
       
  1043 void QLayout::freeze(int w, int h)
       
  1044 {
       
  1045     Q_D(QLayout);
       
  1046     if (!d->topLevel)
       
  1047         return;
       
  1048     if (w <= 0 || h <= 0) {
       
  1049         QSize s = totalSizeHint();
       
  1050         w = s.width();
       
  1051         h = s.height();
       
  1052     }
       
  1053     setSizeConstraint(SetNoConstraint); // layout will not change min/max size
       
  1054     QWidget *parent = parentWidget();
       
  1055     if (parent)
       
  1056         parent->setFixedSize(w, h);
       
  1057 }
       
  1058 
       
  1059 #endif
       
  1060 
       
  1061 
       
  1062 
       
  1063 
       
  1064 
       
  1065 
       
  1066 
       
  1067 /*!
       
  1068     Tells the geometry manager to place the menu bar \a widget at the
       
  1069     top of parentWidget(), outside QWidget::contentsMargins(). All
       
  1070     child widgets are placed below the bottom edge of the menu bar.
       
  1071 */
       
  1072 void QLayout::setMenuBar(QWidget *widget)
       
  1073 {
       
  1074     Q_D(QLayout);
       
  1075 
       
  1076 #ifdef Q_OS_WINCE_WM
       
  1077     if (widget && widget->size().height() > 0)
       
  1078 #else
       
  1079         if (widget)
       
  1080 #endif
       
  1081             addChildWidget(widget);
       
  1082     d->menubar = widget;
       
  1083 }
       
  1084 
       
  1085 /*!
       
  1086     Returns the menu bar set for this layout, or 0 if no menu bar is
       
  1087     set.
       
  1088 */
       
  1089 
       
  1090 QWidget *QLayout::menuBar() const
       
  1091 {
       
  1092     Q_D(const QLayout);
       
  1093     return d->menubar;
       
  1094 }
       
  1095 
       
  1096 
       
  1097 /*!
       
  1098     Returns the minimum size of this layout. This is the smallest
       
  1099     size that the layout can have while still respecting the
       
  1100     specifications.
       
  1101 
       
  1102     The returned value doesn't include the space required by
       
  1103     QWidget::setContentsMargins() or menuBar().
       
  1104 
       
  1105     The default implementation allows unlimited resizing.
       
  1106 */
       
  1107 QSize QLayout::minimumSize() const
       
  1108 {
       
  1109     return QSize(0, 0);
       
  1110 }
       
  1111 
       
  1112 /*!
       
  1113     Returns the maximum size of this layout. This is the largest size
       
  1114     that the layout can have while still respecting the
       
  1115     specifications.
       
  1116 
       
  1117     The returned value doesn't include the space required by
       
  1118     QWidget::setContentsMargins() or menuBar().
       
  1119 
       
  1120     The default implementation allows unlimited resizing.
       
  1121 */
       
  1122 QSize QLayout::maximumSize() const
       
  1123 {
       
  1124     return QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX);
       
  1125 }
       
  1126 
       
  1127 /*!
       
  1128     Returns whether this layout can make use of more space than
       
  1129     sizeHint(). A value of Qt::Vertical or Qt::Horizontal means that
       
  1130     it wants to grow in only one dimension, whereas Qt::Vertical |
       
  1131     Qt::Horizontal means that it wants to grow in both dimensions.
       
  1132 
       
  1133     The default implementation returns Qt::Horizontal | Qt::Vertical.
       
  1134     Subclasses reimplement it to return a meaningful value based on
       
  1135     their child widgets's \l{QSizePolicy}{size policies}.
       
  1136 
       
  1137     \sa sizeHint()
       
  1138 */
       
  1139 Qt::Orientations QLayout::expandingDirections() const
       
  1140 {
       
  1141     return Qt::Horizontal | Qt::Vertical;
       
  1142 }
       
  1143 
       
  1144 void QLayout::activateRecursiveHelper(QLayoutItem *item)
       
  1145 {
       
  1146     item->invalidate();
       
  1147     QLayout *layout = item->layout();
       
  1148     if (layout) {
       
  1149         QLayoutItem *child;
       
  1150         int i=0;
       
  1151         while ((child = layout->itemAt(i++)))
       
  1152             activateRecursiveHelper(child);
       
  1153         layout->d_func()->activated = true;
       
  1154     }
       
  1155 }
       
  1156 
       
  1157 /*!
       
  1158   Updates the layout for parentWidget().
       
  1159 
       
  1160   You should generally not need to call this because it is
       
  1161   automatically called at the most appropriate times.
       
  1162 
       
  1163   \sa activate(), invalidate()
       
  1164 */
       
  1165 
       
  1166 void QLayout::update()
       
  1167 {
       
  1168     QLayout *layout = this;
       
  1169     while (layout && layout->d_func()->activated) {
       
  1170         layout->d_func()->activated = false;
       
  1171         if (layout->d_func()->topLevel) {
       
  1172             Q_ASSERT(layout->parent()->isWidgetType());
       
  1173             QWidget *mw = static_cast<QWidget*>(layout->parent());
       
  1174             QApplication::postEvent(mw, new QEvent(QEvent::LayoutRequest));
       
  1175             break;
       
  1176         }
       
  1177         layout = static_cast<QLayout*>(layout->parent());
       
  1178     }
       
  1179 }
       
  1180 
       
  1181 /*!
       
  1182     Redoes the layout for parentWidget() if necessary.
       
  1183 
       
  1184     You should generally not need to call this because it is
       
  1185     automatically called at the most appropriate times. It returns
       
  1186     true if the layout was redone.
       
  1187 
       
  1188     \sa update(), QWidget::updateGeometry()
       
  1189 */
       
  1190 bool QLayout::activate()
       
  1191 {
       
  1192     Q_D(QLayout);
       
  1193     if (!d->enabled || !parent())
       
  1194         return false;
       
  1195     if (!d->topLevel)
       
  1196         return static_cast<QLayout*>(parent())->activate();
       
  1197     if (d->activated)
       
  1198         return false;
       
  1199     QWidget *mw = static_cast<QWidget*>(parent());
       
  1200     if (mw == 0) {
       
  1201         qWarning("QLayout::activate: %s \"%s\" does not have a main widget",
       
  1202                  QObject::metaObject()->className(), QObject::objectName().toLocal8Bit().data());
       
  1203         return false;
       
  1204     }
       
  1205     activateRecursiveHelper(this);
       
  1206 
       
  1207     QWidgetPrivate *md = mw->d_func();
       
  1208     uint explMin = md->extra ? md->extra->explicitMinSize : 0;
       
  1209     uint explMax = md->extra ? md->extra->explicitMaxSize : 0;
       
  1210 
       
  1211     switch (d->constraint) {
       
  1212     case SetFixedSize:
       
  1213         // will trigger resize
       
  1214         mw->setFixedSize(totalSizeHint());
       
  1215         break;
       
  1216     case SetMinimumSize:
       
  1217         mw->setMinimumSize(totalMinimumSize());
       
  1218         break;
       
  1219     case SetMaximumSize:
       
  1220         mw->setMaximumSize(totalMaximumSize());
       
  1221         break;
       
  1222     case SetMinAndMaxSize:
       
  1223         mw->setMinimumSize(totalMinimumSize());
       
  1224         mw->setMaximumSize(totalMaximumSize());
       
  1225         break;
       
  1226     case SetDefaultConstraint: {
       
  1227         bool widthSet = explMin & Qt::Horizontal;
       
  1228         bool heightSet = explMin & Qt::Vertical;
       
  1229         if (mw->isWindow()) {
       
  1230             QSize ms = totalMinimumSize();
       
  1231             if (widthSet)
       
  1232                 ms.setWidth(mw->minimumSize().width());
       
  1233             if (heightSet)
       
  1234                 ms.setHeight(mw->minimumSize().height());
       
  1235             if ((!heightSet || !widthSet) && hasHeightForWidth()) {
       
  1236                 int h = minimumHeightForWidth(ms.width());
       
  1237                 if (h > ms.height()) {
       
  1238                     if (!heightSet)
       
  1239                         ms.setHeight(0);
       
  1240                     if (!widthSet)
       
  1241                         ms.setWidth(0);
       
  1242                 }
       
  1243             }
       
  1244             mw->setMinimumSize(ms);
       
  1245         } else if (!widthSet || !heightSet) {
       
  1246             QSize ms = mw->minimumSize();
       
  1247             if (!widthSet)
       
  1248                 ms.setWidth(0);
       
  1249             if (!heightSet)
       
  1250                 ms.setHeight(0);
       
  1251             mw->setMinimumSize(ms);
       
  1252         }
       
  1253         break;
       
  1254     }
       
  1255     case SetNoConstraint:
       
  1256         break;
       
  1257     }
       
  1258 
       
  1259     d->doResize(mw->size());
       
  1260 
       
  1261     if (md->extra) {
       
  1262         md->extra->explicitMinSize = explMin;
       
  1263         md->extra->explicitMaxSize = explMax;
       
  1264     }
       
  1265     // ideally only if sizeHint() or sizePolicy() has changed
       
  1266     mw->updateGeometry();
       
  1267     return true;
       
  1268 }
       
  1269 
       
  1270 /*!
       
  1271     \fn QLayoutItem *QLayout::itemAt(int index) const
       
  1272 
       
  1273     Must be implemented in subclasses to return the layout item at \a
       
  1274     index. If there is no such item, the function must return 0.
       
  1275     Items are numbered consecutively from 0. If an item is deleted, other items will be renumbered.
       
  1276 
       
  1277     This function can be used to iterate over a layout. The following
       
  1278     code will draw a rectangle for each layout item in the layout structure of the widget.
       
  1279 
       
  1280     \snippet doc/src/snippets/code/src_gui_kernel_qlayout.cpp 0
       
  1281 
       
  1282     \sa count(), takeAt()
       
  1283 */
       
  1284 
       
  1285 /*!
       
  1286     \fn QLayoutItem *QLayout::takeAt(int index)
       
  1287 
       
  1288     Must be implemented in subclasses to remove the layout item at \a
       
  1289     index from the layout, and return the item. If there is no such
       
  1290     item, the function must do nothing and return 0.  Items are numbered
       
  1291     consecutively from 0. If an item is removed, other items will be
       
  1292     renumbered.
       
  1293 
       
  1294     The following code fragment shows a safe way to remove all items
       
  1295     from a layout:
       
  1296 
       
  1297     \snippet doc/src/snippets/code/src_gui_kernel_qlayout.cpp 1
       
  1298 
       
  1299     \sa itemAt(), count()
       
  1300 */
       
  1301 
       
  1302 /*!
       
  1303     \fn int *QLayout::count() const
       
  1304 
       
  1305     Must be implemented in subclasses to return the number of items
       
  1306     in the layout.
       
  1307 
       
  1308     \sa itemAt()
       
  1309 */
       
  1310 
       
  1311 /*!
       
  1312     Searches for widget \a widget in this layout (not including child
       
  1313     layouts).
       
  1314 
       
  1315     Returns the index of \a widget, or -1 if \a widget is not found.
       
  1316 
       
  1317     The default implementation iterates over all items using itemAt()
       
  1318 */
       
  1319 int QLayout::indexOf(QWidget *widget) const
       
  1320 {
       
  1321     int i = 0;
       
  1322     QLayoutItem *item = itemAt(i);
       
  1323     while (item) {
       
  1324         if (item->widget() == widget)
       
  1325             return i;
       
  1326         ++i;
       
  1327         item = itemAt(i);
       
  1328     }
       
  1329     return -1;
       
  1330 }
       
  1331 
       
  1332 /*!
       
  1333     \enum QLayout::SizeConstraint
       
  1334 
       
  1335     The possible values are:
       
  1336 
       
  1337     \value SetDefaultConstraint The main widget's minimum size is set
       
  1338                     to minimumSize(), unless the widget already has
       
  1339                     a minimum size.
       
  1340 
       
  1341     \value SetFixedSize The main widget's size is set to sizeHint(); it
       
  1342                     cannot be resized at all.
       
  1343     \value SetMinimumSize  The main widget's minimum size is set to
       
  1344                     minimumSize(); it cannot be smaller.
       
  1345 
       
  1346     \value SetMaximumSize  The main widget's maximum size is set to
       
  1347                     maximumSize(); it cannot be larger.
       
  1348 
       
  1349     \value SetMinAndMaxSize  The main widget's minimum size is set to
       
  1350                     minimumSize() and its maximum size is set to
       
  1351                     maximumSize().
       
  1352 
       
  1353     \value SetNoConstraint  The widget is not constrained.
       
  1354 
       
  1355     \omitvalue Auto
       
  1356     \omitvalue FreeResize
       
  1357     \omitvalue Minimum
       
  1358     \omitvalue Fixed
       
  1359 
       
  1360     \sa setSizeConstraint()
       
  1361 */
       
  1362 
       
  1363 /*!
       
  1364     \property QLayout::sizeConstraint
       
  1365     \brief the resize mode of the layout
       
  1366 
       
  1367     The default mode is \l {QLayout::SetDefaultConstraint}
       
  1368     {SetDefaultConstraint}.
       
  1369 */
       
  1370 void QLayout::setSizeConstraint(SizeConstraint constraint)
       
  1371 {
       
  1372     Q_D(QLayout);
       
  1373     if (constraint == d->constraint)
       
  1374         return;
       
  1375 
       
  1376     d->constraint = constraint;
       
  1377     invalidate();
       
  1378 }
       
  1379 
       
  1380 QLayout::SizeConstraint QLayout::sizeConstraint() const
       
  1381 {
       
  1382     Q_D(const QLayout);
       
  1383     return d->constraint;
       
  1384 }
       
  1385 
       
  1386 /*!
       
  1387     Returns the rectangle that should be covered when the geometry of
       
  1388     this layout is set to \a r, provided that this layout supports
       
  1389     setAlignment().
       
  1390 
       
  1391     The result is derived from sizeHint() and expanding(). It is never
       
  1392     larger than \a r.
       
  1393 */
       
  1394 QRect QLayout::alignmentRect(const QRect &r) const
       
  1395 {
       
  1396     QSize s = sizeHint();
       
  1397     Qt::Alignment a = alignment();
       
  1398 
       
  1399     /*
       
  1400       This is a hack to obtain the real maximum size, not
       
  1401       QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX), the value consistently
       
  1402       returned by QLayoutItems that have an alignment.
       
  1403     */
       
  1404     QLayout *that = const_cast<QLayout *>(this);
       
  1405     that->setAlignment(0);
       
  1406     QSize ms = that->maximumSize();
       
  1407     that->setAlignment(a);
       
  1408 
       
  1409     if ((expandingDirections() & Qt::Horizontal) ||
       
  1410          !(a & Qt::AlignHorizontal_Mask)) {
       
  1411         s.setWidth(qMin(r.width(), ms.width()));
       
  1412     }
       
  1413     if ((expandingDirections() & Qt::Vertical) ||
       
  1414          !(a & Qt::AlignVertical_Mask)) {
       
  1415         s.setHeight(qMin(r.height(), ms.height()));
       
  1416     } else if (hasHeightForWidth()) {
       
  1417         int hfw = heightForWidth(s.width());
       
  1418         if (hfw < s.height())
       
  1419             s.setHeight(qMin(hfw, ms.height()));
       
  1420     }
       
  1421 
       
  1422     s = s.boundedTo(r.size());
       
  1423     int x = r.x();
       
  1424     int y = r.y();
       
  1425 
       
  1426     if (a & Qt::AlignBottom)
       
  1427         y += (r.height() - s.height());
       
  1428     else if (!(a & Qt::AlignTop))
       
  1429         y += (r.height() - s.height()) / 2;
       
  1430 
       
  1431     QWidget *parent = parentWidget();
       
  1432     a = QStyle::visualAlignment(parent ? parent->layoutDirection() : QApplication::layoutDirection(), a);
       
  1433     if (a & Qt::AlignRight)
       
  1434         x += (r.width() - s.width());
       
  1435     else if (!(a & Qt::AlignLeft))
       
  1436         x += (r.width() - s.width()) / 2;
       
  1437 
       
  1438     return QRect(x, y, s.width(), s.height());
       
  1439 }
       
  1440 
       
  1441 /*!
       
  1442     Removes the widget \a widget from the layout. After this call, it
       
  1443     is the caller's responsibility to give the widget a reasonable
       
  1444     geometry or to put the widget back into a layout.
       
  1445     
       
  1446     \bold{Note:} The ownership of \a widget remains the same as
       
  1447     when it was added.
       
  1448 
       
  1449     \sa removeItem(), QWidget::setGeometry(), addWidget()
       
  1450 */
       
  1451 void QLayout::removeWidget(QWidget *widget)
       
  1452 {
       
  1453     int i = 0;
       
  1454     QLayoutItem *child;
       
  1455     while ((child = itemAt(i))) {
       
  1456         if (child->widget() == widget) {
       
  1457             delete takeAt(i);
       
  1458             invalidate();
       
  1459         } else {
       
  1460             ++i;
       
  1461         }
       
  1462     }
       
  1463 }
       
  1464 
       
  1465 /*!
       
  1466     Removes the layout item \a item from the layout. It is the
       
  1467     caller's responsibility to delete the item.
       
  1468 
       
  1469     Notice that \a item can be a layout (since QLayout inherits
       
  1470     QLayoutItem).
       
  1471 
       
  1472     \sa removeWidget(), addItem()
       
  1473 */
       
  1474 void QLayout::removeItem(QLayoutItem *item)
       
  1475 {
       
  1476     int i = 0;
       
  1477     QLayoutItem *child;
       
  1478     while ((child = itemAt(i))) {
       
  1479         if (child == item) {
       
  1480             takeAt(i);
       
  1481             invalidate();
       
  1482         } else {
       
  1483             ++i;
       
  1484         }
       
  1485     }
       
  1486 }
       
  1487 
       
  1488 /*!
       
  1489     Enables this layout if \a enable is true, otherwise disables it.
       
  1490 
       
  1491     An enabled layout adjusts dynamically to changes; a disabled
       
  1492     layout acts as if it did not exist.
       
  1493 
       
  1494     By default all layouts are enabled.
       
  1495 
       
  1496     \sa isEnabled()
       
  1497 */
       
  1498 void QLayout::setEnabled(bool enable)
       
  1499 {
       
  1500     Q_D(QLayout);
       
  1501     d->enabled = enable;
       
  1502 }
       
  1503 
       
  1504 /*!
       
  1505     Returns true if the layout is enabled; otherwise returns false.
       
  1506 
       
  1507     \sa setEnabled()
       
  1508 */
       
  1509 bool QLayout::isEnabled() const
       
  1510 {
       
  1511     Q_D(const QLayout);
       
  1512     return d->enabled;
       
  1513 }
       
  1514 
       
  1515 /*!
       
  1516     Returns a size that satisfies all size constraints on \a widget,
       
  1517     including heightForWidth() and that is as close as possible to \a
       
  1518     size.
       
  1519 */
       
  1520 
       
  1521 QSize QLayout::closestAcceptableSize(const QWidget *widget, const QSize &size)
       
  1522 {
       
  1523     QSize result = size.boundedTo(qSmartMaxSize(widget));
       
  1524     result = result.expandedTo(qSmartMinSize(widget));
       
  1525     QLayout *l = widget->layout();
       
  1526     if (l && l->hasHeightForWidth() && result.height() < l->minimumHeightForWidth(result.width()) ) {
       
  1527         QSize current = widget->size();
       
  1528         int currentHfw =  l->minimumHeightForWidth(current.width());
       
  1529         int newHfw = l->minimumHeightForWidth(result.width());
       
  1530         if (current.height() < currentHfw || currentHfw == newHfw) {
       
  1531             //handle the constant hfw case and the vertical-only case, as well as the
       
  1532             // current-size-is-not-correct case
       
  1533             result.setHeight(newHfw);
       
  1534         } else {
       
  1535             // binary search; assume hfw is decreasing ###
       
  1536 
       
  1537             int maxw = qMax(widget->width(),result.width());
       
  1538             int maxh = qMax(widget->height(), result.height());
       
  1539             int minw = qMin(widget->width(),result.width());
       
  1540             int minh = qMin(widget->height(), result.height());
       
  1541 
       
  1542             int minhfw = l->minimumHeightForWidth(minw);
       
  1543             int maxhfw = l->minimumHeightForWidth(maxw);
       
  1544             while (minw < maxw) {
       
  1545                 if (minhfw > maxh) { //assume decreasing
       
  1546                     minw = maxw - (maxw-minw)/2;
       
  1547                     minhfw = l->minimumHeightForWidth(minw);
       
  1548                 } else if (maxhfw < minh ) { //assume decreasing
       
  1549                     maxw = minw + (maxw-minw)/2;
       
  1550                     maxhfw = l->minimumHeightForWidth(maxw);
       
  1551                 } else  {
       
  1552                     break;
       
  1553                 }
       
  1554             }
       
  1555             result = result.expandedTo(QSize(minw, minhfw));
       
  1556         }
       
  1557     }
       
  1558     return result;
       
  1559 }
       
  1560 
       
  1561 /*!
       
  1562     \fn void QLayout::setResizeMode(SizeConstraint constraint)
       
  1563 
       
  1564     Use setSizeConstraint(\a constraint) instead.
       
  1565 */
       
  1566 
       
  1567 /*!
       
  1568     \fn QLayout::SizeConstraint QLayout::resizeMode() const
       
  1569 
       
  1570     Use sizeConstraint() instead.
       
  1571 */
       
  1572 
       
  1573 void QSizePolicy::setControlType(ControlType type)
       
  1574 {
       
  1575     /*
       
  1576         The control type is a flag type, with values 0x1, 0x2, 0x4, 0x8, 0x10,
       
  1577         etc. In memory, we pack it onto the available bits (CTSize) in
       
  1578         setControlType(), and unpack it here.
       
  1579 
       
  1580         Example:
       
  1581 
       
  1582             0x00000001 maps to 0x00000000
       
  1583             0x00000002 maps to 0x00000200
       
  1584             0x00000004 maps to 0x00000400
       
  1585             0x00000008 maps to 0x00000600
       
  1586             etc.
       
  1587     */
       
  1588 
       
  1589     int i = 0;
       
  1590     while (true) {
       
  1591         if (type & (0x1 << i)) {
       
  1592             data = (data & ~CTMask) | (i << CTShift);
       
  1593             return;
       
  1594         }
       
  1595         ++i;
       
  1596     }
       
  1597 }
       
  1598 
       
  1599 QSizePolicy::ControlType QSizePolicy::controlType() const
       
  1600 {
       
  1601     return QSizePolicy::ControlType(0x1 << ((data & CTMask) >> CTShift));
       
  1602 }
       
  1603 
       
  1604 #ifndef QT_NO_DATASTREAM
       
  1605 /*!
       
  1606     \relates QSizePolicy
       
  1607     \since 4.2
       
  1608 
       
  1609     Writes the size \a policy to the data stream \a stream.
       
  1610 
       
  1611     \sa \link datastreamformat.html Format of the QDataStream operators \endlink
       
  1612 */
       
  1613 QDataStream &operator<<(QDataStream &stream, const QSizePolicy &policy)
       
  1614 {
       
  1615     return stream << policy.data;
       
  1616 }
       
  1617 
       
  1618 /*!
       
  1619     \relates QSizePolicy
       
  1620     \since 4.2
       
  1621 
       
  1622     Reads the size \a policy from the data stream \a stream.
       
  1623 
       
  1624     \sa \link datastreamformat.html Format of the QDataStream operators \endlink
       
  1625 */
       
  1626 QDataStream &operator>>(QDataStream &stream, QSizePolicy &policy)
       
  1627 {
       
  1628     return stream >> policy.data;
       
  1629 }
       
  1630 #endif // QT_NO_DATASTREAM
       
  1631 
       
  1632 QT_END_NAMESPACE