Fix a regression with regards to hfw behavior in QStackedWidget
authorJan Arve Saether <jan-arve.saether@digia.com>
Wed, 10 Oct 2012 11:42:07 +0000 (13:42 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 10 Oct 2012 12:22:58 +0000 (14:22 +0200)
This is a regression because we made QStackedWidget actually
support heightForWidth in 4.8. This was done with change
4780f94e391b5e881497c5228661dead42c821fa.

The problem was that heightForWidth was not calculated correctly
because some of the pages were hidden. The hidden pages were
actually not contributing to the hfw of the QStackedWidget at all.
This again caused the QStackedWidget to change its heightForWidth()
value when the current tab changed, which again could cause "jumps"
in the UI when switching tabs (as demonstrated in the task).

The problem was that the patch relied on calling
QWidgetItem::heightForWidth(), and this function would return -1
if the widget was hidden. However, QWidget::heightForWidth() does
not have this magic and returns the proper hfw value regardless
of its visibility.

One could argue about the correctness of this patch, but since
QStackedLayout::sizeHint() disregards QWidgetItem::sizeHint() (it
asks the widget directly), we do the same in
QStackedLayoutHFW::heightForWidth() for consistency.

In addition, QStackedLayout enforces that only widgets can be added
to it, and you cannot add your own QLayoutItem subclasses to it:

  qWarning("QStackedLayout::addItem: Only widgets can be added");

Task-id: QTBUG-24758

Change-Id: I349cf8f4215e4581ea237ef773d53dcdf3db176b
Reviewed-by: Paul Olav Tvete <paul.tvete@digia.com>
src/widgets/kernel/qstackedlayout.cpp
tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp

index 003454c..2660e43 100644 (file)
@@ -502,9 +502,17 @@ int QStackedLayout::heightForWidth(int width) const
     int hfw = 0;
     for (int i = 0; i < n; ++i) {
         if (QLayoutItem *item = itemAt(i)) {
-            hfw = qMax(hfw, item->heightForWidth(width));
+            if (QWidget *w = item->widget())
+                /*
+                Note: Does not query the layout item, but bypasses it and asks the widget
+                directly. This is consistent with how QStackedLayout::sizeHint() is
+                implemented. This also avoids an issue where QWidgetItem::heightForWidth()
+                returns -1 if the widget is hidden.
+                */
+                hfw = qMax(hfw, w->heightForWidth(width));
         }
     }
+    hfw = qMax(hfw, minimumSize().height());
     return hfw;
 }
 
index 6756206..3a34897 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <QtTest/QtTest>
 #include <QLineEdit>
+#include <QLabel>
 #include <QStackedLayout>
 #include <qapplication.h>
 #include <qwidget.h>
@@ -68,6 +69,7 @@ private slots:
     void deleteCurrent();
     void removeWidget();
     void keepFocusAfterSetCurrent();
+    void heigthForWidth();
 
 private:
     QWidget *testWidget;
@@ -362,6 +364,36 @@ void tst_QStackedLayout::keepFocusAfterSetCurrent()
     QVERIFY(edit2->hasFakeEditFocus);
 }
 
+void tst_QStackedLayout::heigthForWidth()
+{
+    if (testWidget->layout()) delete testWidget->layout();
+    QStackedLayout *stackLayout = new QStackedLayout(testWidget);
+
+    QLabel *shortLabel = new QLabel("This is a short text.");
+    shortLabel->setWordWrap(true);
+    stackLayout->addWidget(shortLabel);
+
+    QLabel *longLabel = new QLabel("Write code once to target multiple platforms\n"
+                         "Qt allows you to write advanced applications and UIs once, "
+                         "and deploy them across desktop and embedded operating systems "
+                         "without rewriting the source code saving time and development cost.\n\n"
+                         "Create amazing user experiences\n"
+                         "Whether you prefer C++ or JavaScript, Qt provides the building blocks - "
+                         "a broad set of customizable widgets, graphics canvas, style engine "
+                         "and more that you need to build modern user interfaces. "
+                         "Incorporate 3D graphics, multimedia audio or video, visual effects, "
+                         "and animations to set your application apart from the competition.");
+
+    longLabel->setWordWrap(true);
+    stackLayout->addWidget(longLabel);
+    stackLayout->setCurrentIndex(0);
+    int hfw_index0 = stackLayout->heightForWidth(200);
+
+    stackLayout->setCurrentIndex(1);
+    QCOMPARE(stackLayout->heightForWidth(200), hfw_index0);
+
+}
+
 QTEST_MAIN(tst_QStackedLayout)
 #include "tst_qstackedlayout.moc"