"QWidget",
"QWidgetAction",
"QWidgetData",
+ "QWidgetItemV2",
"QWidgetMapper",
"QWidgetSet",
"QWindowsStyle",
// ------------------ QDesignerWidgetItem
QDesignerWidgetItem::QDesignerWidgetItem(const QLayout *containingLayout, QWidget *w, Qt::Orientations o) :
- QWidgetItem(w),
+ QWidgetItemV2(w),
m_orientations(o),
m_nonLaidOutMinSize(w->minimumSizeHint()),
m_nonLaidOutSizeHint(w->sizeHint()),
QSize QDesignerWidgetItem::minimumSize() const
{
// Just track the size in case we are laid-out or stretched.
- const QSize baseMinSize = QWidgetItem::minimumSize();
+ const QSize baseMinSize = QWidgetItemV2::minimumSize();
QWidget * w = constWidget();
if (w->layout() || subjectToStretch(containingLayout(), w)) {
m_nonLaidOutMinSize = baseMinSize;
QSize QDesignerWidgetItem::sizeHint() const
{
// Just track the size in case we are laid-out or stretched.
- const QSize baseSizeHint = QWidgetItem::sizeHint();
+ const QSize baseSizeHint = QWidgetItemV2::sizeHint();
QWidget * w = constWidget();
if (w->layout() || subjectToStretch(containingLayout(), w)) {
m_nonLaidOutSizeHint = baseSizeHint;
// and destroyed slots as Designer will for example re-create grid layouts to
// shrink them.
-class QDESIGNER_SHARED_EXPORT QDesignerWidgetItem : public QObject, public QWidgetItem {
+class QDESIGNER_SHARED_EXPORT QDesignerWidgetItem : public QObject, public QWidgetItemV2 {
Q_DISABLE_COPY(QDesignerWidgetItem)
Q_OBJECT
public:
QMessageBox
QWidgetAction
QWidgetData
+ QWidgetItemV2
QWidgetMapper
QWidgetSet
QWindowsStyle
if (widgetItemFactoryMethod)
if (QWidgetItem *wi = (*widgetItemFactoryMethod)(layout, widget))
return wi;
- return new QWidgetItem(widget);
+ return new QWidgetItemV2(widget);
}
QSpacerItem *QLayoutPrivate::createSpacerItem(const QLayout *layout, int w, int h, QSizePolicy::Policy hPolicy, QSizePolicy::Policy vPolicy)
return new QSpacerItem(w, h, hPolicy, vPolicy);
}
-
-
/*!
\fn void QLayout::addItem(QLayoutItem *item)
return wid->sizePolicy().controlType();
}
+/*!
+ \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
int heightForWidth(int) const;
QSizePolicy::ControlTypes controlTypes() const;
+
protected:
QWidget *wid;
};
+class Q_GUI_EXPORT QWidgetItemV2 : public QWidgetItem
+{
+public:
+ explicit QWidgetItemV2(QWidget *widget);
+ ~QWidgetItemV2();
+
+ QSize sizeHint() const;
+ QSize minimumSize() const;
+ QSize maximumSize() const;
+ int heightForWidth(int width) const;
+
+private:
+ enum { Dirty = -123, HfwCacheMaxSize = 3 };
+
+ inline bool useSizeCache() const;
+ void updateCacheIfNecessary() const;
+ inline void invalidateSizeCache() {
+ q_cachedMinimumSize.setWidth(Dirty);
+ q_hfwCacheSize = 0;
+ }
+
+ mutable QSize q_cachedMinimumSize;
+ mutable QSize q_cachedSizeHint;
+ mutable QSize q_cachedMaximumSize;
+ mutable QSize q_cachedHfws[HfwCacheMaxSize];
+ mutable short q_firstCachedHfw;
+ mutable short q_hfwCacheSize;
+ void *d;
+
+ friend class QWidgetPrivate;
+
+ Q_DISABLE_COPY(QWidgetItemV2)
+};
+
QT_END_NAMESPACE
QT_END_HEADER
, layout(0)
, needsFlush(0)
, redirectDev(0)
+ , widgetItem(0)
, extraPaintEngine(0)
, polished(0)
, graphicsEffect(0)
QWidgetPrivate::~QWidgetPrivate()
{
+ if (widgetItem)
+ widgetItem->wid = 0;
+
if (extra)
deleteExtra();
void QWidgetPrivate::updateGeometry_helper(bool forceUpdate)
{
Q_Q(QWidget);
+ if (widgetItem)
+ widgetItem->invalidateSizeCache();
if (forceUpdate || !extra || extra->minw != extra->maxw || extra->minh != extra->maxh) {
QWidget *parent;
if (!q->isWindow() && !q->isHidden() && (parent = q->parentWidget())) {
friend class QETWidget;
friend class QLayout;
friend class QWidgetItem;
+ friend class QWidgetItemV2;
friend class QX11PaintEngine;
friend class QShortcutPrivate;
friend class QShortcutMap;
class QPixmap;
class QWidgetBackingStore;
class QGraphicsProxyWidget;
-
+class QWidgetItemV2;
class QStyle;
class Q_AUTOTEST_EXPORT QWidgetBackingStoreTracker
QLayout *layout;
QRegion *needsFlush;
QPaintDevice *redirectDev;
+ QWidgetItemV2 *widgetItem;
QPaintEngine *extraPaintEngine;
mutable const QMetaObject *polished;
QGraphicsEffect *graphicsEffect;
if (w != 0) {
addChildWidget(w);
- item_list[r] = new QWidgetItem(w);
+ item_list[r] = new QWidgetItemV2(w);
w->show();
} else {
item_list[r] = 0;
deleteCentralWidgetItem();
if (widget != 0)
- item = new QWidgetItem(widget);
+ item = new QWidgetItemV2(widget);
#ifndef QT_NO_DOCKWIDGET
dockAreaLayout.centralWidgetItem = item;
if (sb)
addChildWidget(sb);
delete statusbar;
- statusbar = sb ? new QWidgetItem(sb) : 0;
+ statusbar = sb ? new QWidgetItemV2(sb) : 0;
invalidate();
}
#endif // QT_NO_STATUSBAR
QLayoutItem *QToolBarAreaLayoutInfo::insertToolBar(QToolBar *before, QToolBar *toolBar)
{
toolBar->setOrientation(o);
- QLayoutItem *item = new QWidgetItem(toolBar);
+ QLayoutItem *item = new QWidgetItemV2(toolBar);
insertItem(before, item);
return item;
}
}
if (applyingLayout) {
- item.widgetItem = new QWidgetItem(toolBar);
+ item.widgetItem = new QWidgetItemV2(toolBar);
toolBar->setOrientation(floating ? ((shown & 2) ? Qt::Vertical : Qt::Horizontal) : dock.o);
toolBar->setVisible(shown & 1);
toolBar->d_func()->setWindowState(floating, true, rect);
case DomLayoutItem::Widget: {
if (QWidget *w = create(ui_layoutItem->elementWidget(), parentWidget)) {
#ifdef QFORMINTERNAL_NAMESPACE // uilib
- QWidgetItem *item = new QWidgetItem(w);
+ QWidgetItem *item = new QWidgetItemV2(w);
#else // Within Designer: Use factory method that returns special items that refuse to shrink to 0,0
QWidgetItem *item = QLayoutPrivate::createWidgetItem(layout, w);
#endif