Initial import from the monolithic Qt.
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativeflickable / tst_qdeclarativeflickable.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 #include <qtest.h>
42 #include <QtTest/QSignalSpy>
43 #include <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativecomponent.h>
45 #include <QtDeclarative/qdeclarativeview.h>
46 #include <private/qdeclarativeflickable_p.h>
47 #include <private/qdeclarativevaluetype_p.h>
48 #include <QtGui/qgraphicswidget.h>
49 #include <math.h>
50 #include "../../../shared/util.h"
51
52 #ifdef Q_OS_SYMBIAN
53 // In Symbian OS test data is located in applications private dir
54 #define SRCDIR "."
55 #endif
56
57 class tst_qdeclarativeflickable : public QObject
58 {
59     Q_OBJECT
60 public:
61     tst_qdeclarativeflickable();
62
63 private slots:
64     void create();
65     void horizontalViewportSize();
66     void verticalViewportSize();
67     void properties();
68     void boundsBehavior();
69     void maximumFlickVelocity();
70     void flickDeceleration();
71     void pressDelay();
72     void disabledContent();
73     void nestedPressDelay();
74     void flickableDirection();
75     void qgraphicswidget();
76     void resizeContent();
77     void returnToBounds();
78     void testQtQuick11Attributes();
79     void testQtQuick11Attributes_data();
80     void wheel();
81
82 private:
83     QDeclarativeEngine engine;
84
85     template<typename T>
86     T *findItem(QGraphicsObject *parent, const QString &objectName);
87 };
88
89 tst_qdeclarativeflickable::tst_qdeclarativeflickable()
90 {
91 }
92
93 void tst_qdeclarativeflickable::create()
94 {
95     QDeclarativeEngine engine;
96     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickable01.qml"));
97     QDeclarativeFlickable *obj = qobject_cast<QDeclarativeFlickable*>(c.create());
98
99     QVERIFY(obj != 0);
100     QCOMPARE(obj->isAtXBeginning(), true);
101     QCOMPARE(obj->isAtXEnd(), false);
102     QCOMPARE(obj->isAtYBeginning(), true);
103     QCOMPARE(obj->isAtYEnd(), false);
104     QCOMPARE(obj->contentX(), 0.);
105     QCOMPARE(obj->contentY(), 0.);
106
107     QCOMPARE(obj->horizontalVelocity(), 0.);
108     QCOMPARE(obj->verticalVelocity(), 0.);
109
110     QCOMPARE(obj->isInteractive(), true);
111     QCOMPARE(obj->boundsBehavior(), QDeclarativeFlickable::DragAndOvershootBounds);
112     QCOMPARE(obj->pressDelay(), 0);
113     QCOMPARE(obj->maximumFlickVelocity(), 2500.);
114
115     delete obj;
116 }
117
118 void tst_qdeclarativeflickable::horizontalViewportSize()
119 {
120     QDeclarativeEngine engine;
121     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickable02.qml"));
122     QDeclarativeFlickable *obj = qobject_cast<QDeclarativeFlickable*>(c.create());
123
124     QVERIFY(obj != 0);
125     QCOMPARE(obj->contentWidth(), 800.);
126     QCOMPARE(obj->contentHeight(), 300.);
127     QCOMPARE(obj->isAtXBeginning(), true);
128     QCOMPARE(obj->isAtXEnd(), false);
129     QCOMPARE(obj->isAtYBeginning(), true);
130     QCOMPARE(obj->isAtYEnd(), false);
131
132     delete obj;
133 }
134
135 void tst_qdeclarativeflickable::verticalViewportSize()
136 {
137     QDeclarativeEngine engine;
138     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickable03.qml"));
139     QDeclarativeFlickable *obj = qobject_cast<QDeclarativeFlickable*>(c.create());
140
141     QVERIFY(obj != 0);
142     QCOMPARE(obj->contentWidth(), 200.);
143     QCOMPARE(obj->contentHeight(), 1200.);
144     QCOMPARE(obj->isAtXBeginning(), true);
145     QCOMPARE(obj->isAtXEnd(), false);
146     QCOMPARE(obj->isAtYBeginning(), true);
147     QCOMPARE(obj->isAtYEnd(), false);
148
149     delete obj;
150 }
151
152 void tst_qdeclarativeflickable::properties()
153 {
154     QDeclarativeEngine engine;
155     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickable04.qml"));
156     QDeclarativeFlickable *obj = qobject_cast<QDeclarativeFlickable*>(c.create());
157
158     QVERIFY(obj != 0);
159     QCOMPARE(obj->isInteractive(), false);
160     QCOMPARE(obj->boundsBehavior(), QDeclarativeFlickable::StopAtBounds);
161     QCOMPARE(obj->pressDelay(), 200);
162     QCOMPARE(obj->maximumFlickVelocity(), 2000.);
163
164     QVERIFY(obj->property("ok").toBool() == false);
165     QMetaObject::invokeMethod(obj, "check");
166     QVERIFY(obj->property("ok").toBool() == true);
167
168     delete obj;
169 }
170
171 void tst_qdeclarativeflickable::boundsBehavior()
172 {
173     QDeclarativeComponent component(&engine);
174     component.setData("import QtQuick 1.0; Flickable { boundsBehavior: Flickable.StopAtBounds }", QUrl::fromLocalFile(""));
175     QDeclarativeFlickable *flickable = qobject_cast<QDeclarativeFlickable*>(component.create());
176     QSignalSpy spy(flickable, SIGNAL(boundsBehaviorChanged()));
177
178     QVERIFY(flickable);
179     QVERIFY(flickable->boundsBehavior() == QDeclarativeFlickable::StopAtBounds);
180
181     flickable->setBoundsBehavior(QDeclarativeFlickable::DragAndOvershootBounds);
182     QVERIFY(flickable->boundsBehavior() == QDeclarativeFlickable::DragAndOvershootBounds);
183     QCOMPARE(spy.count(),1);
184     flickable->setBoundsBehavior(QDeclarativeFlickable::DragAndOvershootBounds);
185     QCOMPARE(spy.count(),1);
186
187     flickable->setBoundsBehavior(QDeclarativeFlickable::DragOverBounds);
188     QVERIFY(flickable->boundsBehavior() == QDeclarativeFlickable::DragOverBounds);
189     QCOMPARE(spy.count(),2);
190     flickable->setBoundsBehavior(QDeclarativeFlickable::DragOverBounds);
191     QCOMPARE(spy.count(),2);
192
193     flickable->setBoundsBehavior(QDeclarativeFlickable::StopAtBounds);
194     QVERIFY(flickable->boundsBehavior() == QDeclarativeFlickable::StopAtBounds);
195     QCOMPARE(spy.count(),3);
196     flickable->setBoundsBehavior(QDeclarativeFlickable::StopAtBounds);
197     QCOMPARE(spy.count(),3);
198 }
199
200 void tst_qdeclarativeflickable::maximumFlickVelocity()
201 {
202     QDeclarativeComponent component(&engine);
203     component.setData("import QtQuick 1.0; Flickable { maximumFlickVelocity: 1.0; }", QUrl::fromLocalFile(""));
204     QDeclarativeFlickable *flickable = qobject_cast<QDeclarativeFlickable*>(component.create());
205     QSignalSpy spy(flickable, SIGNAL(maximumFlickVelocityChanged()));
206
207     QVERIFY(flickable);
208     QCOMPARE(flickable->maximumFlickVelocity(), 1.0);
209
210     flickable->setMaximumFlickVelocity(2.0);
211     QCOMPARE(flickable->maximumFlickVelocity(), 2.0);
212     QCOMPARE(spy.count(),1);
213     flickable->setMaximumFlickVelocity(2.0);
214     QCOMPARE(spy.count(),1);
215 }
216
217 void tst_qdeclarativeflickable::flickDeceleration()
218 {
219     QDeclarativeComponent component(&engine);
220     component.setData("import QtQuick 1.0; Flickable { flickDeceleration: 1.0; }", QUrl::fromLocalFile(""));
221     QDeclarativeFlickable *flickable = qobject_cast<QDeclarativeFlickable*>(component.create());
222     QSignalSpy spy(flickable, SIGNAL(flickDecelerationChanged()));
223
224     QVERIFY(flickable);
225     QCOMPARE(flickable->flickDeceleration(), 1.0);
226
227     flickable->setFlickDeceleration(2.0);
228     QCOMPARE(flickable->flickDeceleration(), 2.0);
229     QCOMPARE(spy.count(),1);
230     flickable->setFlickDeceleration(2.0);
231     QCOMPARE(spy.count(),1);
232 }
233
234 void tst_qdeclarativeflickable::pressDelay()
235 {
236     QDeclarativeComponent component(&engine);
237     component.setData("import QtQuick 1.0; Flickable { pressDelay: 100; }", QUrl::fromLocalFile(""));
238     QDeclarativeFlickable *flickable = qobject_cast<QDeclarativeFlickable*>(component.create());
239     QSignalSpy spy(flickable, SIGNAL(pressDelayChanged()));
240
241     QVERIFY(flickable);
242     QCOMPARE(flickable->pressDelay(), 100);
243
244     flickable->setPressDelay(200);
245     QCOMPARE(flickable->pressDelay(), 200);
246     QCOMPARE(spy.count(),1);
247     flickable->setPressDelay(200);
248     QCOMPARE(spy.count(),1);
249 }
250
251 // QT-4677
252 void tst_qdeclarativeflickable::disabledContent()
253 {
254     QDeclarativeView *canvas = new QDeclarativeView;
255     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/disabledcontent.qml"));
256     canvas->show();
257     canvas->setFocus();
258     QVERIFY(canvas->rootObject() != 0);
259
260     QDeclarativeFlickable *flickable = qobject_cast<QDeclarativeFlickable*>(canvas->rootObject());
261     QVERIFY(flickable != 0);
262
263     QVERIFY(flickable->contentX() == 0);
264     QVERIFY(flickable->contentY() == 0);
265
266     QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 50)));
267     {
268         QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(70,70)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
269         QApplication::sendEvent(canvas->viewport(), &mv);
270     }
271     {
272         QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(90,90)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
273         QApplication::sendEvent(canvas->viewport(), &mv);
274     }
275     {
276         QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(100,100)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
277         QApplication::sendEvent(canvas->viewport(), &mv);
278     }
279
280     QVERIFY(flickable->contentX() < 0);
281     QVERIFY(flickable->contentY() < 0);
282
283     QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(90, 90)));
284
285     delete canvas;
286 }
287
288
289 // QTBUG-17361
290 void tst_qdeclarativeflickable::nestedPressDelay()
291 {
292     QDeclarativeView *canvas = new QDeclarativeView;
293     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/nestedPressDelay.qml"));
294     canvas->show();
295     canvas->setFocus();
296     QVERIFY(canvas->rootObject() != 0);
297
298     QDeclarativeFlickable *outer = qobject_cast<QDeclarativeFlickable*>(canvas->rootObject());
299     QVERIFY(outer != 0);
300
301     QDeclarativeFlickable *inner = canvas->rootObject()->findChild<QDeclarativeFlickable*>("innerFlickable");
302     QVERIFY(inner != 0);
303
304     QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(150, 150)));
305     // the MouseArea is not pressed immediately
306     QVERIFY(outer->property("pressed").toBool() == false);
307
308     // The outer pressDelay will prevail (50ms, vs. 10sec)
309     // QTRY_VERIFY() has 5sec timeout, so will timeout well within 10sec.
310     QTRY_VERIFY(outer->property("pressed").toBool() == true);
311
312     QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(150, 150)));
313
314     delete canvas;
315 }
316
317 void tst_qdeclarativeflickable::flickableDirection()
318 {
319     QDeclarativeComponent component(&engine);
320     component.setData("import QtQuick 1.0; Flickable { flickableDirection: Flickable.VerticalFlick; }", QUrl::fromLocalFile(""));
321     QDeclarativeFlickable *flickable = qobject_cast<QDeclarativeFlickable*>(component.create());
322     QSignalSpy spy(flickable, SIGNAL(flickableDirectionChanged()));
323
324     QVERIFY(flickable);
325     QCOMPARE(flickable->flickableDirection(), QDeclarativeFlickable::VerticalFlick);
326
327     flickable->setFlickableDirection(QDeclarativeFlickable::HorizontalAndVerticalFlick);
328     QCOMPARE(flickable->flickableDirection(), QDeclarativeFlickable::HorizontalAndVerticalFlick);
329     QCOMPARE(spy.count(),1);
330
331     flickable->setFlickableDirection(QDeclarativeFlickable::AutoFlickDirection);
332     QCOMPARE(flickable->flickableDirection(), QDeclarativeFlickable::AutoFlickDirection);
333     QCOMPARE(spy.count(),2);
334
335     flickable->setFlickableDirection(QDeclarativeFlickable::HorizontalFlick);
336     QCOMPARE(flickable->flickableDirection(), QDeclarativeFlickable::HorizontalFlick);
337     QCOMPARE(spy.count(),3);
338
339     flickable->setFlickableDirection(QDeclarativeFlickable::HorizontalFlick);
340     QCOMPARE(flickable->flickableDirection(), QDeclarativeFlickable::HorizontalFlick);
341     QCOMPARE(spy.count(),3);
342 }
343
344 void tst_qdeclarativeflickable::qgraphicswidget()
345 {
346     QDeclarativeEngine engine;
347     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickableqgraphicswidget.qml"));
348     QDeclarativeFlickable *flickable = qobject_cast<QDeclarativeFlickable*>(c.create());
349
350     QVERIFY(flickable != 0);
351     QGraphicsWidget *widget = findItem<QGraphicsWidget>(flickable->contentItem(), "widget1");
352     QVERIFY(widget);
353 }
354
355 // QtQuick 1.1
356 void tst_qdeclarativeflickable::resizeContent()
357 {
358     QDeclarativeEngine engine;
359     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/resize.qml"));
360     QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(c.create());
361     QDeclarativeFlickable *obj = findItem<QDeclarativeFlickable>(root, "flick");
362
363     QVERIFY(obj != 0);
364     QCOMPARE(obj->contentX(), 0.);
365     QCOMPARE(obj->contentY(), 0.);
366     QCOMPARE(obj->contentWidth(), 300.);
367     QCOMPARE(obj->contentHeight(), 300.);
368
369     QMetaObject::invokeMethod(root, "resizeContent");
370
371     QCOMPARE(obj->contentX(), 100.);
372     QCOMPARE(obj->contentY(), 100.);
373     QCOMPARE(obj->contentWidth(), 600.);
374     QCOMPARE(obj->contentHeight(), 600.);
375
376     delete root;
377 }
378
379 // QtQuick 1.1
380 void tst_qdeclarativeflickable::returnToBounds()
381 {
382     QDeclarativeEngine engine;
383     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/resize.qml"));
384     QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(c.create());
385     QDeclarativeFlickable *obj = findItem<QDeclarativeFlickable>(root, "flick");
386
387     QVERIFY(obj != 0);
388     QCOMPARE(obj->contentX(), 0.);
389     QCOMPARE(obj->contentY(), 0.);
390     QCOMPARE(obj->contentWidth(), 300.);
391     QCOMPARE(obj->contentHeight(), 300.);
392
393     obj->setContentX(100);
394     obj->setContentY(400);
395     QTRY_COMPARE(obj->contentX(), 100.);
396     QTRY_COMPARE(obj->contentY(), 400.);
397
398     QMetaObject::invokeMethod(root, "returnToBounds");
399
400     QTRY_COMPARE(obj->contentX(), 0.);
401     QTRY_COMPARE(obj->contentY(), 0.);
402
403     delete root;
404 }
405
406 void tst_qdeclarativeflickable::testQtQuick11Attributes()
407 {
408     QFETCH(QString, code);
409     QFETCH(QString, warning);
410     QFETCH(QString, error);
411
412     QDeclarativeEngine engine;
413     QObject *obj;
414
415     QDeclarativeComponent invalid(&engine);
416     invalid.setData("import QtQuick 1.0; Flickable { " + code.toUtf8() + " }", QUrl(""));
417     QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
418     obj = invalid.create();
419     QCOMPARE(invalid.errorString(), error);
420     delete obj;
421
422     QDeclarativeComponent valid(&engine);
423     valid.setData("import QtQuick 1.1; Flickable { " + code.toUtf8() + " }", QUrl(""));
424     obj = valid.create();
425     QVERIFY(obj);
426     QVERIFY(valid.errorString().isEmpty());
427     delete obj;
428 }
429
430 void tst_qdeclarativeflickable::testQtQuick11Attributes_data()
431 {
432     QTest::addColumn<QString>("code");
433     QTest::addColumn<QString>("warning");
434     QTest::addColumn<QString>("error");
435
436     QTest::newRow("resizeContent") << "Component.onCompleted: resizeContent(100,100,Qt.point(50,50))"
437             << "<Unknown File>:1: ReferenceError: Can't find variable: resizeContent"
438             << "";
439
440     QTest::newRow("returnToBounds") << "Component.onCompleted: returnToBounds()"
441             << "<Unknown File>:1: ReferenceError: Can't find variable: returnToBounds"
442             << "";
443
444 }
445
446 void tst_qdeclarativeflickable::wheel()
447 {
448     QDeclarativeView *canvas = new QDeclarativeView;
449     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/wheel.qml"));
450     canvas->show();
451     canvas->setFocus();
452     QVERIFY(canvas->rootObject() != 0);
453
454     QDeclarativeFlickable *flick = canvas->rootObject()->findChild<QDeclarativeFlickable*>("flick");
455     QVERIFY(flick != 0);
456
457     QGraphicsScene *scene = canvas->scene();
458     QGraphicsSceneWheelEvent event(QEvent::GraphicsSceneWheel);
459     event.setScenePos(QPointF(200, 200));
460     event.setDelta(-120);
461     event.setOrientation(Qt::Vertical);
462     event.setAccepted(false);
463     QApplication::sendEvent(scene, &event);
464
465     QTRY_VERIFY(flick->contentY() > 0);
466     QVERIFY(flick->contentX() == 0);
467
468     flick->setContentY(0);
469     QVERIFY(flick->contentY() == 0);
470
471     event.setScenePos(QPointF(200, 200));
472     event.setDelta(-120);
473     event.setOrientation(Qt::Horizontal);
474     event.setAccepted(false);
475     QApplication::sendEvent(scene, &event);
476
477     QTRY_VERIFY(flick->contentX() > 0);
478     QVERIFY(flick->contentY() == 0);
479
480     delete canvas;
481 }
482
483
484 template<typename T>
485 T *tst_qdeclarativeflickable::findItem(QGraphicsObject *parent, const QString &objectName)
486 {
487     const QMetaObject &mo = T::staticMetaObject;
488     //qDebug() << parent->childItems().count() << "children";
489     for (int i = 0; i < parent->childItems().count(); ++i) {
490         QGraphicsObject *item = qobject_cast<QGraphicsObject*>(parent->childItems().at(i));
491         if(!item)
492             continue;
493         //qDebug() << "try" << item;
494         if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
495             return static_cast<T*>(item);
496         }
497         item = findItem<T>(item, objectName);
498         if (item)
499             return static_cast<T*>(item);
500     }
501
502     return 0;
503 }
504
505 QTEST_MAIN(tst_qdeclarativeflickable)
506
507 #include "tst_qdeclarativeflickable.moc"