OSDN Git Service

partially revert 16e996daae8de32c8fef02d535c4de1d44ad338f
authorIvailo Monev <xakepa10@laimg.moc>
Sat, 15 Jun 2019 13:36:52 +0000 (13:36 +0000)
committerIvailo Monev <xakepa10@laimg.moc>
Sat, 15 Jun 2019 13:36:52 +0000 (13:36 +0000)
Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
14 files changed:
scripts/namefsck.py
src/designer/shared/qdesigner_widgetitem.cpp
src/designer/shared/qdesigner_widgetitem_p.h
src/gui/CMakeLists.txt
src/gui/kernel/qlayout.cpp
src/gui/kernel/qlayoutitem.cpp
src/gui/kernel/qlayoutitem.h
src/gui/kernel/qwidget.cpp
src/gui/kernel/qwidget.h
src/gui/kernel/qwidget_p.h
src/gui/widgets/qdockwidget.cpp
src/gui/widgets/qmainwindowlayout.cpp
src/gui/widgets/qtoolbararealayout.cpp
src/uitools/abstractformbuilder.cpp

index 2a63ad6..3c4c479 100755 (executable)
@@ -834,6 +834,7 @@ classlist = {
     "QWidget",
     "QWidgetAction",
     "QWidgetData",
+    "QWidgetItemV2",
     "QWidgetMapper",
     "QWidgetSet",
     "QWindowsStyle",
index c44f6aa..0f40b7b 100644 (file)
@@ -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;
index fd9c6e2..9be22d8 100644 (file)
@@ -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:
index 3df4aee..ddabe2a 100644 (file)
@@ -324,6 +324,7 @@ set(GUI_PUBLIC_HEADERS
     QMessageBox
     QWidgetAction
     QWidgetData
+    QWidgetItemV2
     QWidgetMapper
     QWidgetSet
     QWindowsStyle
index 05f2910..fbf9b4b 100644 (file)
@@ -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)
 
index bbb0a71..1ce693a 100644 (file)
@@ -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
 
 
index dde9051..f9db9d7 100644 (file)
@@ -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
index 05783e6..0a0d5cd 100644 (file)
@@ -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())) {
index 7f8e5e7..de56cfc 100644 (file)
@@ -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;
index 5ef09f8..566a4c9 100644 (file)
@@ -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;
index 96aac3f..8e154eb 100644 (file)
@@ -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;
index bb5d33c..79a4452 100644 (file)
@@ -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
index ecddd79..e345301 100644 (file)
@@ -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 QList<QToolBar*
             }
 
             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);
index 90feac7..29b0044 100644 (file)
@@ -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