diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:34:13 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:34:13 (GMT) |
commit | 67ad0519fd165acee4a4d2a94fa502e9e4847bd0 (patch) | |
tree | 1dbf50b3dff8d5ca7e9344733968c72704eb15ff /src/gui/kernel/qlayoutitem.cpp | |
download | Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.zip Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.gz Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.bz2 |
Long live Qt!
Diffstat (limited to 'src/gui/kernel/qlayoutitem.cpp')
-rw-r--r-- | src/gui/kernel/qlayoutitem.cpp | 837 |
1 files changed, 837 insertions, 0 deletions
diff --git a/src/gui/kernel/qlayoutitem.cpp b/src/gui/kernel/qlayoutitem.cpp new file mode 100644 index 0000000..0fd73b8 --- /dev/null +++ b/src/gui/kernel/qlayoutitem.cpp @@ -0,0 +1,837 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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 priv->fromOrToLayoutItemRect(rect, -1); +} + +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 priv->fromOrToLayoutItemRect(rect, +1); +} + +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 appearance + \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://doc.trolltech.com/qq/qq04-height-for-width.html}{Trading + Height for Width}. + + \sa QLayout +*/ + +/*! + \class QSpacerItem + \ingroup appearance + \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 appearance + \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 |