From: Ivailo Monev Date: Sat, 15 Jun 2019 13:36:52 +0000 (+0000) Subject: partially revert 16e996daae8de32c8fef02d535c4de1d44ad338f X-Git-Tag: 4.12.0~5772 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=6d3fe9312c47aa09cceeb89feabae438ed55fdf6;p=kde%2FKatie.git partially revert 16e996daae8de32c8fef02d535c4de1d44ad338f Signed-off-by: Ivailo Monev --- diff --git a/scripts/namefsck.py b/scripts/namefsck.py index 2a63ad622..3c4c479d2 100755 --- a/scripts/namefsck.py +++ b/scripts/namefsck.py @@ -834,6 +834,7 @@ classlist = { "QWidget", "QWidgetAction", "QWidgetData", + "QWidgetItemV2", "QWidgetMapper", "QWidgetSet", "QWindowsStyle", diff --git a/src/designer/shared/qdesigner_widgetitem.cpp b/src/designer/shared/qdesigner_widgetitem.cpp index c44f6aa6d..0f40b7b63 100644 --- a/src/designer/shared/qdesigner_widgetitem.cpp +++ b/src/designer/shared/qdesigner_widgetitem.cpp @@ -115,7 +115,7 @@ namespace qdesigner_internal { // ------------------ 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()), @@ -146,7 +146,7 @@ void QDesignerWidgetItem::expand(QSize *s) const 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; @@ -162,7 +162,7 @@ QSize QDesignerWidgetItem::minimumSize() const 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; diff --git a/src/designer/shared/qdesigner_widgetitem_p.h b/src/designer/shared/qdesigner_widgetitem_p.h index fd9c6e279..9be22d893 100644 --- a/src/designer/shared/qdesigner_widgetitem_p.h +++ b/src/designer/shared/qdesigner_widgetitem_p.h @@ -71,7 +71,7 @@ namespace qdesigner_internal { // 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: diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 3df4aee29..ddabe2a0a 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -324,6 +324,7 @@ set(GUI_PUBLIC_HEADERS QMessageBox QWidgetAction QWidgetData + QWidgetItemV2 QWidgetMapper QWidgetSet QWindowsStyle diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp index 05f2910dc..fbf9b4b90 100644 --- a/src/gui/kernel/qlayout.cpp +++ b/src/gui/kernel/qlayout.cpp @@ -189,7 +189,7 @@ QWidgetItem *QLayoutPrivate::createWidgetItem(const QLayout *layout, QWidget *wi 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) @@ -200,8 +200,6 @@ QSpacerItem *QLayoutPrivate::createSpacerItem(const QLayout *layout, int w, int return new QSpacerItem(w, h, hPolicy, vPolicy); } - - /*! \fn void QLayout::addItem(QLayoutItem *item) diff --git a/src/gui/kernel/qlayoutitem.cpp b/src/gui/kernel/qlayoutitem.cpp index bbb0a7130..1ce693abc 100644 --- a/src/gui/kernel/qlayoutitem.cpp +++ b/src/gui/kernel/qlayoutitem.cpp @@ -675,6 +675,155 @@ QSizePolicy::ControlTypes QWidgetItem::controlTypes() const 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 diff --git a/src/gui/kernel/qlayoutitem.h b/src/gui/kernel/qlayoutitem.h index dde90517d..f9db9d75d 100644 --- a/src/gui/kernel/qlayoutitem.h +++ b/src/gui/kernel/qlayoutitem.h @@ -129,10 +129,45 @@ public: 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 diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 05783e6fc..0a0d5cdb4 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -204,6 +204,7 @@ QWidgetPrivate::QWidgetPrivate(int version) , layout(0) , needsFlush(0) , redirectDev(0) + , widgetItem(0) , extraPaintEngine(0) , polished(0) , graphicsEffect(0) @@ -251,6 +252,9 @@ QWidgetPrivate::QWidgetPrivate(int version) QWidgetPrivate::~QWidgetPrivate() { + if (widgetItem) + widgetItem->wid = 0; + if (extra) deleteExtra(); @@ -8725,6 +8729,8 @@ QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPoint &p, bool ignoreChil 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())) { diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 7f8e5e717..de56cfc48 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -635,6 +635,7 @@ private: friend class QETWidget; friend class QLayout; friend class QWidgetItem; + friend class QWidgetItemV2; friend class QX11PaintEngine; friend class QShortcutPrivate; friend class QShortcutMap; diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 5ef09f80a..566a4c9b1 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -73,7 +73,7 @@ class QPaintEngine; class QPixmap; class QWidgetBackingStore; class QGraphicsProxyWidget; - +class QWidgetItemV2; class QStyle; class Q_AUTOTEST_EXPORT QWidgetBackingStoreTracker @@ -555,6 +555,7 @@ public: QLayout *layout; QRegion *needsFlush; QPaintDevice *redirectDev; + QWidgetItemV2 *widgetItem; QPaintEngine *extraPaintEngine; mutable const QMetaObject *polished; QGraphicsEffect *graphicsEffect; diff --git a/src/gui/widgets/qdockwidget.cpp b/src/gui/widgets/qdockwidget.cpp index 96aac3faa..8e154eb8c 100644 --- a/src/gui/widgets/qdockwidget.cpp +++ b/src/gui/widgets/qdockwidget.cpp @@ -377,7 +377,7 @@ void QDockWidgetLayout::setWidgetForRole(Role r, QWidget *w) if (w != 0) { addChildWidget(w); - item_list[r] = new QWidgetItem(w); + item_list[r] = new QWidgetItemV2(w); w->show(); } else { item_list[r] = 0; diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp index bb5d33cc7..79a4452b3 100644 --- a/src/gui/widgets/qmainwindowlayout.cpp +++ b/src/gui/widgets/qmainwindowlayout.cpp @@ -369,7 +369,7 @@ void QMainWindowLayoutState::setCentralWidget(QWidget *widget) deleteCentralWidgetItem(); if (widget != 0) - item = new QWidgetItem(widget); + item = new QWidgetItemV2(widget); #ifndef QT_NO_DOCKWIDGET dockAreaLayout.centralWidgetItem = item; @@ -1594,7 +1594,7 @@ void QMainWindowLayout::setStatusBar(QStatusBar *sb) if (sb) addChildWidget(sb); delete statusbar; - statusbar = sb ? new QWidgetItem(sb) : 0; + statusbar = sb ? new QWidgetItemV2(sb) : 0; invalidate(); } #endif // QT_NO_STATUSBAR diff --git a/src/gui/widgets/qtoolbararealayout.cpp b/src/gui/widgets/qtoolbararealayout.cpp index ecddd799c..e345301e4 100644 --- a/src/gui/widgets/qtoolbararealayout.cpp +++ b/src/gui/widgets/qtoolbararealayout.cpp @@ -299,7 +299,7 @@ void QToolBarAreaLayoutInfo::fitLayout() 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; } @@ -1356,7 +1356,7 @@ bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QListsetOrientation(floating ? ((shown & 2) ? Qt::Vertical : Qt::Horizontal) : dock.o); toolBar->setVisible(shown & 1); toolBar->d_func()->setWindowState(floating, true, rect); diff --git a/src/uitools/abstractformbuilder.cpp b/src/uitools/abstractformbuilder.cpp index 90feac731..29b004431 100644 --- a/src/uitools/abstractformbuilder.cpp +++ b/src/uitools/abstractformbuilder.cpp @@ -879,7 +879,7 @@ QLayoutItem *QAbstractFormBuilder::create(DomLayoutItem *ui_layoutItem, QLayout 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