tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QtTest/QtTest>
       
    43 #include <QtTest/QSignalSpy>
       
    44 #include <private/qlistmodelinterface_p.h>
       
    45 #include <QtDeclarative/qdeclarativeengine.h>
       
    46 #include <QtDeclarative/qdeclarativeview.h>
       
    47 #include <QtDeclarative/qdeclarativecontext.h>
       
    48 #include <private/qdeclarativerepeater_p.h>
       
    49 #include <private/qdeclarativetext_p.h>
       
    50 
       
    51 inline QUrl TEST_FILE(const QString &filename)
       
    52 {
       
    53     return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
       
    54 }
       
    55 
       
    56 class tst_QDeclarativeRepeater : public QObject
       
    57 {
       
    58     Q_OBJECT
       
    59 public:
       
    60     tst_QDeclarativeRepeater();
       
    61 
       
    62 private slots:
       
    63     void numberModel();
       
    64     void objectList();
       
    65     void stringList();
       
    66     void dataModel();
       
    67     void itemModel();
       
    68     void properties();
       
    69 
       
    70 private:
       
    71     QDeclarativeView *createView();
       
    72     template<typename T>
       
    73     T *findItem(QGraphicsObject *parent, const QString &id);
       
    74 };
       
    75 
       
    76 class TestObject : public QObject
       
    77 {
       
    78     Q_OBJECT
       
    79 
       
    80     Q_PROPERTY(bool error READ error WRITE setError)
       
    81     Q_PROPERTY(bool useModel READ useModel NOTIFY useModelChanged)
       
    82 
       
    83 public:
       
    84     TestObject() : QObject(), mError(true), mUseModel(false) {}
       
    85 
       
    86     bool error() const { return mError; }
       
    87     void setError(bool err) { mError = err; }
       
    88 
       
    89     bool useModel() const { return mUseModel; }
       
    90     void setUseModel(bool use) { mUseModel = use; emit useModelChanged(); }
       
    91 
       
    92 signals:
       
    93     void useModelChanged();
       
    94 
       
    95 private:
       
    96     bool mError;
       
    97     bool mUseModel;
       
    98 };
       
    99 
       
   100 class TestModel : public QAbstractListModel
       
   101 {
       
   102 public:
       
   103     enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
       
   104 
       
   105     TestModel(QObject *parent=0) : QAbstractListModel(parent) {
       
   106         QHash<int, QByteArray> roles;
       
   107         roles[Name] = "name";
       
   108         roles[Number] = "number";
       
   109         setRoleNames(roles);
       
   110     }
       
   111 
       
   112     int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
       
   113     QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
       
   114         QVariant rv;
       
   115         if (role == Name)
       
   116             rv = list.at(index.row()).first;
       
   117         else if (role == Number)
       
   118             rv = list.at(index.row()).second;
       
   119 
       
   120         return rv;
       
   121     }
       
   122 
       
   123     int count() const { return rowCount(); }
       
   124     QString name(int index) const { return list.at(index).first; }
       
   125     QString number(int index) const { return list.at(index).second; }
       
   126 
       
   127     void addItem(const QString &name, const QString &number) {
       
   128         emit beginInsertRows(QModelIndex(), list.count(), list.count());
       
   129         list.append(QPair<QString,QString>(name, number));
       
   130         emit endInsertRows();
       
   131     }
       
   132 
       
   133     void insertItem(int index, const QString &name, const QString &number) {
       
   134         emit beginInsertRows(QModelIndex(), index, index);
       
   135         list.insert(index, QPair<QString,QString>(name, number));
       
   136         emit endInsertRows();
       
   137     }
       
   138 
       
   139     void removeItem(int index) {
       
   140         emit beginRemoveRows(QModelIndex(), index, index);
       
   141         list.removeAt(index);
       
   142         emit endRemoveRows();
       
   143     }
       
   144 
       
   145     void moveItem(int from, int to) {
       
   146         emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
       
   147         list.move(from, to);
       
   148         emit endMoveRows();
       
   149     }
       
   150 
       
   151     void modifyItem(int idx, const QString &name, const QString &number) {
       
   152         list[idx] = QPair<QString,QString>(name, number);
       
   153         emit dataChanged(index(idx,0), index(idx,0));
       
   154     }
       
   155 
       
   156 private:
       
   157     QList<QPair<QString,QString> > list;
       
   158 };
       
   159 
       
   160 
       
   161 tst_QDeclarativeRepeater::tst_QDeclarativeRepeater()
       
   162 {
       
   163 }
       
   164 
       
   165 void tst_QDeclarativeRepeater::numberModel()
       
   166 {
       
   167     QDeclarativeView *canvas = createView();
       
   168 
       
   169     QDeclarativeContext *ctxt = canvas->rootContext();
       
   170     ctxt->setContextProperty("testData", 5);
       
   171     TestObject *testObject = new TestObject;
       
   172     ctxt->setContextProperty("testObject", testObject);
       
   173 
       
   174     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/intmodel.qml"));
       
   175     qApp->processEvents();
       
   176 
       
   177     QDeclarativeRepeater *repeater = findItem<QDeclarativeRepeater>(canvas->rootObject(), "repeater");
       
   178     QVERIFY(repeater != 0);
       
   179     QCOMPARE(repeater->parentItem()->childItems().count(), 5+1);
       
   180 
       
   181     QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
       
   182     QVERIFY(testObject->error() == false);
       
   183 
       
   184     delete testObject;
       
   185     delete canvas;
       
   186 }
       
   187 
       
   188 class MyObject : public QObject
       
   189 {
       
   190     Q_OBJECT
       
   191     Q_PROPERTY(int idx READ idx CONSTANT)
       
   192 public:
       
   193     MyObject(int i) : QObject(), m_idx(i) {}
       
   194 
       
   195     int idx() const { return m_idx; }
       
   196 
       
   197     int m_idx;
       
   198 };
       
   199 
       
   200 void tst_QDeclarativeRepeater::objectList()
       
   201 {
       
   202     QDeclarativeView *canvas = createView();
       
   203     QObjectList data;
       
   204     for(int i=0; i<100; i++)
       
   205         data << new MyObject(i);
       
   206 
       
   207     QDeclarativeContext *ctxt = canvas->rootContext();
       
   208     ctxt->setContextProperty("testData", QVariant::fromValue(data));
       
   209 
       
   210     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/objlist.qml"));
       
   211     qApp->processEvents();
       
   212 
       
   213     QDeclarativeRepeater *repeater = findItem<QDeclarativeRepeater>(canvas->rootObject(), "repeater");
       
   214     QVERIFY(repeater != 0);
       
   215     QCOMPARE(repeater->property("errors").toInt(), 0);//If this fails either they are out of order or can't find the object's data
       
   216     QCOMPARE(repeater->property("instantiated").toInt(), 100);
       
   217 
       
   218     qDeleteAll(data);
       
   219     delete canvas;
       
   220 }
       
   221 
       
   222 /*
       
   223 The Repeater element creates children at its own position in its parent's
       
   224 stacking order.  In this test we insert a repeater between two other Text
       
   225 elements to test this.
       
   226 */
       
   227 void tst_QDeclarativeRepeater::stringList()
       
   228 {
       
   229     QDeclarativeView *canvas = createView();
       
   230 
       
   231     QStringList data;
       
   232     data << "One";
       
   233     data << "Two";
       
   234     data << "Three";
       
   235     data << "Four";
       
   236 
       
   237     QDeclarativeContext *ctxt = canvas->rootContext();
       
   238     ctxt->setContextProperty("testData", data);
       
   239 
       
   240     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/repeater1.qml"));
       
   241     qApp->processEvents();
       
   242 
       
   243     QDeclarativeRepeater *repeater = findItem<QDeclarativeRepeater>(canvas->rootObject(), "repeater");
       
   244     QVERIFY(repeater != 0);
       
   245 
       
   246     QDeclarativeItem *container = findItem<QDeclarativeItem>(canvas->rootObject(), "container");
       
   247     QVERIFY(container != 0);
       
   248 
       
   249     QCOMPARE(container->childItems().count(), data.count() + 3);
       
   250 
       
   251     bool saw_repeater = false;
       
   252     for (int i = 0; i < container->childItems().count(); ++i) {
       
   253 
       
   254         if (i == 0) {
       
   255             QDeclarativeText *name = qobject_cast<QDeclarativeText*>(container->childItems().at(i));
       
   256             QVERIFY(name != 0);
       
   257             QCOMPARE(name->text(), QLatin1String("Zero"));
       
   258         } else if (i == container->childItems().count() - 2) {
       
   259             // The repeater itself
       
   260             QDeclarativeRepeater *rep = qobject_cast<QDeclarativeRepeater*>(container->childItems().at(i));
       
   261             QCOMPARE(rep, repeater);
       
   262             saw_repeater = true;
       
   263             continue;
       
   264         } else if (i == container->childItems().count() - 1) {
       
   265             QDeclarativeText *name = qobject_cast<QDeclarativeText*>(container->childItems().at(i));
       
   266             QVERIFY(name != 0);
       
   267             QCOMPARE(name->text(), QLatin1String("Last"));
       
   268         } else {
       
   269             QDeclarativeText *name = qobject_cast<QDeclarativeText*>(container->childItems().at(i));
       
   270             QVERIFY(name != 0);
       
   271             QCOMPARE(name->text(), data.at(i-1));
       
   272         }
       
   273     }
       
   274     QVERIFY(saw_repeater);
       
   275 
       
   276     delete canvas;
       
   277 }
       
   278 
       
   279 void tst_QDeclarativeRepeater::dataModel()
       
   280 {
       
   281     QDeclarativeView *canvas = createView();
       
   282     QDeclarativeContext *ctxt = canvas->rootContext();
       
   283     TestObject *testObject = new TestObject;
       
   284     ctxt->setContextProperty("testObject", testObject);
       
   285 
       
   286     TestModel testModel;
       
   287     testModel.addItem("one", "1");
       
   288     testModel.addItem("two", "2");
       
   289     testModel.addItem("three", "3");
       
   290 
       
   291     ctxt->setContextProperty("testData", &testModel);
       
   292 
       
   293     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/repeater2.qml"));
       
   294     qApp->processEvents();
       
   295 
       
   296     QDeclarativeRepeater *repeater = findItem<QDeclarativeRepeater>(canvas->rootObject(), "repeater");
       
   297     QVERIFY(repeater != 0);
       
   298 
       
   299     QDeclarativeItem *container = findItem<QDeclarativeItem>(canvas->rootObject(), "container");
       
   300     QVERIFY(container != 0);
       
   301 
       
   302     QCOMPARE(container->childItems().count(), 4);
       
   303 
       
   304     testModel.addItem("four", "4");
       
   305     QCOMPARE(container->childItems().count(), 5);
       
   306 
       
   307     testModel.removeItem(2);
       
   308     QCOMPARE(container->childItems().count(), 4);
       
   309 
       
   310     delete testObject;
       
   311     delete canvas;
       
   312 }
       
   313 
       
   314 void tst_QDeclarativeRepeater::itemModel()
       
   315 {
       
   316     QDeclarativeView *canvas = createView();
       
   317     QDeclarativeContext *ctxt = canvas->rootContext();
       
   318     TestObject *testObject = new TestObject;
       
   319     ctxt->setContextProperty("testObject", testObject);
       
   320 
       
   321     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/itemlist.qml"));
       
   322     qApp->processEvents();
       
   323 
       
   324     QDeclarativeRepeater *repeater = findItem<QDeclarativeRepeater>(canvas->rootObject(), "repeater");
       
   325     QVERIFY(repeater != 0);
       
   326 
       
   327     QDeclarativeItem *container = findItem<QDeclarativeItem>(canvas->rootObject(), "container");
       
   328     QVERIFY(container != 0);
       
   329 
       
   330     QCOMPARE(container->childItems().count(), 1);
       
   331 
       
   332     testObject->setUseModel(true);
       
   333     QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
       
   334     QVERIFY(testObject->error() == false);
       
   335 
       
   336     QCOMPARE(container->childItems().count(), 4);
       
   337     QVERIFY(qobject_cast<QObject*>(container->childItems().at(0))->objectName() == "item1");
       
   338     QVERIFY(qobject_cast<QObject*>(container->childItems().at(1))->objectName() == "item2");
       
   339     QVERIFY(qobject_cast<QObject*>(container->childItems().at(2))->objectName() == "item3");
       
   340     QVERIFY(container->childItems().at(3) == repeater);
       
   341 
       
   342     delete testObject;
       
   343     delete canvas;
       
   344 }
       
   345 
       
   346 void tst_QDeclarativeRepeater::properties()
       
   347 {
       
   348     QDeclarativeEngine engine;
       
   349     QDeclarativeComponent component(&engine, TEST_FILE("/properties.qml"));
       
   350 
       
   351     QDeclarativeItem *rootObject = qobject_cast<QDeclarativeItem*>(component.create());
       
   352     QVERIFY(rootObject);
       
   353 
       
   354     QDeclarativeRepeater *repeater = findItem<QDeclarativeRepeater>(rootObject, "repeater");
       
   355     QVERIFY(repeater);
       
   356 
       
   357     QSignalSpy modelSpy(repeater, SIGNAL(modelChanged()));
       
   358     repeater->setModel(3);
       
   359     QCOMPARE(modelSpy.count(),1);
       
   360     repeater->setModel(3);
       
   361     QCOMPARE(modelSpy.count(),1);
       
   362 
       
   363     QSignalSpy delegateSpy(repeater, SIGNAL(delegateChanged()));
       
   364 
       
   365     QDeclarativeComponent rectComponent(&engine);
       
   366     rectComponent.setData("import Qt 4.7; Rectangle {}", QUrl::fromLocalFile(""));
       
   367 
       
   368     repeater->setDelegate(&rectComponent);
       
   369     QCOMPARE(delegateSpy.count(),1);
       
   370     repeater->setDelegate(&rectComponent);
       
   371     QCOMPARE(delegateSpy.count(),1);
       
   372 
       
   373     delete rootObject;
       
   374 }
       
   375 
       
   376 QDeclarativeView *tst_QDeclarativeRepeater::createView()
       
   377 {
       
   378     QDeclarativeView *canvas = new QDeclarativeView(0);
       
   379     canvas->setFixedSize(240,320);
       
   380 
       
   381     return canvas;
       
   382 }
       
   383 
       
   384 template<typename T>
       
   385 T *tst_QDeclarativeRepeater::findItem(QGraphicsObject *parent, const QString &objectName)
       
   386 {
       
   387     const QMetaObject &mo = T::staticMetaObject;
       
   388     if (mo.cast(parent) && (objectName.isEmpty() || parent->objectName() == objectName))
       
   389         return static_cast<T*>(parent);
       
   390     for (int i = 0; i < parent->childItems().count(); ++i) {
       
   391         QDeclarativeItem *child = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
       
   392         if (!child)
       
   393             continue;
       
   394         QDeclarativeItem *item = findItem<T>(child, objectName);
       
   395         if (item)
       
   396             return static_cast<T*>(item);
       
   397     }
       
   398 
       
   399     return 0;
       
   400 }
       
   401 
       
   402 QTEST_MAIN(tst_QDeclarativeRepeater)
       
   403 
       
   404 #include "tst_qdeclarativerepeater.moc"