--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/kernel/qlayoutitem.cpp Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,836 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlayout.h"
+
+#include "qapplication.h"
+#include "qlayoutengine_p.h"
+#include "qmenubar.h"
+#include "qtoolbar.h"
+#include "qevent.h"
+#include "qstyle.h"
+#include "qvariant.h"
+#include "qwidget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
+{
+ return rect.adjusted(priv->leftLayoutItemMargin, priv->topLayoutItemMargin,
+ -priv->rightLayoutItemMargin, -priv->bottomLayoutItemMargin);
+}
+
+inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
+{
+ return fromLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
+}
+
+inline static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
+{
+ return rect.adjusted(-priv->leftLayoutItemMargin, -priv->topLayoutItemMargin,
+ priv->rightLayoutItemMargin, priv->bottomLayoutItemMargin);
+}
+
+inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
+{
+ return toLayoutItemRect(priv, QRect(QPoint(0, 0), size)).size();
+}
+
+/*!
+ Returns a QVariant storing this QSizePolicy.
+*/
+QSizePolicy::operator QVariant() const
+{
+ return QVariant(QVariant::SizePolicy, this);
+}
+
+/*!
+ \class QLayoutItem
+ \brief The QLayoutItem class provides an abstract item that a
+ QLayout manipulates.
+
+ \ingroup geomanagement
+
+ This is used by custom layouts.
+
+ Pure virtual functions are provided to return information about
+ the layout, including, sizeHint(), minimumSize(), maximumSize()
+ and expanding().
+
+ The layout's geometry can be set and retrieved with setGeometry()
+ and geometry(), and its alignment with setAlignment() and
+ alignment().
+
+ isEmpty() returns whether the layout item is empty. If the
+ concrete item is a QWidget, it can be retrieved using widget().
+ Similarly for layout() and spacerItem().
+
+ Some layouts have width and height interdependencies. These can
+ be expressed using hasHeightForWidth(), heightForWidth(), and
+ minimumHeightForWidth(). For more explanation see the \e{Qt
+ Quarterly} article
+ \l{http://qt.nokia.com/doc/qq/qq04-height-for-width.html}{Trading
+ Height for Width}.
+
+ \sa QLayout
+*/
+
+/*!
+ \class QSpacerItem
+ \ingroup geomanagement
+ \brief The QSpacerItem class provides blank space in a layout.
+
+ Normally, you don't need to use this class directly. Qt's
+ built-in layout managers provide the following functions for
+ manipulating empty space in layouts:
+
+ \table
+ \header \o Class
+ \o Functions
+ \row \o QHBoxLayout
+ \o \l{QBoxLayout::addSpacing()}{addSpacing()},
+ \l{QBoxLayout::addStretch()}{addStretch()},
+ \l{QBoxLayout::insertSpacing()}{insertSpacing()},
+ \l{QBoxLayout::insertStretch()}{insertStretch()}
+ \row \o QGridLayout
+ \o \l{QGridLayout::setRowMinimumHeight()}{setRowMinimumHeight()},
+ \l{QGridLayout::setRowStretch()}{setRowStretch()},
+ \l{QGridLayout::setColumnMinimumWidth()}{setColumnMinimumWidth()},
+ \l{QGridLayout::setColumnStretch()}{setColumnStretch()}
+ \endtable
+
+ \sa QLayout, QWidgetItem, QLayoutItem::spacerItem()
+*/
+
+/*!
+ \class QWidgetItem
+ \ingroup geomanagement
+ \brief The QWidgetItem class is a layout item that represents a widget.
+
+ Normally, you don't need to use this class directly. Qt's
+ built-in layout managers provide the following functions for
+ manipulating widgets in layouts:
+
+ \table
+ \header \o Class
+ \o Functions
+ \row \o QBoxLayout
+ \o \l{QBoxLayout::addWidget()}{addWidget()},
+ \l{QBoxLayout::insertWidget()}{insertWidget()},
+ \l{QBoxLayout::setStretchFactor()}{setStretchFactor()}
+ \row \o QGridLayout
+ \o \l{QGridLayout::addWidget()}{addWidget()}
+ \row \o QStackedLayout
+ \o \l{QStackedLayout::addWidget()}{addWidget()},
+ \l{QStackedLayout::insertWidget()}{insertWidget()},
+ \l{QStackedLayout::currentWidget()}{currentWidget()},
+ \l{QStackedLayout::setCurrentWidget()}{setCurrentWidget()},
+ \l{QStackedLayout::widget()}{widget()}
+ \endtable
+
+ \sa QLayout, QSpacerItem, QLayoutItem::widget()
+*/
+
+/*!
+ \fn QLayoutItem::QLayoutItem(Qt::Alignment alignment)
+
+ Constructs a layout item with an \a alignment.
+ Not all subclasses support alignment.
+*/
+
+/*!
+ \fn Qt::Alignment QLayoutItem::alignment() const
+
+ Returns the alignment of this item.
+*/
+
+/*!
+ Sets the alignment of this item to \a alignment.
+
+ \bold{Note:} Item alignment is only supported by QLayoutItem subclasses
+ where it would have a visual effect. Except for QSpacerItem, which provides
+ blank space for layouts, all public Qt classes that inherit QLayoutItem
+ support item alignment.
+*/
+void QLayoutItem::setAlignment(Qt::Alignment alignment)
+{
+ align = alignment;
+}
+
+/*!
+ \fn QSize QLayoutItem::maximumSize() const
+
+ Implemented in subclasses to return the maximum size of this item.
+*/
+
+/*!
+ \fn QSize QLayoutItem::minimumSize() const
+
+ Implemented in subclasses to return the minimum size of this item.
+*/
+
+/*!
+ \fn QSize QLayoutItem::sizeHint() const
+
+ Implemented in subclasses to return the preferred size of this item.
+*/
+
+/*!
+ \fn Qt::Orientations QLayoutItem::expandingDirections() const
+
+ Returns whether this layout item can make use of more space than
+ sizeHint(). A value of Qt::Vertical or Qt::Horizontal means that
+ it wants to grow in only one dimension, whereas Qt::Vertical |
+ Qt::Horizontal means that it wants to grow in both dimensions.
+*/
+
+/*!
+ \fn void QLayoutItem::setGeometry(const QRect &r)
+
+ Implemented in subclasses to set this item's geometry to \a r.
+
+ \sa geometry()
+*/
+
+/*!
+ \fn QRect QLayoutItem::geometry() const
+
+ Returns the rectangle covered by this layout item.
+
+ \sa setGeometry()
+*/
+
+/*!
+ \fn virtual bool QLayoutItem::isEmpty() const
+
+ Implemented in subclasses to return whether this item is empty,
+ i.e. whether it contains any widgets.
+*/
+
+/*!
+ \fn QSpacerItem::QSpacerItem(int w, int h, QSizePolicy::Policy hPolicy, QSizePolicy::Policy vPolicy)
+
+ Constructs a spacer item with preferred width \a w, preferred
+ height \a h, horizontal size policy \a hPolicy and vertical size
+ policy \a vPolicy.
+
+ The default values provide a gap that is able to stretch if
+ nothing else wants the space.
+*/
+
+/*!
+ Changes this spacer item to have preferred width \a w, preferred
+ height \a h, horizontal size policy \a hPolicy and vertical size
+ policy \a vPolicy.
+
+ The default values provide a gap that is able to stretch if
+ nothing else wants the space.
+
+ Note that if changeSize() is called after the spacer item has been added
+ to a layout, it is necessary to invalidate the layout in order for the
+ spacer item's new size to take effect.
+
+ \sa QSpacerItem::invalidate()
+*/
+void QSpacerItem::changeSize(int w, int h, QSizePolicy::Policy hPolicy,
+ QSizePolicy::Policy vPolicy)
+{
+ width = w;
+ height = h;
+ sizeP = QSizePolicy(hPolicy, vPolicy);
+}
+
+/*!
+ \fn QWidgetItem::QWidgetItem(QWidget *widget)
+
+ Creates an item containing the given \a widget.
+*/
+
+/*!
+ Destroys the QLayoutItem.
+*/
+QLayoutItem::~QLayoutItem()
+{
+}
+
+/*!
+ Invalidates any cached information in this layout item.
+*/
+void QLayoutItem::invalidate()
+{
+}
+
+/*!
+ If this item is a QLayout, it is returned as a QLayout; otherwise
+ 0 is returned. This function provides type-safe casting.
+*/
+QLayout * QLayoutItem::layout()
+{
+ return 0;
+}
+
+/*!
+ If this item is a QSpacerItem, it is returned as a QSpacerItem;
+ otherwise 0 is returned. This function provides type-safe casting.
+*/
+QSpacerItem * QLayoutItem::spacerItem()
+{
+ return 0;
+}
+
+/*!
+ \reimp
+*/
+QLayout * QLayout::layout()
+{
+ return this;
+}
+
+/*!
+ Returns a pointer to this object.
+*/
+QSpacerItem * QSpacerItem::spacerItem()
+{
+ return this;
+}
+
+/*!
+ If this item is a QWidget, it is returned as a QWidget; otherwise
+ 0 is returned. This function provides type-safe casting.
+*/
+QWidget * QLayoutItem::widget()
+{
+ return 0;
+}
+
+/*!
+ Returns the widget managed by this item.
+*/
+QWidget *QWidgetItem::widget()
+{
+ return wid;
+}
+
+/*!
+ Returns true if this layout's preferred height depends on its
+ width; otherwise returns false. The default implementation returns
+ false.
+
+ Reimplement this function in layout managers that support height
+ for width.
+
+ \sa heightForWidth(), QWidget::heightForWidth()
+*/
+bool QLayoutItem::hasHeightForWidth() const
+{
+ return false;
+}
+
+/*!
+ Returns the minimum height this widget needs for the given width,
+ \a w. The default implementation simply returns heightForWidth(\a
+ w).
+*/
+int QLayoutItem::minimumHeightForWidth(int w) const
+{
+ return heightForWidth(w);
+}
+
+
+/*!
+ Returns the preferred height for this layout item, given the width
+ \a w.
+
+ The default implementation returns -1, indicating that the
+ preferred height is independent of the width of the item. Using
+ the function hasHeightForWidth() will typically be much faster
+ than calling this function and testing for -1.
+
+ Reimplement this function in layout managers that support height
+ for width. A typical implementation will look like this:
+ \snippet doc/src/snippets/code/src_gui_kernel_qlayoutitem.cpp 0
+
+ Caching is strongly recommended; without it layout will take
+ exponential time.
+
+ \sa hasHeightForWidth()
+*/
+int QLayoutItem::heightForWidth(int /* w */) const
+{
+ return -1;
+}
+
+/*!
+ Returns the control type(s) for the layout item. For a
+ QWidgetItem, the control type comes from the widget's size
+ policy; for a QLayoutItem, the control types is derived from the
+ layout's contents.
+
+ \sa QSizePolicy::controlType()
+*/
+QSizePolicy::ControlTypes QLayoutItem::controlTypes() const
+{
+ // ### Qt 5: This function should probably be virtual instead
+ if (const QWidget *widget = const_cast<QLayoutItem*>(this)->widget()) {
+ return widget->sizePolicy().controlType();
+ } else if (const QLayout *layout = const_cast<QLayoutItem*>(this)->layout()) {
+ if (layout->count() == 0)
+ return QSizePolicy::DefaultType;
+ QSizePolicy::ControlTypes types;
+ for (int i = layout->count() - 1; i >= 0; --i)
+ types |= layout->itemAt(i)->controlTypes();
+ return types;
+ }
+ return QSizePolicy::DefaultType;
+}
+
+/*!
+ \reimp
+*/
+void QSpacerItem::setGeometry(const QRect &r)
+{
+ rect = r;
+}
+
+/*!
+ \reimp
+*/
+void QWidgetItem::setGeometry(const QRect &rect)
+{
+ if (isEmpty())
+ return;
+
+ QRect r = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? fromLayoutItemRect(wid->d_func(), rect)
+ : rect;
+ const QSize widgetRectSurplus = r.size() - rect.size();
+
+ /*
+ For historical reasons, this code is done using widget rect
+ coordinates, not layout item rect coordinates. However,
+ QWidgetItem's sizeHint(), maximumSize(), and heightForWidth()
+ all work in terms of layout item rect coordinates, so we have to
+ add or subtract widgetRectSurplus here and there. The code could
+ be much simpler if we did everything using layout item rect
+ coordinates and did the conversion right before the call to
+ QWidget::setGeometry().
+ */
+
+ QSize s = r.size().boundedTo(maximumSize() + widgetRectSurplus);
+ int x = r.x();
+ int y = r.y();
+ if (align & (Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask)) {
+ QSize pref(sizeHint());
+ QSizePolicy sp = wid->sizePolicy();
+ if (sp.horizontalPolicy() == QSizePolicy::Ignored)
+ pref.setWidth(wid->sizeHint().expandedTo(wid->minimumSize()).width());
+ if (sp.verticalPolicy() == QSizePolicy::Ignored)
+ pref.setHeight(wid->sizeHint().expandedTo(wid->minimumSize()).height());
+ pref += widgetRectSurplus;
+ if (align & Qt::AlignHorizontal_Mask)
+ s.setWidth(qMin(s.width(), pref.width()));
+ if (align & Qt::AlignVertical_Mask) {
+ if (hasHeightForWidth())
+ s.setHeight(qMin(s.height(),
+ heightForWidth(s.width() - widgetRectSurplus.width())
+ + widgetRectSurplus.height()));
+ else
+ s.setHeight(qMin(s.height(), pref.height()));
+ }
+ }
+ Qt::Alignment alignHoriz = QStyle::visualAlignment(wid->layoutDirection(), align);
+ if (alignHoriz & Qt::AlignRight)
+ x = x + (r.width() - s.width());
+ else if (!(alignHoriz & Qt::AlignLeft))
+ x = x + (r.width() - s.width()) / 2;
+
+ if (align & Qt::AlignBottom)
+ y = y + (r.height() - s.height());
+ else if (!(align & Qt::AlignTop))
+ y = y + (r.height() - s.height()) / 2;
+
+ wid->setGeometry(x, y, s.width(), s.height());
+}
+
+/*!
+ \reimp
+*/
+QRect QSpacerItem::geometry() const
+{
+ return rect;
+}
+
+/*!
+ \reimp
+*/
+QRect QWidgetItem::geometry() const
+{
+ return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemRect(wid->d_func(), wid->geometry())
+ : wid->geometry();
+}
+
+
+/*!
+ \reimp
+*/
+bool QWidgetItem::hasHeightForWidth() const
+{
+ if (isEmpty())
+ return false;
+ if (wid->layout())
+ return wid->layout()->hasHeightForWidth();
+ return wid->sizePolicy().hasHeightForWidth();
+}
+
+/*!
+ \reimp
+*/
+int QWidgetItem::heightForWidth(int w) const
+{
+ if (isEmpty())
+ return -1;
+
+ w = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? fromLayoutItemSize(wid->d_func(), QSize(w, 0)).width()
+ : w;
+
+ int hfw;
+ if (wid->layout())
+ hfw = wid->layout()->totalHeightForWidth(w);
+ else
+ hfw = wid->heightForWidth(w);
+
+ if (hfw > wid->maximumHeight())
+ hfw = wid->maximumHeight();
+ if (hfw < wid->minimumHeight())
+ hfw = wid->minimumHeight();
+
+ hfw = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemSize(wid->d_func(), QSize(0, hfw)).height()
+ : hfw;
+
+ if (hfw < 0)
+ hfw = 0;
+ return hfw;
+}
+
+/*!
+ \reimp
+*/
+Qt::Orientations QSpacerItem::expandingDirections() const
+{
+ return sizeP.expandingDirections();
+}
+
+/*!
+ \reimp
+*/
+Qt::Orientations QWidgetItem::expandingDirections() const
+{
+ if (isEmpty())
+ return Qt::Orientations(0);
+
+ Qt::Orientations e = wid->sizePolicy().expandingDirections();
+ /*
+ ### Qt 4.0:
+ If the layout is expanding, we make the widget expanding, even if
+ its own size policy isn't expanding. This behavior should be
+ reconsidered.
+ */
+ if (wid->layout()) {
+ if (wid->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag
+ && (wid->layout()->expandingDirections() & Qt::Horizontal))
+ e |= Qt::Horizontal;
+ if (wid->sizePolicy().verticalPolicy() & QSizePolicy::GrowFlag
+ && (wid->layout()->expandingDirections() & Qt::Vertical))
+ e |= Qt::Vertical;
+ }
+
+ if (align & Qt::AlignHorizontal_Mask)
+ e &= ~Qt::Horizontal;
+ if (align & Qt::AlignVertical_Mask)
+ e &= ~Qt::Vertical;
+ return e;
+}
+
+/*!
+ \reimp
+*/
+QSize QSpacerItem::minimumSize() const
+{
+ return QSize(sizeP.horizontalPolicy() & QSizePolicy::ShrinkFlag ? 0 : width,
+ sizeP.verticalPolicy() & QSizePolicy::ShrinkFlag ? 0 : height);
+}
+
+/*!
+ \reimp
+*/
+QSize QWidgetItem::minimumSize() const
+{
+ if (isEmpty())
+ return QSize(0, 0);
+ return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemSize(wid->d_func(), qSmartMinSize(this))
+ : qSmartMinSize(this);
+}
+
+/*!
+ \reimp
+*/
+QSize QSpacerItem::maximumSize() const
+{
+ return QSize(sizeP.horizontalPolicy() & QSizePolicy::GrowFlag ? QLAYOUTSIZE_MAX : width,
+ sizeP.verticalPolicy() & QSizePolicy::GrowFlag ? QLAYOUTSIZE_MAX : height);
+}
+
+/*!
+ \reimp
+*/
+QSize QWidgetItem::maximumSize() const
+{
+ if (isEmpty()) {
+ return QSize(0, 0);
+ } else {
+ return !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemSize(wid->d_func(), qSmartMaxSize(this, align))
+ : qSmartMaxSize(this, align);
+ }
+}
+
+/*!
+ \reimp
+*/
+QSize QSpacerItem::sizeHint() const
+{
+ return QSize(width, height);
+}
+
+/*!
+ \reimp
+*/
+QSize QWidgetItem::sizeHint() const
+{
+ QSize s(0, 0);
+ if (!isEmpty()) {
+ s = wid->sizeHint().expandedTo(wid->minimumSizeHint());
+ s = s.boundedTo(wid->maximumSize())
+ .expandedTo(wid->minimumSize());
+ s = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect)
+ ? toLayoutItemSize(wid->d_func(), s)
+ : s;
+
+ if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
+ s.setWidth(0);
+ if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
+ s.setHeight(0);
+ }
+ return s;
+}
+
+/*!
+ Returns true.
+*/
+bool QSpacerItem::isEmpty() const
+{
+ return true;
+}
+
+/*!
+ Returns true if the widget is hidden; otherwise returns false.
+
+ \sa QWidget::isHidden()
+*/
+bool QWidgetItem::isEmpty() const
+{
+ return wid->isHidden() || wid->isWindow();
+}
+
+/*!
+ \class QWidgetItemV2
+ \internal
+*/
+
+inline bool QWidgetItemV2::useSizeCache() const
+{
+ return wid->d_func()->widgetItem == this;
+}
+
+void QWidgetItemV2::updateCacheIfNecessary() const
+{
+ if (q_cachedMinimumSize.width() != Dirty)
+ return;
+
+ const QSize sizeHint(wid->sizeHint());
+ const QSize minimumSizeHint(wid->minimumSizeHint());
+ const QSize minimumSize(wid->minimumSize());
+ const QSize maximumSize(wid->maximumSize());
+ const QSizePolicy sizePolicy(wid->sizePolicy());
+ const QSize expandedSizeHint(sizeHint.expandedTo(minimumSizeHint));
+
+ const QSize smartMinSize(qSmartMinSize(sizeHint, minimumSizeHint, minimumSize, maximumSize, sizePolicy));
+ const QSize smartMaxSize(qSmartMaxSize(expandedSizeHint, minimumSize, maximumSize, sizePolicy, align));
+
+ const bool useLayoutItemRect = !wid->testAttribute(Qt::WA_LayoutUsesWidgetRect);
+
+ q_cachedMinimumSize = useLayoutItemRect
+ ? toLayoutItemSize(wid->d_func(), smartMinSize)
+ : smartMinSize;
+
+ q_cachedSizeHint = expandedSizeHint;
+ q_cachedSizeHint = q_cachedSizeHint.boundedTo(maximumSize)
+ .expandedTo(minimumSize);
+ q_cachedSizeHint = useLayoutItemRect
+ ? toLayoutItemSize(wid->d_func(), q_cachedSizeHint)
+ : q_cachedSizeHint;
+
+ if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
+ q_cachedSizeHint.setWidth(0);
+ if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
+ q_cachedSizeHint.setHeight(0);
+
+ q_cachedMaximumSize = useLayoutItemRect
+ ? toLayoutItemSize(wid->d_func(), smartMaxSize)
+ : smartMaxSize;
+}
+
+QWidgetItemV2::QWidgetItemV2(QWidget *widget)
+ : QWidgetItem(widget),
+ q_cachedMinimumSize(Dirty, Dirty),
+ q_cachedSizeHint(Dirty, Dirty),
+ q_cachedMaximumSize(Dirty, Dirty),
+ q_firstCachedHfw(0),
+ q_hfwCacheSize(0),
+ d(0)
+{
+ QWidgetPrivate *wd = wid->d_func();
+ if (!wd->widgetItem)
+ wd->widgetItem = this;
+}
+
+QWidgetItemV2::~QWidgetItemV2()
+{
+ if (wid) {
+ QWidgetPrivate *wd = wid->d_func();
+ if (wd->widgetItem == this)
+ wd->widgetItem = 0;
+ }
+}
+
+QSize QWidgetItemV2::sizeHint() const
+{
+ if (isEmpty())
+ return QSize(0, 0);
+
+ if (useSizeCache()) {
+ updateCacheIfNecessary();
+ return q_cachedSizeHint;
+ } else {
+ return QWidgetItem::sizeHint();
+ }
+}
+
+QSize QWidgetItemV2::minimumSize() const
+{
+ if (isEmpty())
+ return QSize(0, 0);
+
+ if (useSizeCache()) {
+ updateCacheIfNecessary();
+ return q_cachedMinimumSize;
+ } else {
+ return QWidgetItem::minimumSize();
+ }
+}
+
+QSize QWidgetItemV2::maximumSize() const
+{
+ if (isEmpty())
+ return QSize(0, 0);
+
+ if (useSizeCache()) {
+ updateCacheIfNecessary();
+ return q_cachedMaximumSize;
+ } else {
+ return QWidgetItem::maximumSize();
+ }
+}
+
+/*
+ The height-for-width cache is organized as a circular buffer. The entries
+
+ q_hfwCachedHfws[q_firstCachedHfw],
+ ...,
+ q_hfwCachedHfws[(q_firstCachedHfw + q_hfwCacheSize - 1) % HfwCacheMaxSize]
+
+ contain the last cached values. When the cache is full, the first entry to
+ be erased is the entry before q_hfwCachedHfws[q_firstCachedHfw]. When
+ values are looked up, we try to move q_firstCachedHfw to point to that new
+ entry (unless the cache is not full, in which case it would leave the cache
+ in a broken state), so that the most recently used entry is also the last
+ to be erased.
+*/
+
+int QWidgetItemV2::heightForWidth(int width) const
+{
+ if (isEmpty())
+ return -1;
+
+ for (int i = 0; i < q_hfwCacheSize; ++i) {
+ int offset = q_firstCachedHfw + i;
+ const QSize &size = q_cachedHfws[offset % HfwCacheMaxSize];
+ if (size.width() == width) {
+ if (q_hfwCacheSize == HfwCacheMaxSize)
+ q_firstCachedHfw = offset;
+ return size.height();
+ }
+ }
+
+ if (q_hfwCacheSize < HfwCacheMaxSize)
+ ++q_hfwCacheSize;
+ q_firstCachedHfw = (q_firstCachedHfw + HfwCacheMaxSize - 1) % HfwCacheMaxSize;
+
+ int height = QWidgetItem::heightForWidth(width);
+ q_cachedHfws[q_firstCachedHfw] = QSize(width, height);
+ return height;
+}
+
+QT_END_NAMESPACE