--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,693 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui>
+#include <math.h>
+
+//TESTED_CLASS=QGraphicsLayout
+//TESTED_FILES=
+
+class tst_QGraphicsLayout : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QGraphicsLayout();
+ virtual ~tst_QGraphicsLayout();
+
+private slots:
+ void sizeHints();
+ void compressLayoutRequest();
+ void automaticReparenting();
+ void verifyActivate();
+ void constructors();
+ void alternativeLayoutItems();
+ void ownership();
+};
+
+tst_QGraphicsLayout::tst_QGraphicsLayout()
+{
+}
+
+tst_QGraphicsLayout::~tst_QGraphicsLayout()
+{
+}
+
+void tst_QGraphicsLayout::sizeHints()
+{
+
+ QGraphicsView view;
+ QGraphicsScene scene;
+ QGraphicsWidget *window = new QGraphicsWidget();
+ scene.addItem(window);
+ QGraphicsLinearLayout *lout = new QGraphicsLinearLayout(window);
+ lout->setContentsMargins(0,0,0,0);
+ QGraphicsWidget *gw = new QGraphicsWidget(window);
+ gw->setMinimumSize(QSizeF(10,10));
+ gw->setPreferredSize(QSizeF(100,100));
+ gw->setMaximumSize(QSizeF(500,500));
+ lout->addItem(gw);
+ QCOMPARE(lout->effectiveSizeHint(Qt::MinimumSize), gw->effectiveSizeHint(Qt::MinimumSize));
+ QCOMPARE(lout->effectiveSizeHint(Qt::PreferredSize), gw->effectiveSizeHint(Qt::PreferredSize));
+ QCOMPARE(lout->effectiveSizeHint(Qt::MaximumSize), gw->effectiveSizeHint(Qt::MaximumSize));
+
+}
+
+class TestGraphicsWidget : public QGraphicsWidget {
+public:
+ TestGraphicsWidget(QGraphicsWidget *parent = 0) : QGraphicsWidget(parent)
+ { }
+
+ bool event(QEvent *e) {
+ ++(m_eventCount[int(e->type())]);
+ return QGraphicsWidget::event(e);
+ }
+
+ int eventCount(QEvent::Type type) {
+ return m_eventCount.value(int(type));
+ }
+ void clearEventCount() {
+ m_eventCount.clear();
+ }
+private:
+ QMap<int, int> m_eventCount;
+};
+
+void tst_QGraphicsLayout::compressLayoutRequest()
+{
+ QGraphicsView view;
+ QGraphicsScene scene;
+ TestGraphicsWidget *tw = new TestGraphicsWidget();
+ scene.addItem(tw);
+ view.show();
+ QGraphicsLinearLayout *lout = new QGraphicsLinearLayout(tw);
+ for (int i = 0; i < 4; ++i) {
+ QGraphicsWidget *gw = new QGraphicsWidget(tw);
+ gw->setPreferredSize(QSizeF(50, 50));
+ lout->addItem(gw);
+ }
+ QApplication::processEvents();
+ QCOMPARE(tw->eventCount(QEvent::LayoutRequest), 1);
+}
+
+void tst_QGraphicsLayout::automaticReparenting()
+{
+ QGraphicsView view;
+ QGraphicsScene scene;
+ {
+ QGraphicsWidget *w = new QGraphicsWidget();
+ QGraphicsLinearLayout *l = new QGraphicsLinearLayout(w);
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ l->addItem(w1);
+ scene.addItem(w);
+ QCOMPARE(w1->parentWidget(), w);
+ delete w;
+ }
+ {
+ QGraphicsWidget *w = new QGraphicsWidget();
+ QGraphicsLinearLayout *l = new QGraphicsLinearLayout(w);
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ l->addItem(w1);
+ scene.addItem(w);
+ QCOMPARE(w1->parentWidget(), w);
+
+ QGraphicsWidget *ww = new QGraphicsWidget();
+ QGraphicsLinearLayout *l1 = new QGraphicsLinearLayout(ww);
+#if !defined(Q_OS_MAC) && defined(QT_DEBUG)
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLayout::addChildLayoutItem: QGraphicsWidget \"\""
+ " in wrong parent; moved to correct parent");
+#endif
+ l1->addItem(w1);
+ QCOMPARE(w1->parentWidget(), ww);
+ delete w;
+ }
+
+ QGraphicsWidget *window = new QGraphicsWidget();
+ scene.addItem(window);
+ view.show();
+ QGraphicsLinearLayout *l1 = new QGraphicsLinearLayout();
+ QGraphicsWidget *w1 = new QGraphicsWidget();
+ l1->addItem(w1);
+ QGraphicsWidget *w2 = new QGraphicsWidget();
+ l1->addItem(w2);
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(0));
+ QCOMPARE(w2->parentItem(), static_cast<QGraphicsItem*>(0));
+ scene.addItem(w1);
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(0));
+ window->setLayout(l1);
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(window));
+ QCOMPARE(w2->parentItem(), static_cast<QGraphicsItem*>(window));
+
+ // Sublayouts
+ QGraphicsLinearLayout *l2 = new QGraphicsLinearLayout();
+ QGraphicsWidget *w3 = new QGraphicsWidget();
+ l2->addItem(w3);
+ QGraphicsWidget *w4 = new QGraphicsWidget();
+ l2->addItem(w4);
+ QGraphicsLinearLayout *l3 = new QGraphicsLinearLayout();
+ l2->addItem(l3);
+ QGraphicsWidget *window2 = new QGraphicsWidget();
+ scene.addItem(window2);
+ window2->setLayout(l2);
+
+ QCOMPARE(w3->parentItem(), static_cast<QGraphicsItem*>(window2));
+ QCOMPARE(w4->parentItem(), static_cast<QGraphicsItem*>(window2));
+
+ // graphics item with another parent
+ QGraphicsLinearLayout *l5 = new QGraphicsLinearLayout();
+ l5->addItem(w1);
+ l5->addItem(w2);
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(window));
+ QCOMPARE(w2->parentItem(), static_cast<QGraphicsItem*>(window));
+ QGraphicsLinearLayout *l4 = new QGraphicsLinearLayout();
+ l4->addItem(l5);
+ QGraphicsWidget *window3 = new QGraphicsWidget();
+ scene.addItem(window3);
+ window3->setLayout(l4);
+
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(window3));
+ QCOMPARE(w2->parentItem(), static_cast<QGraphicsItem*>(window3));
+}
+
+class TestLayout : public QGraphicsLinearLayout
+{
+ public:
+ TestLayout(QGraphicsLayoutItem *parent = 0)
+ : QGraphicsLinearLayout(parent)
+ {
+ m_count = 0;
+ }
+
+ void setGeometry(const QRectF &rect) {
+
+ ++m_count;
+ QGraphicsLinearLayout::setGeometry(rect);
+ }
+
+
+ int m_count;
+};
+
+void tst_QGraphicsLayout::verifyActivate()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *window = new QGraphicsWidget();
+ scene.addItem(window);
+ TestLayout *lout = new TestLayout(window);
+ QGraphicsWidget *w = new QGraphicsWidget();
+ lout->addItem(w);
+ window->setLayout(lout);
+
+ QCOMPARE(lout->m_count, 0);
+ window->setVisible(false);
+ QCOMPARE(lout->m_count, 0);
+ window->setVisible(true);
+ // on polish or the first time a widget is shown, the widget is resized.
+ QCOMPARE(lout->m_count, 1);
+
+}
+
+class Layout : public QGraphicsLayout
+{
+public:
+ Layout(QGraphicsLayoutItem *parentItem = 0) : QGraphicsLayout(parentItem) {}
+
+ void setGeometry(const QRectF &rect)
+ {
+ QGraphicsLayout::setGeometry(rect);
+ }
+
+ int count() const {
+ return 0;
+ }
+
+ QGraphicsLayoutItem *itemAt(int index) const {
+ Q_UNUSED(index);
+ return 0;
+ }
+
+ void removeAt(int index)
+ {
+ Q_UNUSED(index);
+ }
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const
+ {
+ Q_UNUSED(constraint);
+ Q_UNUSED(which);
+ return QSizeF(100,100);
+ }
+
+};
+
+void tst_QGraphicsLayout::constructors()
+{
+ // Strange test, but see the fix that was with this submit
+ QVector<Layout*> layouts;
+ for (int pass = 0; pass < 5; ++pass) {
+ Layout *lay = new Layout();
+ layouts << lay;
+ qreal left, top, right, bottom;
+ lay->getContentsMargins(&left, &top, &right, &bottom);
+ // Test if the style defaults are sane (should always be ints)
+ double intpart;
+ QVERIFY(modf(left, &intpart) == 0.0);
+ QVERIFY(modf(top, &intpart) == 0.0);
+ QVERIFY(modf(right, &intpart) == 0.0);
+ QVERIFY(modf(bottom, &intpart) == 0.0);
+
+ lay->setContentsMargins(1, 2, 4, 8);
+ lay->getContentsMargins(&left, &top, &right, &bottom);
+
+ QCOMPARE(int(left), 1);
+ QCOMPARE(int(top), 2);
+ QCOMPARE(int(right), 4);
+ QCOMPARE(int(bottom), 8);
+ }
+
+ qDeleteAll(layouts);
+}
+
+class AnimatedLayoutItem : public QGraphicsLayoutItem {
+public:
+ AnimatedLayoutItem(QGraphicsRectItem *item)
+ : QGraphicsLayoutItem()
+ {
+ setGraphicsItem(item);
+ }
+
+ void setGeometry(const QRectF &geom);
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const;
+
+ inline QGraphicsRectItem *rectItem() {
+ return static_cast<QGraphicsRectItem *>(graphicsItem());
+ }
+
+ QRectF m_geom;
+private:
+ AnimatedLayoutItem() {}
+};
+
+void AnimatedLayoutItem::setGeometry(const QRectF &geom)
+{
+ QGraphicsLayoutItem::setGeometry(geom);
+}
+
+QSizeF AnimatedLayoutItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ switch (which) {
+ case Qt::MinimumSize:
+ return QSizeF(32,32);
+ case Qt::PreferredSize:
+ return QSizeF(160,90);
+ case Qt::MaximumSize:
+ return QSizeF(1000,1000);
+ default:
+ return QSizeF(300, 300);
+ }
+}
+
+class AnimatedLayout : public QObject, public QGraphicsLinearLayout {
+ Q_OBJECT
+public:
+ AnimatedLayout(QGraphicsWidget *widget) : QGraphicsLinearLayout(widget), m_timeline(500, this)
+ {
+ connect(&m_timeline, SIGNAL(valueChanged(qreal)), this, SLOT(valueChanged(qreal)));
+ }
+
+ void setGeometry(const QRectF &geom) {
+ fromGeoms.clear();
+ toGeoms.clear();
+ for (int i = 0; i < count(); ++i) {
+ fromGeoms << itemAt(i)->geometry();
+ }
+
+ QGraphicsLinearLayout::setGeometry(geom);
+
+ for (int i = 0; i < count(); ++i) {
+ toGeoms << itemAt(i)->geometry();
+ }
+ m_timeline.start();
+ }
+
+private slots:
+ void valueChanged(qreal value) {
+ for (int i = 0; i < fromGeoms.count(); ++i) {
+ QGraphicsLayoutItem *li = itemAt(i);
+ QRectF from = fromGeoms.at(i);
+ QRectF to = toGeoms.at(i);
+
+ QRectF geom(from.topLeft() + (to.topLeft() - from.topLeft()) * value,
+ from.size() + (to.size() - from.size()) * value);
+ static_cast<QGraphicsRectItem*>(li->graphicsItem())->setRect(geom);
+ }
+ }
+private:
+ QTimeLine m_timeline;
+ QVector<QRectF> fromGeoms;
+ QVector<QRectF> toGeoms;
+};
+
+
+void tst_QGraphicsLayout::alternativeLayoutItems()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *window = new QGraphicsWidget;
+ scene.addItem(window);
+ AnimatedLayout *lout = new AnimatedLayout(window);
+ lout->setContentsMargins(0, 0, 0, 0);
+ lout->setSpacing(0);
+
+ QGraphicsRectItem *item1 = new QGraphicsRectItem;
+ AnimatedLayoutItem *li1 = new AnimatedLayoutItem(item1);
+ lout->addItem(li1);
+
+ QGraphicsRectItem *item2 = new QGraphicsRectItem;
+ AnimatedLayoutItem *li2 = new AnimatedLayoutItem(item2);
+ lout->addItem(li2);
+
+ QGraphicsRectItem *item3 = new QGraphicsRectItem;
+ AnimatedLayoutItem *li3 = new AnimatedLayoutItem(item3);
+ lout->addItem(li3);
+
+ window->setLayout(lout);
+
+ window->setGeometry(0, 0, 99, 99);
+ view.setSceneRect(QRectF(-10, -10, 110, 110));
+ view.resize(150, 150);
+ view.show();
+
+ QApplication::processEvents();
+ QTest::qWait(750);
+ QApplication::processEvents();
+
+ QCOMPARE(static_cast<QGraphicsRectItem*>(li1->graphicsItem())->rect(), QRectF( 0, 0, 33, 99));
+ QCOMPARE(static_cast<QGraphicsRectItem*>(li2->graphicsItem())->rect(), QRectF(33, 0, 33, 99));
+ QCOMPARE(static_cast<QGraphicsRectItem*>(li3->graphicsItem())->rect(), QRectF(66, 0, 33, 99));
+
+ lout->setOrientation(Qt::Vertical);
+
+ QApplication::processEvents();
+ QTest::qWait(750);
+ QApplication::processEvents();
+ QCOMPARE(static_cast<QGraphicsRectItem*>(li1->graphicsItem())->rect(), QRectF(0, 0, 99, 33));
+ QCOMPARE(static_cast<QGraphicsRectItem*>(li2->graphicsItem())->rect(), QRectF(0, 33, 99, 33));
+ QCOMPARE(static_cast<QGraphicsRectItem*>(li3->graphicsItem())->rect(), QRectF(0, 66, 99, 33));
+
+}
+
+class CustomLayoutItem : public QGraphicsLayoutItem {
+public:
+ CustomLayoutItem(QSet<QGraphicsLayoutItem*> *destructedSet)
+ : QGraphicsLayoutItem()
+ {
+ m_destructedSet = destructedSet;
+ setOwnedByLayout(true);
+ }
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const;
+
+ ~CustomLayoutItem() {
+ m_destructedSet->insert(this);
+ }
+private:
+ QSet<QGraphicsLayoutItem*> *m_destructedSet;
+};
+
+QSizeF CustomLayoutItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ switch (which) {
+ case Qt::MinimumSize:
+ return QSizeF(32,32);
+ case Qt::PreferredSize:
+ return QSizeF(160,90);
+ case Qt::MaximumSize:
+ return QSizeF(1000,1000);
+ default:
+ return QSizeF(300, 300);
+ }
+}
+
+class CustomGraphicsWidget : public QGraphicsWidget {
+public:
+ CustomGraphicsWidget(QSet<QGraphicsLayoutItem*> *destructedSet = 0)
+ : QGraphicsWidget()
+ {
+ m_destructedSet = destructedSet;
+ }
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * = 0)
+ {
+ const QRect r = option->rect.adjusted(0, 0, -1, -1);
+ painter->drawLine(r.topLeft(), r.bottomRight());
+ painter->drawLine(r.bottomLeft(), r.topRight());
+ painter->drawRect(r);
+ }
+
+ ~CustomGraphicsWidget() {
+ if (m_destructedSet)
+ m_destructedSet->insert(this);
+ }
+private:
+ QSet<QGraphicsLayoutItem*> *m_destructedSet;
+};
+
+QSizeF CustomGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ switch (which) {
+ case Qt::MinimumSize:
+ return QSizeF(32,32);
+ case Qt::PreferredSize:
+ return QSizeF(160,90);
+ case Qt::MaximumSize:
+ return QSizeF(1000,1000);
+ default:
+ return QSizeF(300, 300);
+ }
+}
+
+static bool compareSets(const QSet<QGraphicsLayoutItem*> &actual, const QSet<QGraphicsLayoutItem*> &expected)
+{
+ if (actual != expected) {
+ qDebug() << "actual:" << actual << "expected:" << expected;
+ return false;
+ }
+ return true;
+}
+
+class CustomLayout : public QGraphicsLayout
+{
+public :
+CustomLayout(QGraphicsLayoutItem *parent)
+ : QGraphicsLayout(parent)
+{
+}
+
+
+~CustomLayout()
+{
+}
+
+int count() const
+{
+ return items.count();
+}
+
+QGraphicsLayoutItem* itemAt(int index) const
+{
+ return items.at(index);
+}
+
+
+void removeAt(int index)
+{
+ items.removeAt(index);
+}
+
+void addItem(QGraphicsLayoutItem *item)
+{
+ insertItem(items.count(), item);
+}
+
+void insertItem(int index, QGraphicsLayoutItem *item)
+{
+ index = qBound(0, index, items.count());
+
+ item->setParentLayoutItem(this);
+
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
+ updateParentWidget(widget);
+
+
+ if (index == items.count()) {
+ items.append(item);
+ } else {
+ items.insert(index, item);
+ }
+
+ updateGeometry();
+ activate();
+}
+
+void updateParentWidget(QGraphicsWidget *item)
+{
+ QGraphicsLayoutItem *parentItem = parentLayoutItem();
+ while (parentItem && parentItem->isLayout()) {
+ parentItem = parentItem->parentLayoutItem();
+ }
+
+ if (parentItem) {
+ item->setParentItem(static_cast<QGraphicsWidget*>(parentItem));
+ }
+}
+
+QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ return QSizeF(50,50);
+}
+
+QList<QGraphicsLayoutItem*> items;
+
+};
+
+void tst_QGraphicsLayout::ownership()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ {
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout;
+ QSet<QGraphicsLayoutItem*> destructedSet;
+ CustomLayoutItem *li1 = new CustomLayoutItem(&destructedSet);
+ lay->addItem(li1);
+ CustomLayoutItem *li2 = new CustomLayoutItem(&destructedSet);
+ lay->addItem(li2);
+ CustomLayoutItem *li3 = new CustomLayoutItem(&destructedSet);
+ lay->addItem(li3);
+ destructedSet.clear();
+
+ delete lay;
+ QSet<QGraphicsLayoutItem*> expected;
+ expected << li1 << li2 << li3;
+ QVERIFY(compareSets(destructedSet, expected));
+ }
+
+ {
+ QGraphicsWidget *window = new QGraphicsWidget;
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout;
+ QSet<QGraphicsLayoutItem*> destructedSet;
+ CustomGraphicsWidget *li1 = new CustomGraphicsWidget(&destructedSet);
+ lay->addItem(li1);
+ CustomGraphicsWidget *li2 = new CustomGraphicsWidget(&destructedSet);
+ lay->addItem(li2);
+ CustomGraphicsWidget *li3 = new CustomGraphicsWidget(&destructedSet);
+ lay->addItem(li3);
+ window->setLayout(lay);
+ scene.addItem(window);
+
+ destructedSet.clear();
+ window->setLayout(0);
+ QVERIFY(destructedSet.count() == 0);
+ delete window;
+ }
+
+ {
+ QGraphicsWidget *window = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout;
+
+ CustomGraphicsWidget *li1 = new CustomGraphicsWidget;
+ lay->addItem(li1);
+
+ QGraphicsLinearLayout *li2 = new QGraphicsLinearLayout;
+ CustomGraphicsWidget *li2_1 = new CustomGraphicsWidget;
+ li2->addItem(li2_1);
+ CustomGraphicsWidget *li2_2 = new CustomGraphicsWidget;
+ li2->addItem(li2_2);
+ CustomGraphicsWidget *li2_3 = new CustomGraphicsWidget;
+ li2->addItem(li2_3);
+ lay->addItem(li2);
+
+ CustomGraphicsWidget *li3 = new CustomGraphicsWidget;
+ lay->addItem(li3);
+
+ window->setLayout(lay);
+ scene.addItem(window);
+ view.resize(500, 200);
+ view.show();
+
+ for (int i = li2->count(); i > 0; --i) {
+ QCOMPARE(li2->count(), i);
+ delete li2->itemAt(0);
+ }
+
+ for (int i = lay->count(); i > 0; --i) {
+ QCOMPARE(lay->count(), i);
+ delete lay->itemAt(0);
+ }
+
+ delete window;
+ }
+
+ {
+ QGraphicsWidget *top = new QGraphicsWidget;
+ QGraphicsWidget *w = new QGraphicsWidget;
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ CustomLayout *layout = new CustomLayout(top);
+ layout->addItem(w);
+ layout->addItem(w2);
+ top->setLayout(layout);
+ delete top;
+ //don't crash after that.
+ }
+}
+
+QTEST_MAIN(tst_QGraphicsLayout)
+#include "tst_qgraphicslayout.moc"