src/gui/kernel/qlayoutitem.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the 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 "qevent.h"
       
    49 #include "qstyle.h"
       
    50 #include "qvariant.h"
       
    51 #include "qwidget_p.h"
       
    52 
       
    53 QT_BEGIN_NAMESPACE
       
    54 
       
    55 inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
       
    56 {
       
    57     return rect.adjusted(priv->leftLayoutItemMargin, priv->topLayoutItemMargin,
       
    58                          -priv->rightLayoutItemMargin, -priv->bottomLayoutItemMargin);
       
    59 }
       
    60 
       
    61 inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
       
    62 {
       
    63     return fromLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
       
    64 }
       
    65 
       
    66 inline static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
       
    67 {
       
    68     return rect.adjusted(-priv->leftLayoutItemMargin, -priv->topLayoutItemMargin,
       
    69                          priv->rightLayoutItemMargin, priv->bottomLayoutItemMargin);
       
    70 }
       
    71 
       
    72 inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
       
    73 {
       
    74     return toLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
       
    75 }
       
    76 
       
    77 /*!
       
    78    Returns a QVariant storing this QSizePolicy.
       
    79 */
       
    80 QSizePolicy::operator QVariant() const
       
    81 {
       
    82     return QVariant(QVariant::SizePolicy, this);
       
    83 }
       
    84 
       
    85 /*!
       
    86     \class QLayoutItem
       
    87     \brief The QLayoutItem class provides an abstract item that a
       
    88     QLayout manipulates.
       
    89 
       
    90     \ingroup geomanagement
       
    91 
       
    92     This is used by custom layouts.
       
    93 
       
    94     Pure virtual functions are provided to return information about
       
    95     the layout, including, sizeHint(), minimumSize(), maximumSize()
       
    96     and expanding().
       
    97 
       
    98     The layout's geometry can be set and retrieved with setGeometry()
       
    99     and geometry(), and its alignment with setAlignment() and
       
   100     alignment().
       
   101 
       
   102     isEmpty() returns whether the layout item is empty. If the
       
   103     concrete item is a QWidget, it can be retrieved using widget().
       
   104     Similarly for layout() and spacerItem().
       
   105 
       
   106     Some layouts have width and height interdependencies. These can
       
   107     be expressed using hasHeightForWidth(), heightForWidth(), and
       
   108     minimumHeightForWidth(). For more explanation see the \e{Qt
       
   109     Quarterly} article
       
   110     \l{http://qt.nokia.com/doc/qq/qq04-height-for-width.html}{Trading
       
   111     Height for Width}.
       
   112 
       
   113     \sa QLayout
       
   114 */
       
   115 
       
   116 /*!
       
   117     \class QSpacerItem
       
   118     \ingroup geomanagement
       
   119     \brief The QSpacerItem class provides blank space in a layout.
       
   120 
       
   121     Normally, you don't need to use this class directly. Qt's
       
   122     built-in layout managers provide the following functions for
       
   123     manipulating empty space in layouts:
       
   124 
       
   125     \table
       
   126     \header \o Class
       
   127             \o Functions
       
   128     \row    \o QHBoxLayout
       
   129             \o \l{QBoxLayout::addSpacing()}{addSpacing()},
       
   130                \l{QBoxLayout::addStretch()}{addStretch()},
       
   131                \l{QBoxLayout::insertSpacing()}{insertSpacing()},
       
   132                \l{QBoxLayout::insertStretch()}{insertStretch()}
       
   133     \row    \o QGridLayout
       
   134             \o \l{QGridLayout::setRowMinimumHeight()}{setRowMinimumHeight()},
       
   135                \l{QGridLayout::setRowStretch()}{setRowStretch()},
       
   136                \l{QGridLayout::setColumnMinimumWidth()}{setColumnMinimumWidth()},
       
   137                \l{QGridLayout::setColumnStretch()}{setColumnStretch()}
       
   138     \endtable
       
   139 
       
   140     \sa QLayout, QWidgetItem, QLayoutItem::spacerItem()
       
   141 */
       
   142 
       
   143 /*!
       
   144     \class QWidgetItem
       
   145     \ingroup geomanagement
       
   146     \brief The QWidgetItem class is a layout item that represents a widget.
       
   147 
       
   148     Normally, you don't need to use this class directly. Qt's
       
   149     built-in layout managers provide the following functions for
       
   150     manipulating widgets in layouts:
       
   151 
       
   152     \table
       
   153     \header \o Class
       
   154             \o Functions
       
   155     \row    \o QBoxLayout
       
   156             \o \l{QBoxLayout::addWidget()}{addWidget()},
       
   157                \l{QBoxLayout::insertWidget()}{insertWidget()},
       
   158                \l{QBoxLayout::setStretchFactor()}{setStretchFactor()}
       
   159     \row    \o QGridLayout
       
   160             \o \l{QGridLayout::addWidget()}{addWidget()}
       
   161     \row    \o QStackedLayout
       
   162             \o \l{QStackedLayout::addWidget()}{addWidget()},
       
   163                \l{QStackedLayout::insertWidget()}{insertWidget()},
       
   164                \l{QStackedLayout::currentWidget()}{currentWidget()},
       
   165                \l{QStackedLayout::setCurrentWidget()}{setCurrentWidget()},
       
   166                \l{QStackedLayout::widget()}{widget()}
       
   167     \endtable
       
   168 
       
   169     \sa QLayout, QSpacerItem, QLayoutItem::widget()
       
   170 */
       
   171 
       
   172 /*!
       
   173     \fn QLayoutItem::QLayoutItem(Qt::Alignment alignment)
       
   174 
       
   175     Constructs a layout item with an \a alignment.
       
   176     Not all subclasses support alignment.
       
   177 */
       
   178 
       
   179 /*!
       
   180     \fn Qt::Alignment QLayoutItem::alignment() const
       
   181 
       
   182     Returns the alignment of this item.
       
   183 */
       
   184 
       
   185 /*!
       
   186     Sets the alignment of this item to \a alignment.
       
   187 
       
   188     \bold{Note:} Item alignment is only supported by QLayoutItem subclasses
       
   189     where it would have a visual effect. Except for QSpacerItem, which provides
       
   190     blank space for layouts, all public Qt classes that inherit QLayoutItem
       
   191     support item alignment.
       
   192 */
       
   193 void QLayoutItem::setAlignment(Qt::Alignment alignment)
       
   194 {
       
   195     align = alignment;
       
   196 }
       
   197 
       
   198 /*!
       
   199     \fn QSize QLayoutItem::maximumSize() const
       
   200 
       
   201     Implemented in subclasses to return the maximum size of this item.
       
   202 */
       
   203 
       
   204 /*!
       
   205     \fn QSize QLayoutItem::minimumSize() const
       
   206 
       
   207     Implemented in subclasses to return the minimum size of this item.
       
   208 */
       
   209 
       
   210 /*!
       
   211     \fn QSize QLayoutItem::sizeHint() const
       
   212 
       
   213     Implemented in subclasses to return the preferred size of this item.
       
   214 */
       
   215 
       
   216 /*!
       
   217     \fn Qt::Orientations QLayoutItem::expandingDirections() const
       
   218 
       
   219     Returns whether this layout item can make use of more space than
       
   220     sizeHint(). A value of Qt::Vertical or Qt::Horizontal means that
       
   221     it wants to grow in only one dimension, whereas Qt::Vertical |
       
   222     Qt::Horizontal means that it wants to grow in both dimensions.
       
   223 */
       
   224 
       
   225 /*!
       
   226     \fn void QLayoutItem::setGeometry(const QRect &r)
       
   227 
       
   228     Implemented in subclasses to set this item's geometry to \a r.
       
   229 
       
   230     \sa geometry()
       
   231 */
       
   232 
       
   233 /*!
       
   234     \fn QRect QLayoutItem::geometry() const
       
   235 
       
   236     Returns the rectangle covered by this layout item.
       
   237 
       
   238     \sa setGeometry()
       
   239 */
       
   240 
       
   241 /*!
       
   242     \fn virtual bool QLayoutItem::isEmpty() const
       
   243 
       
   244     Implemented in subclasses to return whether this item is empty,
       
   245     i.e. whether it contains any widgets.
       
   246 */
       
   247 
       
   248 /*!
       
   249     \fn QSpacerItem::QSpacerItem(int w, int h, QSizePolicy::Policy hPolicy, QSizePolicy::Policy vPolicy)
       
   250 
       
   251     Constructs a spacer item with preferred width \a w, preferred
       
   252     height \a h, horizontal size policy \a hPolicy and vertical size
       
   253     policy \a vPolicy.
       
   254 
       
   255     The default values provide a gap that is able to stretch if
       
   256     nothing else wants the space.
       
   257 */
       
   258 
       
   259 /*!
       
   260     Changes this spacer item to have preferred width \a w, preferred
       
   261     height \a h, horizontal size policy \a hPolicy and vertical size
       
   262     policy \a vPolicy.
       
   263 
       
   264     The default values provide a gap that is able to stretch if
       
   265     nothing else wants the space.
       
   266 
       
   267     Note that if changeSize() is called after the spacer item has been added
       
   268     to a layout, it is necessary to invalidate the layout in order for the
       
   269     spacer item's new size to take effect.
       
   270 
       
   271     \sa QSpacerItem::invalidate()
       
   272 */
       
   273 void QSpacerItem::changeSize(int w, int h, QSizePolicy::Policy hPolicy,
       
   274                              QSizePolicy::Policy vPolicy)
       
   275 {
       
   276     width = w;
       
   277     height = h;
       
   278     sizeP = QSizePolicy(hPolicy, vPolicy);
       
   279 }
       
   280 
       
   281 /*!
       
   282     \fn QWidgetItem::QWidgetItem(QWidget *widget)
       
   283 
       
   284     Creates an item containing the given \a widget.
       
   285 */
       
   286 
       
   287 /*!
       
   288     Destroys the QLayoutItem.
       
   289 */
       
   290 QLayoutItem::~QLayoutItem()
       
   291 {
       
   292 }
       
   293 
       
   294 /*!
       
   295     Invalidates any cached information in this layout item.
       
   296 */
       
   297 void QLayoutItem::invalidate()
       
   298 {
       
   299 }
       
   300 
       
   301 /*!
       
   302     If this item is a QLayout, it is returned as a QLayout; otherwise
       
   303     0 is returned. This function provides type-safe casting.
       
   304 */
       
   305 QLayout * QLayoutItem::layout()
       
   306 {
       
   307     return 0;
       
   308 }
       
   309 
       
   310 /*!
       
   311     If this item is a QSpacerItem, it is returned as a QSpacerItem;
       
   312     otherwise 0 is returned. This function provides type-safe casting.
       
   313 */
       
   314 QSpacerItem * QLayoutItem::spacerItem()
       
   315 {
       
   316     return 0;
       
   317 }
       
   318 
       
   319 /*!
       
   320     \reimp
       
   321 */
       
   322 QLayout * QLayout::layout()
       
   323 {
       
   324     return this;
       
   325 }
       
   326 
       
   327 /*!
       
   328     Returns a pointer to this object.
       
   329 */
       
   330 QSpacerItem * QSpacerItem::spacerItem()
       
   331 {
       
   332     return this;
       
   333 }
       
   334 
       
   335 /*!
       
   336     If this item is a QWidget, it is returned as a QWidget; otherwise
       
   337     0 is returned. This function provides type-safe casting.
       
   338 */
       
   339 QWidget * QLayoutItem::widget()
       
   340 {
       
   341     return 0;
       
   342 }
       
   343 
       
   344 /*!
       
   345     Returns the widget managed by this item.
       
   346 */
       
   347 QWidget *QWidgetItem::widget()
       
   348 {
       
   349     return wid;
       
   350 }
       
   351 
       
   352 /*!
       
   353     Returns true if this layout's preferred height depends on its
       
   354     width; otherwise returns false. The default implementation returns
       
   355     false.
       
   356 
       
   357     Reimplement this function in layout managers that support height
       
   358     for width.
       
   359 
       
   360     \sa heightForWidth(), QWidget::heightForWidth()
       
   361 */
       
   362 bool QLayoutItem::hasHeightForWidth() const
       
   363 {
       
   364     return false;
       
   365 }
       
   366 
       
   367 /*!
       
   368     Returns the minimum height this widget needs for the given width,
       
   369     \a w. The default implementation simply returns heightForWidth(\a
       
   370     w).
       
   371 */
       
   372 int QLayoutItem::minimumHeightForWidth(int w) const
       
   373 {
       
   374     return heightForWidth(w);
       
   375 }
       
   376 
       
   377 
       
   378 /*!
       
   379     Returns the preferred height for this layout item, given the width
       
   380     \a w.
       
   381 
       
   382     The default implementation returns -1, indicating that the
       
   383     preferred height is independent of the width of the item. Using
       
   384     the function hasHeightForWidth() will typically be much faster
       
   385     than calling this function and testing for -1.
       
   386 
       
   387     Reimplement this function in layout managers that support height
       
   388     for width. A typical implementation will look like this:
       
   389     \snippet doc/src/snippets/code/src_gui_kernel_qlayoutitem.cpp 0
       
   390 
       
   391     Caching is strongly recommended; without it layout will take
       
   392     exponential time.
       
   393 
       
   394     \sa hasHeightForWidth()
       
   395 */
       
   396 int QLayoutItem::heightForWidth(int /* w */) const
       
   397 {
       
   398     return -1;
       
   399 }
       
   400 
       
   401 /*!
       
   402     Returns the control type(s) for the layout item. For a
       
   403     QWidgetItem, the control type comes from the widget's size
       
   404     policy; for a QLayoutItem, the control types is derived from the
       
   405     layout's contents.
       
   406 
       
   407     \sa QSizePolicy::controlType()
       
   408 */
       
   409 QSizePolicy::ControlTypes QLayoutItem::controlTypes() const
       
   410 {
       
   411     // ### Qt 5: This function should probably be virtual instead
       
   412     if (const QWidget *widget = const_cast<QLayoutItem*>(this)->widget()) {
       
   413         return widget->sizePolicy().controlType();
       
   414     } else if (const QLayout *layout = const_cast<QLayoutItem*>(this)->layout()) {
       
   415         if (layout->count() == 0)
       
   416             return QSizePolicy::DefaultType;
       
   417         QSizePolicy::ControlTypes types;
       
   418         for (int i = layout->count() - 1; i >= 0; --i)
       
   419             types |= layout->itemAt(i)->controlTypes();
       
   420         return types;
       
   421     }
       
   422     return QSizePolicy::DefaultType;
       
   423 }
       
   424 
       
   425 /*!
       
   426     \reimp
       
   427 */
       
   428 void QSpacerItem::setGeometry(const QRect &r)
       
   429 {
       
   430     rect = r;
       
   431 }
       
   432 
       
   433 /*!
       
   434     \reimp
       
   435 */
       
   436 void QWidgetItem::setGeometry(const QRect &rect)
       
   437 {
       
   438     if (isEmpty())
       
   439         return;
       
   440 
       
   441     QRect r = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
       
   442             ? fromLayoutItemRect(wid->d_func(), rect)
       
   443             : rect;
       
   444     const QSize widgetRectSurplus = r.size() - rect.size(); 
       
   445 
       
   446     /* 
       
   447        For historical reasons, this code is done using widget rect 
       
   448        coordinates, not layout item rect coordinates. However, 
       
   449        QWidgetItem's sizeHint(), maximumSize(), and heightForWidth() 
       
   450        all work in terms of layout item rect coordinates, so we have to 
       
   451        add or subtract widgetRectSurplus here and there. The code could 
       
   452        be much simpler if we did everything using layout item rect 
       
   453        coordinates and did the conversion right before the call to 
       
   454        QWidget::setGeometry(). 
       
   455      */ 
       
   456 
       
   457     QSize s = r.size().boundedTo(maximumSize() + widgetRectSurplus);  
       
   458     int x = r.x();
       
   459     int y = r.y();
       
   460     if (align & (Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask)) {
       
   461         QSize pref(sizeHint());
       
   462         QSizePolicy sp = wid->sizePolicy();
       
   463         if (sp.horizontalPolicy() == QSizePolicy::Ignored)
       
   464             pref.setWidth(wid->sizeHint().expandedTo(wid->minimumSize()).width());
       
   465         if (sp.verticalPolicy() == QSizePolicy::Ignored)
       
   466             pref.setHeight(wid->sizeHint().expandedTo(wid->minimumSize()).height());
       
   467         pref += widgetRectSurplus;
       
   468         if (align & Qt::AlignHorizontal_Mask)
       
   469             s.setWidth(qMin(s.width(), pref.width()));
       
   470         if (align & Qt::AlignVertical_Mask) {
       
   471             if (hasHeightForWidth())
       
   472                 s.setHeight(qMin(s.height(), 
       
   473                                  heightForWidth(s.width() - widgetRectSurplus.width()) 
       
   474                                  + widgetRectSurplus.height()));
       
   475             else
       
   476                 s.setHeight(qMin(s.height(), pref.height()));
       
   477         }
       
   478     }
       
   479     Qt::Alignment alignHoriz = QStyle::visualAlignment(wid->layoutDirection(), align);
       
   480     if (alignHoriz & Qt::AlignRight)
       
   481         x = x + (r.width() - s.width());
       
   482     else if (!(alignHoriz & Qt::AlignLeft))
       
   483         x = x + (r.width() - s.width()) / 2;
       
   484 
       
   485     if (align & Qt::AlignBottom)
       
   486         y = y + (r.height() - s.height());
       
   487     else if (!(align & Qt::AlignTop))
       
   488         y = y + (r.height() - s.height()) / 2;
       
   489 
       
   490     wid->setGeometry(x, y, s.width(), s.height());
       
   491 }
       
   492 
       
   493 /*!
       
   494     \reimp
       
   495 */
       
   496 QRect QSpacerItem::geometry() const
       
   497 {
       
   498     return rect;
       
   499 }
       
   500 
       
   501 /*!
       
   502     \reimp
       
   503 */
       
   504 QRect QWidgetItem::geometry() const
       
   505 {
       
   506     return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
       
   507            ? toLayoutItemRect(wid->d_func(), wid->geometry())
       
   508            : wid->geometry();
       
   509 }
       
   510 
       
   511 
       
   512 /*!
       
   513     \reimp
       
   514 */
       
   515 bool QWidgetItem::hasHeightForWidth() const
       
   516 {
       
   517     if (isEmpty())
       
   518         return false;
       
   519     if (wid->layout())
       
   520         return wid->layout()->hasHeightForWidth();
       
   521     return wid->sizePolicy().hasHeightForWidth();
       
   522 }
       
   523 
       
   524 /*!
       
   525     \reimp
       
   526 */
       
   527 int QWidgetItem::heightForWidth(int w) const
       
   528 {
       
   529     if (isEmpty())
       
   530         return -1;
       
   531 
       
   532     w = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
       
   533       ? fromLayoutItemSize(wid->d_func(), QSize(w, 0)).width()
       
   534       : w;
       
   535 
       
   536     int hfw;
       
   537     if (wid->layout())
       
   538         hfw = wid->layout()->totalHeightForWidth(w);
       
   539     else
       
   540         hfw = wid->heightForWidth(w);
       
   541 
       
   542     if (hfw > wid->maximumHeight())
       
   543         hfw = wid->maximumHeight();
       
   544     if (hfw < wid->minimumHeight())
       
   545         hfw = wid->minimumHeight();
       
   546 
       
   547     hfw = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
       
   548         ? toLayoutItemSize(wid->d_func(), QSize(0, hfw)).height()
       
   549         : hfw;
       
   550 
       
   551     if (hfw < 0)
       
   552         hfw = 0;
       
   553     return hfw;
       
   554 }
       
   555 
       
   556 /*!
       
   557     \reimp
       
   558 */
       
   559 Qt::Orientations QSpacerItem::expandingDirections() const
       
   560 {
       
   561     return sizeP.expandingDirections();
       
   562 }
       
   563 
       
   564 /*!
       
   565     \reimp
       
   566 */
       
   567 Qt::Orientations QWidgetItem::expandingDirections() const
       
   568 {
       
   569     if (isEmpty())
       
   570         return Qt::Orientations(0);
       
   571 
       
   572     Qt::Orientations e = wid->sizePolicy().expandingDirections();
       
   573     /*
       
   574       ### Qt 4.0:
       
   575       If the layout is expanding, we make the widget expanding, even if
       
   576       its own size policy isn't expanding. This behavior should be
       
   577       reconsidered.
       
   578     */
       
   579     if (wid->layout()) {
       
   580         if (wid->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag
       
   581                 && (wid->layout()->expandingDirections() & Qt::Horizontal))
       
   582             e |= Qt::Horizontal;
       
   583         if (wid->sizePolicy().verticalPolicy() & QSizePolicy::GrowFlag
       
   584                 && (wid->layout()->expandingDirections() & Qt::Vertical))
       
   585             e |= Qt::Vertical;
       
   586     }
       
   587 
       
   588     if (align & Qt::AlignHorizontal_Mask)
       
   589         e &= ~Qt::Horizontal;
       
   590     if (align & Qt::AlignVertical_Mask)
       
   591         e &= ~Qt::Vertical;
       
   592     return e;
       
   593 }
       
   594 
       
   595 /*!
       
   596     \reimp
       
   597 */
       
   598 QSize QSpacerItem::minimumSize() const
       
   599 {
       
   600     return QSize(sizeP.horizontalPolicy() & QSizePolicy::ShrinkFlag ? 0 : width,
       
   601                  sizeP.verticalPolicy() & QSizePolicy::ShrinkFlag ? 0 : height);
       
   602 }
       
   603 
       
   604 /*!
       
   605     \reimp
       
   606 */
       
   607 QSize QWidgetItem::minimumSize() const
       
   608 {
       
   609     if (isEmpty())
       
   610         return QSize(0, 0);
       
   611     return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
       
   612            ? toLayoutItemSize(wid->d_func(), qSmartMinSize(this))
       
   613            : qSmartMinSize(this);
       
   614 }
       
   615 
       
   616 /*!
       
   617     \reimp
       
   618 */
       
   619 QSize QSpacerItem::maximumSize() const
       
   620 {
       
   621     return QSize(sizeP.horizontalPolicy() & QSizePolicy::GrowFlag ? QLAYOUTSIZE_MAX : width,
       
   622                  sizeP.verticalPolicy() & QSizePolicy::GrowFlag ? QLAYOUTSIZE_MAX : height);
       
   623 }
       
   624 
       
   625 /*!
       
   626     \reimp
       
   627 */
       
   628 QSize QWidgetItem::maximumSize() const
       
   629 {
       
   630     if (isEmpty()) {
       
   631         return QSize(0, 0);
       
   632     } else {
       
   633         return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
       
   634                ? toLayoutItemSize(wid->d_func(), qSmartMaxSize(this, align))
       
   635                : qSmartMaxSize(this, align);
       
   636     }
       
   637 }
       
   638 
       
   639 /*!
       
   640     \reimp
       
   641 */
       
   642 QSize QSpacerItem::sizeHint() const
       
   643 {
       
   644     return QSize(width, height);
       
   645 }
       
   646 
       
   647 /*!
       
   648     \reimp
       
   649 */
       
   650 QSize QWidgetItem::sizeHint() const
       
   651 {
       
   652     QSize s(0, 0);
       
   653     if (!isEmpty()) {
       
   654         s = wid->sizeHint().expandedTo(wid->minimumSizeHint());
       
   655         s = s.boundedTo(wid->maximumSize())
       
   656              .expandedTo(wid->minimumSize());
       
   657         s = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
       
   658            ? toLayoutItemSize(wid->d_func(), s)
       
   659            : s;
       
   660 
       
   661         if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
       
   662             s.setWidth(0);
       
   663         if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
       
   664             s.setHeight(0);
       
   665     }
       
   666     return s;
       
   667 }
       
   668 
       
   669 /*!
       
   670     Returns true.
       
   671 */
       
   672 bool QSpacerItem::isEmpty() const
       
   673 {
       
   674     return true;
       
   675 }
       
   676 
       
   677 /*!
       
   678     Returns true if the widget is hidden; otherwise returns false.
       
   679 
       
   680     \sa QWidget::isHidden()
       
   681 */
       
   682 bool QWidgetItem::isEmpty() const
       
   683 {
       
   684     return wid->isHidden() || wid->isWindow();
       
   685 }
       
   686 
       
   687 /*!
       
   688     \class QWidgetItemV2
       
   689     \internal
       
   690 */
       
   691 
       
   692 inline bool QWidgetItemV2::useSizeCache() const
       
   693 {
       
   694     return wid->d_func()->widgetItem == this;
       
   695 }
       
   696 
       
   697 void QWidgetItemV2::updateCacheIfNecessary() const
       
   698 {
       
   699     if (q_cachedMinimumSize.width() != Dirty)
       
   700         return;
       
   701 
       
   702     const QSize sizeHint(wid->sizeHint());
       
   703     const QSize minimumSizeHint(wid->minimumSizeHint());
       
   704     const QSize minimumSize(wid->minimumSize());
       
   705     const QSize maximumSize(wid->maximumSize());
       
   706     const QSizePolicy sizePolicy(wid->sizePolicy());
       
   707     const QSize expandedSizeHint(sizeHint.expandedTo(minimumSizeHint));
       
   708 
       
   709     const QSize smartMinSize(qSmartMinSize(sizeHint, minimumSizeHint, minimumSize, maximumSize, sizePolicy));
       
   710     const QSize smartMaxSize(qSmartMaxSize(expandedSizeHint, minimumSize, maximumSize, sizePolicy, align));
       
   711 
       
   712     const bool useLayoutItemRect = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect);
       
   713 
       
   714     q_cachedMinimumSize = useLayoutItemRect
       
   715            ? toLayoutItemSize(wid->d_func(), smartMinSize)
       
   716            : smartMinSize;
       
   717 
       
   718     q_cachedSizeHint = expandedSizeHint;
       
   719     q_cachedSizeHint = q_cachedSizeHint.boundedTo(maximumSize)
       
   720                                        .expandedTo(minimumSize);
       
   721     q_cachedSizeHint = useLayoutItemRect
       
   722            ? toLayoutItemSize(wid->d_func(), q_cachedSizeHint)
       
   723            : q_cachedSizeHint;
       
   724 
       
   725     if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
       
   726         q_cachedSizeHint.setWidth(0);
       
   727     if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
       
   728         q_cachedSizeHint.setHeight(0);
       
   729 
       
   730     q_cachedMaximumSize = useLayoutItemRect
       
   731                ? toLayoutItemSize(wid->d_func(), smartMaxSize)
       
   732                : smartMaxSize;
       
   733 }
       
   734 
       
   735 QWidgetItemV2::QWidgetItemV2(QWidget *widget)
       
   736     : QWidgetItem(widget),
       
   737       q_cachedMinimumSize(Dirty, Dirty),
       
   738       q_cachedSizeHint(Dirty, Dirty),
       
   739       q_cachedMaximumSize(Dirty, Dirty),
       
   740       q_firstCachedHfw(0),
       
   741       q_hfwCacheSize(0),
       
   742       d(0)
       
   743 {
       
   744     QWidgetPrivate *wd = wid->d_func();
       
   745     if (!wd->widgetItem)
       
   746         wd->widgetItem = this;
       
   747 }
       
   748 
       
   749 QWidgetItemV2::~QWidgetItemV2()
       
   750 {
       
   751     if (wid) {
       
   752         QWidgetPrivate *wd = wid->d_func();
       
   753         if (wd->widgetItem == this)
       
   754             wd->widgetItem = 0;
       
   755     }
       
   756 }
       
   757 
       
   758 QSize QWidgetItemV2::sizeHint() const
       
   759 {
       
   760     if (isEmpty())
       
   761         return QSize(0, 0);
       
   762 
       
   763     if (useSizeCache()) {
       
   764         updateCacheIfNecessary();
       
   765         return q_cachedSizeHint;
       
   766     } else {
       
   767         return QWidgetItem::sizeHint();
       
   768     }
       
   769 }
       
   770 
       
   771 QSize QWidgetItemV2::minimumSize() const
       
   772 {
       
   773     if (isEmpty())
       
   774         return QSize(0, 0);
       
   775 
       
   776     if (useSizeCache()) {
       
   777         updateCacheIfNecessary();
       
   778         return q_cachedMinimumSize;
       
   779     } else {
       
   780         return QWidgetItem::minimumSize();
       
   781     }
       
   782 }
       
   783 
       
   784 QSize QWidgetItemV2::maximumSize() const
       
   785 {
       
   786     if (isEmpty())
       
   787         return QSize(0, 0);
       
   788 
       
   789     if (useSizeCache()) {
       
   790         updateCacheIfNecessary();
       
   791         return q_cachedMaximumSize;
       
   792     } else {
       
   793         return QWidgetItem::maximumSize();
       
   794     }
       
   795 }
       
   796 
       
   797 /*
       
   798     The height-for-width cache is organized as a circular buffer. The entries
       
   799 
       
   800         q_hfwCachedHfws[q_firstCachedHfw],
       
   801         ...,
       
   802         q_hfwCachedHfws[(q_firstCachedHfw + q_hfwCacheSize - 1) % HfwCacheMaxSize]
       
   803 
       
   804     contain the last cached values. When the cache is full, the first entry to
       
   805     be erased is the entry before q_hfwCachedHfws[q_firstCachedHfw]. When
       
   806     values are looked up, we try to move q_firstCachedHfw to point to that new
       
   807     entry (unless the cache is not full, in which case it would leave the cache
       
   808     in a broken state), so that the most recently used entry is also the last
       
   809     to be erased.
       
   810 */
       
   811 
       
   812 int QWidgetItemV2::heightForWidth(int width) const
       
   813 {
       
   814     if (isEmpty())
       
   815         return -1;
       
   816 
       
   817     for (int i = 0; i < q_hfwCacheSize; ++i) {
       
   818         int offset = q_firstCachedHfw + i;
       
   819         const QSize &size = q_cachedHfws[offset % HfwCacheMaxSize];
       
   820         if (size.width() == width) {
       
   821             if (q_hfwCacheSize == HfwCacheMaxSize)
       
   822                 q_firstCachedHfw = offset;
       
   823             return size.height();
       
   824         }
       
   825     }
       
   826 
       
   827     if (q_hfwCacheSize < HfwCacheMaxSize)
       
   828         ++q_hfwCacheSize;
       
   829     q_firstCachedHfw = (q_firstCachedHfw + HfwCacheMaxSize - 1) % HfwCacheMaxSize;
       
   830 
       
   831     int height = QWidgetItem::heightForWidth(width);
       
   832     q_cachedHfws[q_firstCachedHfw] = QSize(width, height);
       
   833     return height;
       
   834 }
       
   835 
       
   836 QT_END_NAMESPACE