src/gui/kernel/qlayout.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the 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.3
       
   500 
       
   501     Extracts the left, top, right, and bottom margins used around the
       
   502     layout, and assigns them to *\a left, *\a top, *\a right, and *\a
       
   503     bottom (unless they are null pointers).
       
   504 
       
   505     By default, QLayout uses the values provided by the style. On
       
   506     most platforms, the margin is 11 pixels in all directions.
       
   507 
       
   508     \sa setContentsMargins(), QStyle::pixelMetric(),
       
   509         {QStyle::}{PM_LayoutLeftMargin},
       
   510         {QStyle::}{PM_LayoutTopMargin},
       
   511         {QStyle::}{PM_LayoutRightMargin},
       
   512         {QStyle::}{PM_LayoutBottomMargin}
       
   513 */
       
   514 void QLayout::getContentsMargins(int *left, int *top, int *right, int *bottom) const
       
   515 {
       
   516     Q_D(const QLayout);
       
   517     d->getMargin(left, d->userLeftMargin, QStyle::PM_LayoutLeftMargin);
       
   518     d->getMargin(top, d->userTopMargin, QStyle::PM_LayoutTopMargin);
       
   519     d->getMargin(right, d->userRightMargin, QStyle::PM_LayoutRightMargin);
       
   520     d->getMargin(bottom, d->userBottomMargin, QStyle::PM_LayoutBottomMargin);
       
   521 }
       
   522 
       
   523 /*!
       
   524     \since 4.3
       
   525 
       
   526     Returns the layout's geometry() rectangle, but taking into account the
       
   527     contents margins.
       
   528 
       
   529     \sa setContentsMargins(), getContentsMargins()
       
   530 */
       
   531 QRect QLayout::contentsRect() const
       
   532 {
       
   533     Q_D(const QLayout);
       
   534     int left, top, right, bottom;
       
   535     getContentsMargins(&left, &top, &right, &bottom);
       
   536     return d->rect.adjusted(+left, +top, -right, -bottom);
       
   537 }
       
   538 
       
   539 #ifdef QT3_SUPPORT
       
   540 bool QLayout::isTopLevel() const
       
   541 {
       
   542     Q_D(const QLayout);
       
   543     return d->topLevel;
       
   544 }
       
   545 #endif
       
   546 
       
   547 /*!
       
   548     Returns the parent widget of this layout, or 0 if this layout is
       
   549     not installed on any widget.
       
   550 
       
   551     If the layout is a sub-layout, this function returns the parent
       
   552     widget of the parent layout.
       
   553 
       
   554     \sa parent()
       
   555 */
       
   556 QWidget *QLayout::parentWidget() const
       
   557 {
       
   558     Q_D(const QLayout);
       
   559     if (!d->topLevel) {
       
   560         if (parent()) {
       
   561             QLayout *parentLayout = qobject_cast<QLayout*>(parent());
       
   562             if (!parentLayout) {
       
   563                 qWarning("QLayout::parentWidget: A layout can only have another layout as a parent.");
       
   564                 return 0;
       
   565             }
       
   566             return parentLayout->parentWidget();
       
   567         } else {
       
   568             return 0;
       
   569         }
       
   570     } else {
       
   571         Q_ASSERT(parent() && parent()->isWidgetType());
       
   572         return static_cast<QWidget *>(parent());
       
   573     }
       
   574 }
       
   575 
       
   576 /*!
       
   577     \reimp
       
   578 */
       
   579 bool QLayout::isEmpty() const
       
   580 {
       
   581     int i = 0;
       
   582     QLayoutItem *item = itemAt(i);
       
   583     while (item) {
       
   584         if (!item->isEmpty())
       
   585             return false;
       
   586         ++i;
       
   587         item = itemAt(i);
       
   588     }
       
   589     return true;
       
   590 }
       
   591 
       
   592 /*!
       
   593     \reimp
       
   594 */
       
   595 void QLayout::setGeometry(const QRect &r)
       
   596 {
       
   597     Q_D(QLayout);
       
   598     d->rect = r;
       
   599 }
       
   600 
       
   601 /*!
       
   602     \reimp
       
   603 */
       
   604 QRect QLayout::geometry() const
       
   605 {
       
   606     Q_D(const QLayout);
       
   607     return d->rect;
       
   608 }
       
   609 
       
   610 /*!
       
   611     \reimp
       
   612 */
       
   613 void QLayout::invalidate()
       
   614 {
       
   615     Q_D(QLayout);
       
   616     d->rect = QRect();
       
   617     update();
       
   618 }
       
   619 
       
   620 static bool removeWidgetRecursively(QLayoutItem *li, QWidget *w)
       
   621 {
       
   622     QLayout *lay = li->layout();
       
   623     if (!lay)
       
   624         return false;
       
   625     int i = 0;
       
   626     QLayoutItem *child;
       
   627     while ((child = lay->itemAt(i))) {
       
   628         if (child->widget() == w) {
       
   629             delete lay->takeAt(i);
       
   630             lay->invalidate();
       
   631             return true;
       
   632         } else if (removeWidgetRecursively(child, w)) {
       
   633             return true;
       
   634         } else {
       
   635             ++i;
       
   636         }
       
   637     }
       
   638     return false;
       
   639 }
       
   640 
       
   641 
       
   642 void QLayoutPrivate::doResize(const QSize &r)
       
   643 {
       
   644     Q_Q(QLayout);
       
   645     int mbh = menuBarHeightForWidth(menubar, r.width());
       
   646     QWidget *mw = q->parentWidget();
       
   647     QRect rect = mw->testAttribute(Qt::WA_LayoutOnEntireRect) ? mw->rect() : mw->contentsRect();
       
   648     rect.setTop(rect.top() + mbh);
       
   649     q->setGeometry(rect);
       
   650 #ifndef QT_NO_MENUBAR
       
   651     if (menubar)
       
   652         menubar->setGeometry(0,0,r.width(), mbh);
       
   653 #endif
       
   654 }
       
   655 
       
   656 
       
   657 /*!
       
   658     \internal
       
   659     Performs child widget layout when the parent widget is
       
   660     resized.  Also handles removal of widgets. \a e is the
       
   661     event
       
   662 */
       
   663 void QLayout::widgetEvent(QEvent *e)
       
   664 {
       
   665     Q_D(QLayout);
       
   666     if (!d->enabled)
       
   667         return;
       
   668 
       
   669     switch (e->type()) {
       
   670     case QEvent::Resize:
       
   671         if (d->activated) {
       
   672             QResizeEvent *r = (QResizeEvent *)e;
       
   673             d->doResize(r->size());
       
   674         } else {
       
   675             activate();
       
   676         }
       
   677         break;
       
   678     case QEvent::ChildRemoved:
       
   679         {
       
   680             QChildEvent *c = (QChildEvent *)e;
       
   681             if (c->child()->isWidgetType()) {
       
   682                 QWidget *w = (QWidget *)c->child();
       
   683 #ifndef QT_NO_MENUBAR
       
   684                 if (w == d->menubar)
       
   685                     d->menubar = 0;
       
   686 #endif
       
   687                 removeWidgetRecursively(this, w);
       
   688             }
       
   689         }
       
   690         break;
       
   691 #ifdef QT3_SUPPORT
       
   692     case QEvent::ChildInserted:
       
   693         if (d->topLevel && d->autoNewChild) {
       
   694             QChildEvent *c = (QChildEvent *)e;
       
   695             if (c->child()->isWidgetType()) {
       
   696                 QWidget *w = (QWidget *)c->child();
       
   697                 if (!w->isWindow()) {
       
   698 #if !defined(QT_NO_MENUBAR) && !defined(QT_NO_TOOLBAR)
       
   699                     if (qobject_cast<QMenuBar*>(w) && !qobject_cast<QToolBar*>(w->parentWidget())) {
       
   700                         d->menubar = (QMenuBar *)w;
       
   701                         invalidate();
       
   702                     } else
       
   703 #endif
       
   704 #ifndef QT_NO_SIZEGRIP
       
   705                     if (qobject_cast<QSizeGrip*>(w) ) {
       
   706                         //SizeGrip is handled by the dialog itself.
       
   707                     } else
       
   708 #endif
       
   709                         addItem(QLayoutPrivate::createWidgetItem(this, w));
       
   710                 }
       
   711             }
       
   712         }
       
   713         break;
       
   714     case QEvent::LayoutHint:
       
   715         d->activated = false;
       
   716         // fall through
       
   717 #endif
       
   718     case QEvent::LayoutRequest:
       
   719         if (static_cast<QWidget *>(parent())->isVisible())
       
   720             activate();
       
   721         break;
       
   722     default:
       
   723         break;
       
   724     }
       
   725 }
       
   726 
       
   727 /*!
       
   728     \reimp
       
   729 */
       
   730 void QLayout::childEvent(QChildEvent *e)
       
   731 {
       
   732     Q_D(QLayout);
       
   733     if (!d->enabled)
       
   734         return;
       
   735 
       
   736     if (e->type() == QEvent::ChildRemoved) {
       
   737         QChildEvent *c = (QChildEvent*)e;
       
   738         int i = 0;
       
   739 
       
   740         QLayoutItem *item;
       
   741         while ((item = itemAt(i))) {
       
   742             if (item == static_cast<QLayout*>(c->child())) {
       
   743                 takeAt(i);
       
   744                 invalidate();
       
   745                 break;
       
   746             } else {
       
   747                 ++i;
       
   748             }
       
   749         }
       
   750     }
       
   751 }
       
   752 
       
   753 /*!
       
   754   \internal
       
   755   Also takes contentsMargins and menu bar into account.
       
   756 */
       
   757 int QLayout::totalHeightForWidth(int w) const
       
   758 {
       
   759     Q_D(const QLayout);
       
   760     int side=0, top=0;
       
   761     if (d->topLevel) {
       
   762         QWidget *parent = parentWidget();
       
   763         parent->ensurePolished();
       
   764         QWidgetPrivate *wd = parent->d_func();
       
   765         side += wd->leftmargin + wd->rightmargin;
       
   766         top += wd->topmargin + wd->bottommargin;
       
   767     }
       
   768     int h = heightForWidth(w - side) + top;
       
   769 #ifndef QT_NO_MENUBAR
       
   770     h += menuBarHeightForWidth(d->menubar, w);
       
   771 #endif
       
   772     return h;
       
   773 }
       
   774 
       
   775 /*!
       
   776   \internal
       
   777   Also takes contentsMargins and menu bar into account.
       
   778 */
       
   779 QSize QLayout::totalMinimumSize() const
       
   780 {
       
   781     Q_D(const QLayout);
       
   782     int side=0, top=0;
       
   783     if (d->topLevel) {
       
   784         QWidget *pw = parentWidget();
       
   785         pw->ensurePolished();
       
   786         QWidgetPrivate *wd = pw->d_func();
       
   787         side += wd->leftmargin + wd->rightmargin;
       
   788         top += wd->topmargin + wd->bottommargin;
       
   789     }
       
   790 
       
   791     QSize s = minimumSize();
       
   792 #ifndef QT_NO_MENUBAR
       
   793     top += menuBarHeightForWidth(d->menubar, s.width() + side);
       
   794 #endif
       
   795     return s + QSize(side, top);
       
   796 }
       
   797 
       
   798 /*!
       
   799   \internal
       
   800   Also takes contentsMargins and menu bar into account.
       
   801 */
       
   802 QSize QLayout::totalSizeHint() const
       
   803 {
       
   804     Q_D(const QLayout);
       
   805     int side=0, top=0;
       
   806     if (d->topLevel) {
       
   807         QWidget *pw = parentWidget();
       
   808         pw->ensurePolished();
       
   809         QWidgetPrivate *wd = pw->d_func();
       
   810         side += wd->leftmargin + wd->rightmargin;
       
   811         top += wd->topmargin + wd->bottommargin;
       
   812     }
       
   813 
       
   814     QSize s = sizeHint();
       
   815     if (hasHeightForWidth())
       
   816         s.setHeight(heightForWidth(s.width() + side));
       
   817 #ifndef QT_NO_MENUBAR
       
   818     top += menuBarHeightForWidth(d->menubar, s.width());
       
   819 #endif
       
   820     return s + QSize(side, top);
       
   821 }
       
   822 
       
   823 /*!
       
   824   \internal
       
   825   Also takes contentsMargins and menu bar into account.
       
   826 */
       
   827 QSize QLayout::totalMaximumSize() const
       
   828 {
       
   829     Q_D(const QLayout);
       
   830     int side=0, top=0;
       
   831     if (d->topLevel) {
       
   832         QWidget *pw = parentWidget();
       
   833         pw->ensurePolished();
       
   834         QWidgetPrivate *wd = pw->d_func();
       
   835         side += wd->leftmargin + wd->rightmargin;
       
   836         top += wd->topmargin + wd->bottommargin;
       
   837     }
       
   838 
       
   839     QSize s = maximumSize();
       
   840 #ifndef QT_NO_MENUBAR
       
   841     top += menuBarHeightForWidth(d->menubar, s.width());
       
   842 #endif
       
   843 
       
   844     if (d->topLevel)
       
   845         s = QSize(qMin(s.width() + side, QLAYOUTSIZE_MAX),
       
   846                    qMin(s.height() + top, QLAYOUTSIZE_MAX));
       
   847     return s;
       
   848 }
       
   849 
       
   850 /*!
       
   851   \internal
       
   852   Destroys the layout, deleting all child layouts.
       
   853   Geometry management stops when a top-level layout is deleted.
       
   854 
       
   855   The layout classes will probably be fatally confused if you delete
       
   856   a sublayout.
       
   857 */
       
   858 QLayout::~QLayout()
       
   859 {
       
   860     Q_D(QLayout);
       
   861     /*
       
   862       This function may be called during the QObject destructor,
       
   863       when the parent no longer is a QWidget.
       
   864     */
       
   865     if (d->topLevel && parent() && parent()->isWidgetType() &&
       
   866          ((QWidget*)parent())->layout() == this)
       
   867         ((QWidget*)parent())->d_func()->layout = 0;
       
   868 }
       
   869 
       
   870 #ifdef QT3_SUPPORT
       
   871 /*!
       
   872     Removes and deletes all items in this layout.
       
   873 */
       
   874 void QLayout::deleteAllItems()
       
   875 {
       
   876     QLayoutItem *l;
       
   877     while ((l = takeAt(0)))
       
   878         delete l;
       
   879 }
       
   880 #endif
       
   881 
       
   882 /*!
       
   883     This function is called from \c addLayout() or \c insertLayout() functions in
       
   884     subclasses to add layout \a l as a sub-layout.
       
   885 
       
   886     The only scenario in which you need to call it directly is if you
       
   887     implement a custom layout that supports nested layouts.
       
   888 
       
   889     \sa QBoxLayout::addLayout(), QBoxLayout::insertLayout(), QGridLayout::addLayout()
       
   890 */
       
   891 void QLayout::addChildLayout(QLayout *l)
       
   892 {
       
   893     if (l->parent()) {
       
   894         qWarning("QLayout::addChildLayout: layout \"%s\" already has a parent",
       
   895                  l->objectName().toLocal8Bit().data());
       
   896         return;
       
   897     }
       
   898     l->setParent(this);
       
   899 
       
   900     if (QWidget *mw = parentWidget()) {
       
   901         l->d_func()->reparentChildWidgets(mw);
       
   902     }
       
   903 
       
   904 }
       
   905 
       
   906 #ifdef QT_DEBUG
       
   907 static bool layoutDebug()
       
   908 {
       
   909     static int checked_env = -1;
       
   910     if(checked_env == -1)
       
   911         checked_env = !!qgetenv("QT_LAYOUT_DEBUG").toInt();
       
   912 
       
   913     return checked_env;
       
   914 }
       
   915 #endif
       
   916 
       
   917 void QLayoutPrivate::reparentChildWidgets(QWidget *mw)
       
   918 {
       
   919     Q_Q(QLayout);
       
   920     int n =  q->count();
       
   921 
       
   922 #ifndef QT_NO_MENUBAR
       
   923     if (menubar && menubar->parentWidget() != mw) {
       
   924         menubar->setParent(mw);
       
   925     }
       
   926 #endif
       
   927     bool mwVisible = mw && mw->isVisible();
       
   928     for (int i = 0; i < n; ++i) {
       
   929         QLayoutItem *item = q->itemAt(i);
       
   930         if (QWidget *w = item->widget()) {
       
   931             QWidget *pw = w->parentWidget();
       
   932 #ifdef QT_DEBUG
       
   933             if (pw && pw != mw && layoutDebug()) {
       
   934                 qWarning("QLayout::addChildLayout: widget %s \"%s\" in wrong parent; moved to correct parent",
       
   935                          w->metaObject()->className(), w->objectName().toLocal8Bit().data());
       
   936             }
       
   937 #endif
       
   938             bool needShow = mwVisible && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
       
   939             if (pw != mw)
       
   940                 w->setParent(mw);
       
   941             if (needShow)
       
   942                 QMetaObject::invokeMethod(w, "_q_showIfNotHidden", Qt::QueuedConnection); //show later
       
   943         } else if (QLayout *l = item->layout()) {
       
   944             l->d_func()->reparentChildWidgets(mw);
       
   945         }
       
   946     }
       
   947 }
       
   948 
       
   949 /*!
       
   950     This function is called from \c addWidget() functions in
       
   951     subclasses to add \a w as a child widget.
       
   952 
       
   953     If \a w is already in a layout, this function will give a warning
       
   954     and remove \a w from the layout. This function must therefore be
       
   955     called before adding \a w to the layout's data structure.
       
   956 */
       
   957 void QLayout::addChildWidget(QWidget *w)
       
   958 {
       
   959     QWidget *mw = parentWidget();
       
   960     QWidget *pw = w->parentWidget();
       
   961 
       
   962     //Qt::WA_LaidOut is never reset. It only means that the widget at some point has
       
   963     //been in a layout.
       
   964     if (pw && w->testAttribute(Qt::WA_LaidOut)) {
       
   965         QLayout *l = pw->layout();
       
   966         if (l && removeWidgetRecursively(l, w)) {
       
   967 #ifdef QT_DEBUG
       
   968             if (layoutDebug())
       
   969                 qWarning("QLayout::addChildWidget: %s \"%s\" is already in a layout; moved to new layout",
       
   970                          w->metaObject()->className(), w->objectName().toLocal8Bit().data());
       
   971 #endif
       
   972         }
       
   973     }
       
   974     if (pw && mw && pw != mw) {
       
   975 #ifdef QT_DEBUG
       
   976             if (layoutDebug())
       
   977                 qWarning("QLayout::addChildWidget: %s \"%s\" in wrong parent; moved to correct parent",
       
   978                          w->metaObject()->className(), w->objectName().toLocal8Bit().data());
       
   979 #endif
       
   980         pw = 0;
       
   981     }
       
   982     bool needShow = mw && mw->isVisible() && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
       
   983     if (!pw && mw)
       
   984         w->setParent(mw);
       
   985     w->setAttribute(Qt::WA_LaidOut);
       
   986     if (needShow)
       
   987         QMetaObject::invokeMethod(w, "_q_showIfNotHidden", Qt::QueuedConnection); //show later
       
   988 }
       
   989 
       
   990 #ifdef QT3_SUPPORT
       
   991 /*!
       
   992   \compat
       
   993 
       
   994     Sets this layout's parent widget to a fixed size with width \a w
       
   995     and height \a h, stopping the user from resizing it, and also
       
   996     prevents the layout from resizing it, even if the layout's size
       
   997     hint should change. Does nothing if this is not a top-level
       
   998     layout (i.e., if parent()->isWidgetType()).
       
   999 
       
  1000     As a special case, if both \a w and \a h are 0, then the layout's
       
  1001     current sizeHint() is used.
       
  1002 
       
  1003     Use \c setResizeMode(Fixed) to stop the widget from being resized
       
  1004     by the user, while still allowing the layout to resize it when
       
  1005     the sizeHint() changes.
       
  1006 
       
  1007     Use \c setResizeMode(FreeResize) to allow the user to resize the
       
  1008     widget, while preventing the layout from resizing it.
       
  1009 
       
  1010 */
       
  1011 void QLayout::freeze(int w, int h)
       
  1012 {
       
  1013     Q_D(QLayout);
       
  1014     if (!d->topLevel)
       
  1015         return;
       
  1016     if (w <= 0 || h <= 0) {
       
  1017         QSize s = totalSizeHint();
       
  1018         w = s.width();
       
  1019         h = s.height();
       
  1020     }
       
  1021     setSizeConstraint(SetNoConstraint); // layout will not change min/max size
       
  1022     QWidget *parent = parentWidget();
       
  1023     if (parent)
       
  1024         parent->setFixedSize(w, h);
       
  1025 }
       
  1026 
       
  1027 #endif
       
  1028 
       
  1029 
       
  1030 
       
  1031 
       
  1032 
       
  1033 
       
  1034 
       
  1035 /*!
       
  1036     Tells the geometry manager to place the menu bar \a widget at the
       
  1037     top of parentWidget(), outside QWidget::contentsMargins(). All
       
  1038     child widgets are placed below the bottom edge of the menu bar.
       
  1039 */
       
  1040 void QLayout::setMenuBar(QWidget *widget)
       
  1041 {
       
  1042     Q_D(QLayout);
       
  1043 
       
  1044 #ifdef Q_OS_WINCE_WM
       
  1045     if (widget && widget->size().height() > 0)
       
  1046 #else
       
  1047         if (widget)
       
  1048 #endif
       
  1049             addChildWidget(widget);
       
  1050     d->menubar = widget;
       
  1051 }
       
  1052 
       
  1053 /*!
       
  1054     Returns the menu bar set for this layout, or 0 if no menu bar is
       
  1055     set.
       
  1056 */
       
  1057 
       
  1058 QWidget *QLayout::menuBar() const
       
  1059 {
       
  1060     Q_D(const QLayout);
       
  1061     return d->menubar;
       
  1062 }
       
  1063 
       
  1064 
       
  1065 /*!
       
  1066     Returns the minimum size of this layout. This is the smallest
       
  1067     size that the layout can have while still respecting the
       
  1068     specifications.
       
  1069 
       
  1070     The returned value doesn't include the space required by
       
  1071     QWidget::setContentsMargins() or menuBar().
       
  1072 
       
  1073     The default implementation allows unlimited resizing.
       
  1074 */
       
  1075 QSize QLayout::minimumSize() const
       
  1076 {
       
  1077     return QSize(0, 0);
       
  1078 }
       
  1079 
       
  1080 /*!
       
  1081     Returns the maximum size of this layout. This is the largest size
       
  1082     that the layout can have while still respecting the
       
  1083     specifications.
       
  1084 
       
  1085     The returned value doesn't include the space required by
       
  1086     QWidget::setContentsMargins() or menuBar().
       
  1087 
       
  1088     The default implementation allows unlimited resizing.
       
  1089 */
       
  1090 QSize QLayout::maximumSize() const
       
  1091 {
       
  1092     return QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX);
       
  1093 }
       
  1094 
       
  1095 /*!
       
  1096     Returns whether this layout can make use of more space than
       
  1097     sizeHint(). A value of Qt::Vertical or Qt::Horizontal means that
       
  1098     it wants to grow in only one dimension, whereas Qt::Vertical |
       
  1099     Qt::Horizontal means that it wants to grow in both dimensions.
       
  1100 
       
  1101     The default implementation returns Qt::Horizontal | Qt::Vertical.
       
  1102     Subclasses reimplement it to return a meaningful value based on
       
  1103     their child widgets's \l{QSizePolicy}{size policies}.
       
  1104 
       
  1105     \sa sizeHint()
       
  1106 */
       
  1107 Qt::Orientations QLayout::expandingDirections() const
       
  1108 {
       
  1109     return Qt::Horizontal | Qt::Vertical;
       
  1110 }
       
  1111 
       
  1112 void QLayout::activateRecursiveHelper(QLayoutItem *item)
       
  1113 {
       
  1114     item->invalidate();
       
  1115     QLayout *layout = item->layout();
       
  1116     if (layout) {
       
  1117         QLayoutItem *child;
       
  1118         int i=0;
       
  1119         while ((child = layout->itemAt(i++)))
       
  1120             activateRecursiveHelper(child);
       
  1121         layout->d_func()->activated = true;
       
  1122     }
       
  1123 }
       
  1124 
       
  1125 /*!
       
  1126   Updates the layout for parentWidget().
       
  1127 
       
  1128   You should generally not need to call this because it is
       
  1129   automatically called at the most appropriate times.
       
  1130 
       
  1131   \sa activate(), invalidate()
       
  1132 */
       
  1133 
       
  1134 void QLayout::update()
       
  1135 {
       
  1136     QLayout *layout = this;
       
  1137     while (layout && layout->d_func()->activated) {
       
  1138         layout->d_func()->activated = false;
       
  1139         if (layout->d_func()->topLevel) {
       
  1140             Q_ASSERT(layout->parent()->isWidgetType());
       
  1141             QWidget *mw = static_cast<QWidget*>(layout->parent());
       
  1142             QApplication::postEvent(mw, new QEvent(QEvent::LayoutRequest));
       
  1143             break;
       
  1144         }
       
  1145         layout = static_cast<QLayout*>(layout->parent());
       
  1146     }
       
  1147 }
       
  1148 
       
  1149 /*!
       
  1150     Redoes the layout for parentWidget() if necessary.
       
  1151 
       
  1152     You should generally not need to call this because it is
       
  1153     automatically called at the most appropriate times. It returns
       
  1154     true if the layout was redone.
       
  1155 
       
  1156     \sa update(), QWidget::updateGeometry()
       
  1157 */
       
  1158 bool QLayout::activate()
       
  1159 {
       
  1160     Q_D(QLayout);
       
  1161     if (!d->enabled || !parent())
       
  1162         return false;
       
  1163     if (!d->topLevel)
       
  1164         return static_cast<QLayout*>(parent())->activate();
       
  1165     if (d->activated)
       
  1166         return false;
       
  1167     QWidget *mw = static_cast<QWidget*>(parent());
       
  1168     if (mw == 0) {
       
  1169         qWarning("QLayout::activate: %s \"%s\" does not have a main widget",
       
  1170                  QObject::metaObject()->className(), QObject::objectName().toLocal8Bit().data());
       
  1171         return false;
       
  1172     }
       
  1173     activateRecursiveHelper(this);
       
  1174 
       
  1175     QWidgetPrivate *md = mw->d_func();
       
  1176     uint explMin = md->extra ? md->extra->explicitMinSize : 0;
       
  1177     uint explMax = md->extra ? md->extra->explicitMaxSize : 0;
       
  1178 
       
  1179     switch (d->constraint) {
       
  1180     case SetFixedSize:
       
  1181         // will trigger resize
       
  1182         mw->setFixedSize(totalSizeHint());
       
  1183         break;
       
  1184     case SetMinimumSize:
       
  1185         mw->setMinimumSize(totalMinimumSize());
       
  1186         break;
       
  1187     case SetMaximumSize:
       
  1188         mw->setMaximumSize(totalMaximumSize());
       
  1189         break;
       
  1190     case SetMinAndMaxSize:
       
  1191         mw->setMinimumSize(totalMinimumSize());
       
  1192         mw->setMaximumSize(totalMaximumSize());
       
  1193         break;
       
  1194     case SetDefaultConstraint: {
       
  1195         bool widthSet = explMin & Qt::Horizontal;
       
  1196         bool heightSet = explMin & Qt::Vertical;
       
  1197         if (mw->isWindow()) {
       
  1198             QSize ms = totalMinimumSize();
       
  1199             if (widthSet)
       
  1200                 ms.setWidth(mw->minimumSize().width());
       
  1201             if (heightSet)
       
  1202                 ms.setHeight(mw->minimumSize().height());
       
  1203             if ((!heightSet || !widthSet) && hasHeightForWidth()) {
       
  1204                 int h = minimumHeightForWidth(ms.width());
       
  1205                 if (h > ms.height()) {
       
  1206                     if (!heightSet)
       
  1207                         ms.setHeight(0);
       
  1208                     if (!widthSet)
       
  1209                         ms.setWidth(0);
       
  1210                 }
       
  1211             }
       
  1212             mw->setMinimumSize(ms);
       
  1213         } else if (!widthSet || !heightSet) {
       
  1214             QSize ms = mw->minimumSize();
       
  1215             if (!widthSet)
       
  1216                 ms.setWidth(0);
       
  1217             if (!heightSet)
       
  1218                 ms.setHeight(0);
       
  1219             mw->setMinimumSize(ms);
       
  1220         }
       
  1221         break;
       
  1222     }
       
  1223     case SetNoConstraint:
       
  1224         break;
       
  1225     }
       
  1226 
       
  1227     d->doResize(mw->size());
       
  1228 
       
  1229     if (md->extra) {
       
  1230         md->extra->explicitMinSize = explMin;
       
  1231         md->extra->explicitMaxSize = explMax;
       
  1232     }
       
  1233     // ideally only if sizeHint() or sizePolicy() has changed
       
  1234     mw->updateGeometry();
       
  1235     return true;
       
  1236 }
       
  1237 
       
  1238 /*!
       
  1239     \fn QLayoutItem *QLayout::itemAt(int index) const
       
  1240 
       
  1241     Must be implemented in subclasses to return the layout item at \a
       
  1242     index. If there is no such item, the function must return 0.
       
  1243     Items are numbered consecutively from 0. If an item is deleted, other items will be renumbered.
       
  1244 
       
  1245     This function can be used to iterate over a layout. The following
       
  1246     code will draw a rectangle for each layout item in the layout structure of the widget.
       
  1247 
       
  1248     \snippet doc/src/snippets/code/src_gui_kernel_qlayout.cpp 0
       
  1249 
       
  1250     \sa count(), takeAt()
       
  1251 */
       
  1252 
       
  1253 /*!
       
  1254     \fn QLayoutItem *QLayout::takeAt(int index)
       
  1255 
       
  1256     Must be implemented in subclasses to remove the layout item at \a
       
  1257     index from the layout, and return the item. If there is no such
       
  1258     item, the function must do nothing and return 0.  Items are numbered
       
  1259     consecutively from 0. If an item is removed, other items will be
       
  1260     renumbered.
       
  1261 
       
  1262     The following code fragment shows a safe way to remove all items
       
  1263     from a layout:
       
  1264 
       
  1265     \snippet doc/src/snippets/code/src_gui_kernel_qlayout.cpp 1
       
  1266 
       
  1267     \sa itemAt(), count()
       
  1268 */
       
  1269 
       
  1270 /*!
       
  1271     \fn int *QLayout::count() const
       
  1272 
       
  1273     Must be implemented in subclasses to return the number of items
       
  1274     in the layout.
       
  1275 
       
  1276     \sa itemAt()
       
  1277 */
       
  1278 
       
  1279 /*!
       
  1280     Searches for widget \a widget in this layout (not including child
       
  1281     layouts).
       
  1282 
       
  1283     Returns the index of \a widget, or -1 if \a widget is not found.
       
  1284 
       
  1285     The default implementation iterates over all items using itemAt()
       
  1286 */
       
  1287 int QLayout::indexOf(QWidget *widget) const
       
  1288 {
       
  1289     int i = 0;
       
  1290     QLayoutItem *item = itemAt(i);
       
  1291     while (item) {
       
  1292         if (item->widget() == widget)
       
  1293             return i;
       
  1294         ++i;
       
  1295         item = itemAt(i);
       
  1296     }
       
  1297     return -1;
       
  1298 }
       
  1299 
       
  1300 /*!
       
  1301     \enum QLayout::SizeConstraint
       
  1302 
       
  1303     The possible values are:
       
  1304 
       
  1305     \value SetDefaultConstraint The main widget's minimum size is set
       
  1306                     to minimumSize(), unless the widget already has
       
  1307                     a minimum size.
       
  1308 
       
  1309     \value SetFixedSize The main widget's size is set to sizeHint(); it
       
  1310                     cannot be resized at all.
       
  1311     \value SetMinimumSize  The main widget's minimum size is set to
       
  1312                     minimumSize(); it cannot be smaller.
       
  1313 
       
  1314     \value SetMaximumSize  The main widget's maximum size is set to
       
  1315                     maximumSize(); it cannot be larger.
       
  1316 
       
  1317     \value SetMinAndMaxSize  The main widget's minimum size is set to
       
  1318                     minimumSize() and its maximum size is set to
       
  1319                     maximumSize().
       
  1320 
       
  1321     \value SetNoConstraint  The widget is not constrained.
       
  1322 
       
  1323     \omitvalue Auto
       
  1324     \omitvalue FreeResize
       
  1325     \omitvalue Minimum
       
  1326     \omitvalue Fixed
       
  1327 
       
  1328     \sa setSizeConstraint()
       
  1329 */
       
  1330 
       
  1331 /*!
       
  1332     \property QLayout::sizeConstraint
       
  1333     \brief the resize mode of the layout
       
  1334 
       
  1335     The default mode is \l {QLayout::SetDefaultConstraint}
       
  1336     {SetDefaultConstraint}.
       
  1337 */
       
  1338 void QLayout::setSizeConstraint(SizeConstraint constraint)
       
  1339 {
       
  1340     Q_D(QLayout);
       
  1341     if (constraint == d->constraint)
       
  1342         return;
       
  1343 
       
  1344     d->constraint = constraint;
       
  1345     invalidate();
       
  1346 }
       
  1347 
       
  1348 QLayout::SizeConstraint QLayout::sizeConstraint() const
       
  1349 {
       
  1350     Q_D(const QLayout);
       
  1351     return d->constraint;
       
  1352 }
       
  1353 
       
  1354 /*!
       
  1355     Returns the rectangle that should be covered when the geometry of
       
  1356     this layout is set to \a r, provided that this layout supports
       
  1357     setAlignment().
       
  1358 
       
  1359     The result is derived from sizeHint() and expanding(). It is never
       
  1360     larger than \a r.
       
  1361 */
       
  1362 QRect QLayout::alignmentRect(const QRect &r) const
       
  1363 {
       
  1364     QSize s = sizeHint();
       
  1365     Qt::Alignment a = alignment();
       
  1366 
       
  1367     /*
       
  1368       This is a hack to obtain the real maximum size, not
       
  1369       QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX), the value consistently
       
  1370       returned by QLayoutItems that have an alignment.
       
  1371     */
       
  1372     QLayout *that = const_cast<QLayout *>(this);
       
  1373     that->setAlignment(0);
       
  1374     QSize ms = that->maximumSize();
       
  1375     that->setAlignment(a);
       
  1376 
       
  1377     if ((expandingDirections() & Qt::Horizontal) ||
       
  1378          !(a & Qt::AlignHorizontal_Mask)) {
       
  1379         s.setWidth(qMin(r.width(), ms.width()));
       
  1380     }
       
  1381     if ((expandingDirections() & Qt::Vertical) ||
       
  1382          !(a & Qt::AlignVertical_Mask)) {
       
  1383         s.setHeight(qMin(r.height(), ms.height()));
       
  1384     } else if (hasHeightForWidth()) {
       
  1385         int hfw = heightForWidth(s.width());
       
  1386         if (hfw < s.height())
       
  1387             s.setHeight(qMin(hfw, ms.height()));
       
  1388     }
       
  1389 
       
  1390     s = s.boundedTo(r.size());
       
  1391     int x = r.x();
       
  1392     int y = r.y();
       
  1393 
       
  1394     if (a & Qt::AlignBottom)
       
  1395         y += (r.height() - s.height());
       
  1396     else if (!(a & Qt::AlignTop))
       
  1397         y += (r.height() - s.height()) / 2;
       
  1398 
       
  1399     QWidget *parent = parentWidget();
       
  1400     a = QStyle::visualAlignment(parent ? parent->layoutDirection() : QApplication::layoutDirection(), a);
       
  1401     if (a & Qt::AlignRight)
       
  1402         x += (r.width() - s.width());
       
  1403     else if (!(a & Qt::AlignLeft))
       
  1404         x += (r.width() - s.width()) / 2;
       
  1405 
       
  1406     return QRect(x, y, s.width(), s.height());
       
  1407 }
       
  1408 
       
  1409 /*!
       
  1410     Removes the widget \a widget from the layout. After this call, it
       
  1411     is the caller's responsibility to give the widget a reasonable
       
  1412     geometry or to put the widget back into a layout.
       
  1413     
       
  1414     \bold{Note:} The ownership of \a widget remains the same as
       
  1415     when it was added.
       
  1416 
       
  1417     \sa removeItem(), QWidget::setGeometry(), addWidget()
       
  1418 */
       
  1419 void QLayout::removeWidget(QWidget *widget)
       
  1420 {
       
  1421     int i = 0;
       
  1422     QLayoutItem *child;
       
  1423     while ((child = itemAt(i))) {
       
  1424         if (child->widget() == widget) {
       
  1425             delete takeAt(i);
       
  1426             invalidate();
       
  1427         } else {
       
  1428             ++i;
       
  1429         }
       
  1430     }
       
  1431 }
       
  1432 
       
  1433 /*!
       
  1434     Removes the layout item \a item from the layout. It is the
       
  1435     caller's responsibility to delete the item.
       
  1436 
       
  1437     Notice that \a item can be a layout (since QLayout inherits
       
  1438     QLayoutItem).
       
  1439 
       
  1440     \sa removeWidget(), addItem()
       
  1441 */
       
  1442 void QLayout::removeItem(QLayoutItem *item)
       
  1443 {
       
  1444     int i = 0;
       
  1445     QLayoutItem *child;
       
  1446     while ((child = itemAt(i))) {
       
  1447         if (child == item) {
       
  1448             takeAt(i);
       
  1449             invalidate();
       
  1450         } else {
       
  1451             ++i;
       
  1452         }
       
  1453     }
       
  1454 }
       
  1455 
       
  1456 /*!
       
  1457     Enables this layout if \a enable is true, otherwise disables it.
       
  1458 
       
  1459     An enabled layout adjusts dynamically to changes; a disabled
       
  1460     layout acts as if it did not exist.
       
  1461 
       
  1462     By default all layouts are enabled.
       
  1463 
       
  1464     \sa isEnabled()
       
  1465 */
       
  1466 void QLayout::setEnabled(bool enable)
       
  1467 {
       
  1468     Q_D(QLayout);
       
  1469     d->enabled = enable;
       
  1470 }
       
  1471 
       
  1472 /*!
       
  1473     Returns true if the layout is enabled; otherwise returns false.
       
  1474 
       
  1475     \sa setEnabled()
       
  1476 */
       
  1477 bool QLayout::isEnabled() const
       
  1478 {
       
  1479     Q_D(const QLayout);
       
  1480     return d->enabled;
       
  1481 }
       
  1482 
       
  1483 /*!
       
  1484     Returns a size that satisfies all size constraints on \a widget,
       
  1485     including heightForWidth() and that is as close as possible to \a
       
  1486     size.
       
  1487 */
       
  1488 
       
  1489 QSize QLayout::closestAcceptableSize(const QWidget *widget, const QSize &size)
       
  1490 {
       
  1491     QSize result = size.boundedTo(qSmartMaxSize(widget));
       
  1492     result = result.expandedTo(qSmartMinSize(widget));
       
  1493     QLayout *l = widget->layout();
       
  1494     if (l && l->hasHeightForWidth() && result.height() < l->minimumHeightForWidth(result.width()) ) {
       
  1495         QSize current = widget->size();
       
  1496         int currentHfw =  l->minimumHeightForWidth(current.width());
       
  1497         int newHfw = l->minimumHeightForWidth(result.width());
       
  1498         if (current.height() < currentHfw || currentHfw == newHfw) {
       
  1499             //handle the constant hfw case and the vertical-only case, as well as the
       
  1500             // current-size-is-not-correct case
       
  1501             result.setHeight(newHfw);
       
  1502         } else {
       
  1503             // binary search; assume hfw is decreasing ###
       
  1504 
       
  1505             int maxw = qMax(widget->width(),result.width());
       
  1506             int maxh = qMax(widget->height(), result.height());
       
  1507             int minw = qMin(widget->width(),result.width());
       
  1508             int minh = qMin(widget->height(), result.height());
       
  1509 
       
  1510             int minhfw = l->minimumHeightForWidth(minw);
       
  1511             int maxhfw = l->minimumHeightForWidth(maxw);
       
  1512             while (minw < maxw) {
       
  1513                 if (minhfw > maxh) { //assume decreasing
       
  1514                     minw = maxw - (maxw-minw)/2;
       
  1515                     minhfw = l->minimumHeightForWidth(minw);
       
  1516                 } else if (maxhfw < minh ) { //assume decreasing
       
  1517                     maxw = minw + (maxw-minw)/2;
       
  1518                     maxhfw = l->minimumHeightForWidth(maxw);
       
  1519                 } else  {
       
  1520                     break;
       
  1521                 }
       
  1522             }
       
  1523             result = result.expandedTo(QSize(minw, minhfw));
       
  1524         }
       
  1525     }
       
  1526     return result;
       
  1527 }
       
  1528 
       
  1529 /*!
       
  1530     \fn void QLayout::setResizeMode(SizeConstraint constraint)
       
  1531 
       
  1532     Use setSizeConstraint(\a constraint) instead.
       
  1533 */
       
  1534 
       
  1535 /*!
       
  1536     \fn QLayout::SizeConstraint QLayout::resizeMode() const
       
  1537 
       
  1538     Use sizeConstraint() instead.
       
  1539 */
       
  1540 
       
  1541 void QSizePolicy::setControlType(ControlType type)
       
  1542 {
       
  1543     /*
       
  1544         The control type is a flag type, with values 0x1, 0x2, 0x4, 0x8, 0x10,
       
  1545         etc. In memory, we pack it onto the available bits (CTSize) in
       
  1546         setControlType(), and unpack it here.
       
  1547 
       
  1548         Example:
       
  1549 
       
  1550             0x00000001 maps to 0x00000000
       
  1551             0x00000002 maps to 0x00000200
       
  1552             0x00000004 maps to 0x00000400
       
  1553             0x00000008 maps to 0x00000600
       
  1554             etc.
       
  1555     */
       
  1556 
       
  1557     int i = 0;
       
  1558     while (true) {
       
  1559         if (type & (0x1 << i)) {
       
  1560             data = (data & ~CTMask) | (i << CTShift);
       
  1561             return;
       
  1562         }
       
  1563         ++i;
       
  1564     }
       
  1565 }
       
  1566 
       
  1567 QSizePolicy::ControlType QSizePolicy::controlType() const
       
  1568 {
       
  1569     return QSizePolicy::ControlType(0x1 << ((data & CTMask) >> CTShift));
       
  1570 }
       
  1571 
       
  1572 #ifndef QT_NO_DATASTREAM
       
  1573 /*!
       
  1574     \relates QSizePolicy
       
  1575     \since 4.2
       
  1576 
       
  1577     Writes the size \a policy to the data stream \a stream.
       
  1578 
       
  1579     \sa \link datastreamformat.html Format of the QDataStream operators \endlink
       
  1580 */
       
  1581 QDataStream &operator<<(QDataStream &stream, const QSizePolicy &policy)
       
  1582 {
       
  1583     return stream << policy.data;
       
  1584 }
       
  1585 
       
  1586 /*!
       
  1587     \relates QSizePolicy
       
  1588     \since 4.2
       
  1589 
       
  1590     Reads the size \a policy from the data stream \a stream.
       
  1591 
       
  1592     \sa \link datastreamformat.html Format of the QDataStream operators \endlink
       
  1593 */
       
  1594 QDataStream &operator>>(QDataStream &stream, QSizePolicy &policy)
       
  1595 {
       
  1596     return stream >> policy.data;
       
  1597 }
       
  1598 #endif // QT_NO_DATASTREAM
       
  1599 
       
  1600 QT_END_NAMESPACE