--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2016 Ivailo Monev
+**
+** This file is part of the test suite of the Katie Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+**
+** GNU Lesser General Public License Usage
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QBoxLayout : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QBoxLayout();
+ virtual ~tst_QBoxLayout();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void insertSpacerItem();
+ void insertLayout();
+ void sizeHint();
+ void sizeConstraints();
+ void setGeometry();
+ void setStyleShouldChangeSpacing();
+
+ void testLayoutEngine_data();
+ void testLayoutEngine();
+
+ void taskQTBUG_7103_minMaxWidthNotRespected();
+ void taskQTBUG_27420_takeAtShouldUnparentLayout();
+};
+
+class CustomLayoutStyle : public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ CustomLayoutStyle() : QWindowsStyle()
+ {
+ hspacing = 5;
+ vspacing = 10;
+ }
+
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0,
+ const QWidget * widget = 0 ) const;
+
+ int hspacing;
+ int vspacing;
+};
+
+int CustomLayoutStyle::pixelMetric(PixelMetric metric, const QStyleOption * option /*= 0*/,
+ const QWidget * widget /*= 0*/ ) const
+{
+ switch (metric) {
+ case PM_LayoutLeftMargin:
+ return 0;
+ case PM_LayoutTopMargin:
+ return 3;
+ case PM_LayoutRightMargin:
+ return 6;
+ case PM_LayoutBottomMargin:
+ return 9;
+ case PM_LayoutHorizontalSpacing:
+ return hspacing;
+ case PM_LayoutVerticalSpacing:
+ return vspacing;
+ default:
+ break;
+ }
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+}
+
+
+tst_QBoxLayout::tst_QBoxLayout()
+{
+}
+
+tst_QBoxLayout::~tst_QBoxLayout()
+{
+}
+
+void tst_QBoxLayout::initTestCase()
+{
+}
+
+void tst_QBoxLayout::cleanupTestCase()
+{
+}
+
+void tst_QBoxLayout::init()
+{
+}
+
+void tst_QBoxLayout::cleanup()
+{
+}
+
+void tst_QBoxLayout::insertSpacerItem()
+{
+ QWidget *window = new QWidget;
+
+ QSpacerItem *spacer1 = new QSpacerItem(20, 10, QSizePolicy::Expanding, QSizePolicy::Expanding);
+ QSpacerItem *spacer2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ QBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(new QLineEdit("Foooooooooooooooooooooooooo"));
+ layout->addSpacerItem(spacer1);
+ layout->addWidget(new QLineEdit("Baaaaaaaaaaaaaaaaaaaaaaaaar"));
+ layout->insertSpacerItem(0, spacer2);
+ window->setLayout(layout);
+
+ QVERIFY(layout->itemAt(0) == spacer2);
+ QVERIFY(layout->itemAt(2) == spacer1);
+
+ window->show();
+}
+
+void tst_QBoxLayout::insertLayout()
+{
+ QWidget *window = new QWidget;
+ QVBoxLayout *vbox = new QVBoxLayout(window);
+ QVBoxLayout *dummyParentLayout = new QVBoxLayout;
+ QHBoxLayout *subLayout = new QHBoxLayout;
+ dummyParentLayout->addLayout(subLayout);
+ QCOMPARE(subLayout->parent(), dummyParentLayout);
+ QCOMPARE(dummyParentLayout->count(), 1);
+
+ // add subLayout to another layout
+ QTest::ignoreMessage(QtWarningMsg, "QLayout::addChildLayout: layout \"\" already has a parent");
+ vbox->addLayout(subLayout);
+ QCOMPARE((subLayout->parent() == vbox), (vbox->count() == 1));
+
+ delete dummyParentLayout;
+ delete window;
+}
+
+
+void tst_QBoxLayout::sizeHint()
+{
+ QWidget *window = new QWidget;
+ QHBoxLayout *lay1 = new QHBoxLayout;
+ QHBoxLayout *lay2 = new QHBoxLayout;
+ QLabel *label = new QLabel("widget twooooooooooooooooooooooooooooooooooooooooooooooooooooooo");
+ lay2->addWidget(label);
+ lay1->addLayout(lay2);
+ window->setLayout(lay1);
+ window->show();
+ label->setText("foooooooo baaaaaaar");
+ QSize sh = lay1->sizeHint();
+ QApplication::processEvents();
+ // Note that this is not strictly required behaviour - actually
+ // the preferred behaviour would be that sizeHint returns
+ // the same value regardless of what's lying in the event queue.
+ // (i.e. we would check for equality here instead)
+ QVERIFY(lay1->sizeHint() != sh);
+}
+
+void tst_QBoxLayout::sizeConstraints()
+{
+ QWidget *window = new QWidget;
+ QHBoxLayout *lay = new QHBoxLayout;
+ lay->addWidget(new QLabel("foooooooooooooooooooooooooooooooooooo"));
+ lay->addWidget(new QLabel("baaaaaaaaaaaaaaaaaaaaaaaaaaaaaar"));
+ lay->setSizeConstraint(QLayout::SetFixedSize);
+ window->setLayout(lay);
+ window->show();
+ QApplication::processEvents();
+ QSize sh = window->sizeHint();
+ lay->takeAt(1);
+ QVERIFY(sh.width() >= window->sizeHint().width() &&
+ sh.height() >= window->sizeHint().height());
+
+}
+
+void tst_QBoxLayout::setGeometry()
+{
+ QWidget toplevel;
+ QWidget w(&toplevel);
+ QVBoxLayout *lay = new QVBoxLayout;
+ lay->setMargin(0);
+ lay->setSpacing(0);
+ QHBoxLayout *lay2 = new QHBoxLayout;
+ QDial *dial = new QDial;
+ lay2->addWidget(dial);
+ lay2->setAlignment(Qt::AlignTop);
+ lay2->setAlignment(Qt::AlignRight);
+ lay->addLayout(lay2);
+ w.setLayout(lay);
+ toplevel.show();
+
+ QRect newGeom(0, 0, 70, 70);
+ lay2->setGeometry(newGeom);
+ QVERIFY2(newGeom.contains(dial->geometry()), "dial->geometry() should be smaller and within newGeom");
+}
+
+void tst_QBoxLayout::setStyleShouldChangeSpacing()
+{
+
+ QWidget *window = new QWidget;
+ QHBoxLayout *hbox = new QHBoxLayout(window);
+ QPushButton *pb1 = new QPushButton(tr("The spacing between this"));
+ QPushButton *pb2 = new QPushButton(tr("and this button should depend on the style of the parent widget"));;
+ pb1->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ pb2->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ hbox->addWidget(pb1);
+ hbox->addWidget(pb2);
+ CustomLayoutStyle *style1 = new CustomLayoutStyle;
+ style1->hspacing = 6;
+ window->setStyle(style1);
+ window->show();
+
+ QTest::qWait(100);
+ int spacing = pb2->geometry().left() - pb1->geometry().right() - 1;
+ QCOMPARE(spacing, 6);
+
+ CustomLayoutStyle *style2 = new CustomLayoutStyle();
+ style2->hspacing = 10;
+ window->setStyle(style2);
+ QTest::qWait(100);
+ spacing = pb2->geometry().left() - pb1->geometry().right() - 1;
+ QCOMPARE(spacing, 10);
+
+ delete window;
+ delete style1;
+ delete style2;
+}
+
+void tst_QBoxLayout::taskQTBUG_7103_minMaxWidthNotRespected()
+{
+ QLabel *label = new QLabel("Qt uses standard C++, but makes extensive use of the C pre-processor to enrich the language. Qt can also be used in several other programming languages via language bindings. It runs on all major platforms, and has extensive internationalization support. Non-GUI features include SQL database access, XML parsing, thread management, network support and a unified cross-platform API for file handling.");
+ label->setWordWrap(true);
+ label->setFixedWidth(200);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(label);
+ layout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding));
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ int height = label->height();
+
+ QRect g = widget.geometry();
+ g.setWidth(600);
+ widget.setGeometry(g);
+
+ QTest::qWait(50);
+
+ QCOMPARE(label->height(), height);
+}
+
+void tst_QBoxLayout::taskQTBUG_27420_takeAtShouldUnparentLayout()
+{
+ QSharedPointer<QHBoxLayout> outer(new QHBoxLayout);
+ QPointer<QVBoxLayout> inner = new QVBoxLayout;
+
+ outer->addLayout(inner);
+ QCOMPARE(outer->count(), 1);
+ QCOMPARE(inner->parent(), outer.data());
+
+ QLayoutItem *item = outer->takeAt(0);
+ QCOMPARE(item->layout(), inner.data());
+ QVERIFY(!item->layout()->parent());
+
+ outer.clear();
+
+ if (inner)
+ delete item; // success: a taken item/layout should not be deleted when the old parent is deleted
+ else
+ QVERIFY(!inner.isNull());
+}
+
+
+struct Descr
+{
+ Descr(int min, int sh, int max = -1, bool exp= false, int _stretch = 0, bool _empty = false)
+ :minimumSize(min), sizeHint(sh), maximumSize(max < 0 ? QLAYOUTSIZE_MAX : max),
+ expanding(exp), stretch(_stretch), empty(_empty)
+ {}
+
+ int minimumSize;
+ int sizeHint;
+ int maximumSize;
+ bool expanding;
+
+ int stretch;
+
+ bool empty;
+};
+
+
+typedef QList<Descr> DescrList;
+Q_DECLARE_METATYPE(DescrList);
+
+typedef QList<int> SizeList;
+Q_DECLARE_METATYPE(SizeList);
+
+typedef QList<int> PosList;
+
+
+
+class LayoutItem : public QLayoutItem
+{
+public:
+ LayoutItem(const Descr &descr) :m_descr(descr) {}
+
+ QSize sizeHint() const { return QSize(m_descr.sizeHint, 100); }
+ QSize minimumSize() const { return QSize(m_descr.minimumSize, 0); }
+ QSize maximumSize() const { return QSize(m_descr.maximumSize, QLAYOUTSIZE_MAX); }
+ Qt::Orientations expandingDirections() const
+ { return m_descr.expanding ? Qt::Horizontal : Qt::Orientations(0); }
+ void setGeometry(const QRect &r) { m_pos = r.x(); m_size = r.width();}
+ QRect geometry() const { return QRect(m_pos, 0, m_size, 100); }
+ bool isEmpty() const { return m_descr.empty; }
+
+private:
+ Descr m_descr;
+ int m_pos;
+ int m_size;
+};
+
+void tst_QBoxLayout::testLayoutEngine_data()
+{
+ // (int min, int sh, int max = -1, bool exp= false, int _stretch = 0, bool _empty = false)
+ QTest::addColumn<DescrList>("itemDescriptions");
+ QTest::addColumn<int>("size");
+ QTest::addColumn<int>("spacing");
+ QTest::addColumn<PosList>("expectedPositions");
+ QTest::addColumn<SizeList>("expectedSizes");
+
+ QTest::newRow("Just one")
+ << (DescrList() << Descr(0, 100))
+ << 200
+ << 0
+ << (PosList() << 0)
+ << (SizeList() << 200);
+
+ QTest::newRow("Two non-exp")
+ << (DescrList() << Descr(0, 100) << Descr(0,100))
+ << 400
+ << 0
+ << (PosList() << 0 << 200)
+ << (SizeList() << 200 << 200);
+
+ QTest::newRow("Exp + non-exp")
+ << (DescrList() << Descr(0, 100, -1, true) << Descr(0,100))
+ << 400
+ << 0
+ << (PosList() << 0 << 300)
+ << (SizeList() << 300 << 100);
+
+
+ QTest::newRow("Stretch")
+ << (DescrList() << Descr(0, 100, -1, false, 1) << Descr(0,100, -1, false, 2))
+ << 300
+ << 0
+ << (PosList() << 0 << 100)
+ << (SizeList() << 100 << 200);
+
+
+ QTest::newRow("Spacing")
+ << (DescrList() << Descr(0, 100) << Descr(0,100))
+ << 400
+ << 10
+ << (PosList() << 0 << 205)
+ << (SizeList() << 195 << 195);
+
+
+ QTest::newRow("Less than minimum")
+ << (DescrList() << Descr(100, 100, 100, false) << Descr(50, 100, 100, false))
+ << 100
+ << 0
+ << (PosList() << 0 << 50)
+ << (SizeList() << 50 << 50);
+
+
+ QTest::newRow("Less than sizehint")
+ << (DescrList() << Descr(100, 200, 100, false) << Descr(50, 200, 100, false))
+ << 200
+ << 0
+ << (PosList() << 0 << 100)
+ << (SizeList() << 100 << 100);
+
+ QTest::newRow("Too much space")
+ << (DescrList() << Descr(0, 100, 100, false) << Descr(0, 100, 100, false))
+ << 500
+ << 0
+ << (PosList() << 100 << 300)
+ << (SizeList() << 100 << 100);
+
+ QTest::newRow("Empty")
+ << (DescrList() << Descr(0, 100, 100) << Descr(0,0,-1, false, 0, true) << Descr(0, 100, 100) )
+ << 500
+ << 0
+ << (PosList() << 100 << 300 << 300)
+ << (SizeList() << 100 << 0 << 100);
+
+ QTest::newRow("QTBUG-33104")
+ << (DescrList() << Descr(11, 75, 75, true) << Descr(75, 75))
+ << 200
+ << 0
+ << (PosList() << 0 << 75)
+ << (SizeList() << 75 << 125);
+
+ QTest::newRow("Expanding with maximumSize")
+ << (DescrList() << Descr(11, 75, 100, true) << Descr(75, 75))
+ << 200
+ << 0
+ << (PosList() << 0 << 100)
+ << (SizeList() << 100 << 100);
+
+ QTest::newRow("Stretch with maximumSize")
+ << (DescrList() << Descr(11, 75, 100, false, 1) << Descr(75, 75))
+ << 200
+ << 0
+ << (PosList() << 0 << 100)
+ << (SizeList() << 100 << 100);
+
+ QTest::newRow("Stretch with maximumSize last")
+ << (DescrList() << Descr(75, 75) << Descr(11, 75, 100, false, 1))
+ << 200
+ << 0
+ << (PosList() << 0 << 100)
+ << (SizeList() << 100 << 100);
+}
+
+void tst_QBoxLayout::testLayoutEngine()
+{
+ QFETCH(DescrList, itemDescriptions);
+ QFETCH(int, size);
+ QFETCH(int, spacing);
+ QFETCH(PosList, expectedPositions);
+ QFETCH(SizeList, expectedSizes);
+
+ QHBoxLayout box;
+ box.setSpacing(spacing);
+ int i;
+ for (i = 0; i < itemDescriptions.count(); ++i) {
+ Descr descr = itemDescriptions.at(i);
+ LayoutItem *li = new LayoutItem(descr);
+ box.addItem(li);
+ box.setStretch(i, descr.stretch);
+ }
+ box.setGeometry(QRect(0,0,size,100));
+ for (i = 0; i < expectedSizes.count(); ++i) {
+ int xSize = expectedSizes.at(i);
+ int xPos = expectedPositions.at(i);
+ QLayoutItem *item = box.itemAt(i);
+ QCOMPARE(item->geometry().width(), xSize);
+ QCOMPARE(item->geometry().x(), xPos);
+ }
+}
+
+QTEST_MAIN(tst_QBoxLayout)
+
+#include "moc_tst_qboxlayout.cpp"