31b9ec6fc8b733b05d4185650745f8a2ec7ed3b4
[profile/ivi/qtdeclarative.git] / tests / auto / qtquick1 / qdeclarativeflickable / tst_qdeclarativeflickable.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
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 <QtQuick1/qdeclarativeview.h>
46 #include <private/qdeclarativeflickable_p.h>
47 #include <private/qdeclarativevaluetype_p.h>
48 #include <QtWidgets/qgraphicswidget.h>
49 #include <math.h>
50
51 class tst_qdeclarativeflickable : public QObject
52 {
53     Q_OBJECT
54 public:
55     tst_qdeclarativeflickable();
56
57 private slots:
58     void create();
59     void horizontalViewportSize();
60     void verticalViewportSize();
61     void properties();
62     void boundsBehavior();
63     void maximumFlickVelocity();
64     void flickDeceleration();
65     void pressDelay();
66     void disabledContent();
67     void nestedPressDelay();
68     void flickableDirection();
69     void qgraphicswidget();
70     void resizeContent();
71     void returnToBounds();
72     void testQtQuick11Attributes();
73     void testQtQuick11Attributes_data();
74     void wheel();
75     void disabled();
76     void flickVelocity();
77
78 private:
79     QDeclarativeEngine engine;
80
81     void flick(QGraphicsView *canvas, const QPoint &from, const QPoint &to, int duration);
82     template<typename T>
83     T *findItem(QGraphicsObject *parent, const QString &objectName);
84 };
85
86 tst_qdeclarativeflickable::tst_qdeclarativeflickable()
87 {
88 }
89
90 void tst_qdeclarativeflickable::create()
91 {
92     QDeclarativeEngine engine;
93     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickable01.qml"));
94     QDeclarative1Flickable *obj = qobject_cast<QDeclarative1Flickable*>(c.create());
95
96     QVERIFY(obj != 0);
97     QCOMPARE(obj->isAtXBeginning(), true);
98     QCOMPARE(obj->isAtXEnd(), false);
99     QCOMPARE(obj->isAtYBeginning(), true);
100     QCOMPARE(obj->isAtYEnd(), false);
101     QCOMPARE(obj->contentX(), 0.);
102     QCOMPARE(obj->contentY(), 0.);
103
104     QCOMPARE(obj->horizontalVelocity(), 0.);
105     QCOMPARE(obj->verticalVelocity(), 0.);
106
107     QCOMPARE(obj->isInteractive(), true);
108     QCOMPARE(obj->boundsBehavior(), QDeclarative1Flickable::DragAndOvershootBounds);
109     QCOMPARE(obj->pressDelay(), 0);
110     QCOMPARE(obj->maximumFlickVelocity(), 2500.);
111
112     delete obj;
113 }
114
115 void tst_qdeclarativeflickable::horizontalViewportSize()
116 {
117     QDeclarativeEngine engine;
118     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickable02.qml"));
119     QDeclarative1Flickable *obj = qobject_cast<QDeclarative1Flickable*>(c.create());
120
121     QVERIFY(obj != 0);
122     QCOMPARE(obj->contentWidth(), 800.);
123     QCOMPARE(obj->contentHeight(), 300.);
124     QCOMPARE(obj->isAtXBeginning(), true);
125     QCOMPARE(obj->isAtXEnd(), false);
126     QCOMPARE(obj->isAtYBeginning(), true);
127     QCOMPARE(obj->isAtYEnd(), false);
128
129     delete obj;
130 }
131
132 void tst_qdeclarativeflickable::verticalViewportSize()
133 {
134     QDeclarativeEngine engine;
135     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickable03.qml"));
136     QDeclarative1Flickable *obj = qobject_cast<QDeclarative1Flickable*>(c.create());
137
138     QVERIFY(obj != 0);
139     QCOMPARE(obj->contentWidth(), 200.);
140     QCOMPARE(obj->contentHeight(), 1200.);
141     QCOMPARE(obj->isAtXBeginning(), true);
142     QCOMPARE(obj->isAtXEnd(), false);
143     QCOMPARE(obj->isAtYBeginning(), true);
144     QCOMPARE(obj->isAtYEnd(), false);
145
146     delete obj;
147 }
148
149 void tst_qdeclarativeflickable::properties()
150 {
151     QDeclarativeEngine engine;
152     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickable04.qml"));
153     QDeclarative1Flickable *obj = qobject_cast<QDeclarative1Flickable*>(c.create());
154
155     QVERIFY(obj != 0);
156     QCOMPARE(obj->isInteractive(), false);
157     QCOMPARE(obj->boundsBehavior(), QDeclarative1Flickable::StopAtBounds);
158     QCOMPARE(obj->pressDelay(), 200);
159     QCOMPARE(obj->maximumFlickVelocity(), 2000.);
160
161     QVERIFY(obj->property("ok").toBool() == false);
162     QMetaObject::invokeMethod(obj, "check");
163     QVERIFY(obj->property("ok").toBool() == true);
164
165     delete obj;
166 }
167
168 void tst_qdeclarativeflickable::boundsBehavior()
169 {
170     QDeclarativeComponent component(&engine);
171     component.setData("import QtQuick 1.0; Flickable { boundsBehavior: Flickable.StopAtBounds }", QUrl::fromLocalFile(""));
172     QDeclarative1Flickable *flickable = qobject_cast<QDeclarative1Flickable*>(component.create());
173     QSignalSpy spy(flickable, SIGNAL(boundsBehaviorChanged()));
174
175     QVERIFY(flickable);
176     QVERIFY(flickable->boundsBehavior() == QDeclarative1Flickable::StopAtBounds);
177
178     flickable->setBoundsBehavior(QDeclarative1Flickable::DragAndOvershootBounds);
179     QVERIFY(flickable->boundsBehavior() == QDeclarative1Flickable::DragAndOvershootBounds);
180     QCOMPARE(spy.count(),1);
181     flickable->setBoundsBehavior(QDeclarative1Flickable::DragAndOvershootBounds);
182     QCOMPARE(spy.count(),1);
183
184     flickable->setBoundsBehavior(QDeclarative1Flickable::DragOverBounds);
185     QVERIFY(flickable->boundsBehavior() == QDeclarative1Flickable::DragOverBounds);
186     QCOMPARE(spy.count(),2);
187     flickable->setBoundsBehavior(QDeclarative1Flickable::DragOverBounds);
188     QCOMPARE(spy.count(),2);
189
190     flickable->setBoundsBehavior(QDeclarative1Flickable::StopAtBounds);
191     QVERIFY(flickable->boundsBehavior() == QDeclarative1Flickable::StopAtBounds);
192     QCOMPARE(spy.count(),3);
193     flickable->setBoundsBehavior(QDeclarative1Flickable::StopAtBounds);
194     QCOMPARE(spy.count(),3);
195 }
196
197 void tst_qdeclarativeflickable::maximumFlickVelocity()
198 {
199     QDeclarativeComponent component(&engine);
200     component.setData("import QtQuick 1.0; Flickable { maximumFlickVelocity: 1.0; }", QUrl::fromLocalFile(""));
201     QDeclarative1Flickable *flickable = qobject_cast<QDeclarative1Flickable*>(component.create());
202     QSignalSpy spy(flickable, SIGNAL(maximumFlickVelocityChanged()));
203
204     QVERIFY(flickable);
205     QCOMPARE(flickable->maximumFlickVelocity(), 1.0);
206
207     flickable->setMaximumFlickVelocity(2.0);
208     QCOMPARE(flickable->maximumFlickVelocity(), 2.0);
209     QCOMPARE(spy.count(),1);
210     flickable->setMaximumFlickVelocity(2.0);
211     QCOMPARE(spy.count(),1);
212 }
213
214 void tst_qdeclarativeflickable::flickDeceleration()
215 {
216     QDeclarativeComponent component(&engine);
217     component.setData("import QtQuick 1.0; Flickable { flickDeceleration: 1.0; }", QUrl::fromLocalFile(""));
218     QDeclarative1Flickable *flickable = qobject_cast<QDeclarative1Flickable*>(component.create());
219     QSignalSpy spy(flickable, SIGNAL(flickDecelerationChanged()));
220
221     QVERIFY(flickable);
222     QCOMPARE(flickable->flickDeceleration(), 1.0);
223
224     flickable->setFlickDeceleration(2.0);
225     QCOMPARE(flickable->flickDeceleration(), 2.0);
226     QCOMPARE(spy.count(),1);
227     flickable->setFlickDeceleration(2.0);
228     QCOMPARE(spy.count(),1);
229 }
230
231 void tst_qdeclarativeflickable::pressDelay()
232 {
233     QDeclarativeComponent component(&engine);
234     component.setData("import QtQuick 1.0; Flickable { pressDelay: 100; }", QUrl::fromLocalFile(""));
235     QDeclarative1Flickable *flickable = qobject_cast<QDeclarative1Flickable*>(component.create());
236     QSignalSpy spy(flickable, SIGNAL(pressDelayChanged()));
237
238     QVERIFY(flickable);
239     QCOMPARE(flickable->pressDelay(), 100);
240
241     flickable->setPressDelay(200);
242     QCOMPARE(flickable->pressDelay(), 200);
243     QCOMPARE(spy.count(),1);
244     flickable->setPressDelay(200);
245     QCOMPARE(spy.count(),1);
246 }
247
248 // QT-4677
249 void tst_qdeclarativeflickable::disabledContent()
250 {
251     QDeclarativeView *canvas = new QDeclarativeView;
252     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/disabledcontent.qml"));
253     canvas->show();
254     canvas->setFocus();
255     QVERIFY(canvas->rootObject() != 0);
256
257     QDeclarative1Flickable *flickable = qobject_cast<QDeclarative1Flickable*>(canvas->rootObject());
258     QVERIFY(flickable != 0);
259
260     QVERIFY(flickable->contentX() == 0);
261     QVERIFY(flickable->contentY() == 0);
262
263     QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 50)));
264     {
265         QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(70,70)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
266         QApplication::sendEvent(canvas->viewport(), &mv);
267     }
268     {
269         QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(90,90)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
270         QApplication::sendEvent(canvas->viewport(), &mv);
271     }
272     {
273         QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(100,100)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
274         QApplication::sendEvent(canvas->viewport(), &mv);
275     }
276
277     QVERIFY(flickable->contentX() < 0);
278     QVERIFY(flickable->contentY() < 0);
279
280     QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(90, 90)));
281
282     delete canvas;
283 }
284
285
286 // QTBUG-17361
287 void tst_qdeclarativeflickable::nestedPressDelay()
288 {
289     QDeclarativeView *canvas = new QDeclarativeView;
290     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/nestedPressDelay.qml"));
291     canvas->show();
292     canvas->setFocus();
293     QVERIFY(canvas->rootObject() != 0);
294
295     QDeclarative1Flickable *outer = qobject_cast<QDeclarative1Flickable*>(canvas->rootObject());
296     QVERIFY(outer != 0);
297
298     QDeclarative1Flickable *inner = canvas->rootObject()->findChild<QDeclarative1Flickable*>("innerFlickable");
299     QVERIFY(inner != 0);
300
301     QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(150, 150)));
302     // the MouseArea is not pressed immediately
303     QVERIFY(outer->property("pressed").toBool() == false);
304
305     // The outer pressDelay will prevail (50ms, vs. 10sec)
306     // QTRY_VERIFY() has 5sec timeout, so will timeout well within 10sec.
307     QTRY_VERIFY(outer->property("pressed").toBool() == true);
308
309     QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(150, 150)));
310
311     delete canvas;
312 }
313
314 void tst_qdeclarativeflickable::flickableDirection()
315 {
316     QDeclarativeComponent component(&engine);
317     component.setData("import QtQuick 1.0; Flickable { flickableDirection: Flickable.VerticalFlick; }", QUrl::fromLocalFile(""));
318     QDeclarative1Flickable *flickable = qobject_cast<QDeclarative1Flickable*>(component.create());
319     QSignalSpy spy(flickable, SIGNAL(flickableDirectionChanged()));
320
321     QVERIFY(flickable);
322     QCOMPARE(flickable->flickableDirection(), QDeclarative1Flickable::VerticalFlick);
323
324     flickable->setFlickableDirection(QDeclarative1Flickable::HorizontalAndVerticalFlick);
325     QCOMPARE(flickable->flickableDirection(), QDeclarative1Flickable::HorizontalAndVerticalFlick);
326     QCOMPARE(spy.count(),1);
327
328     flickable->setFlickableDirection(QDeclarative1Flickable::AutoFlickDirection);
329     QCOMPARE(flickable->flickableDirection(), QDeclarative1Flickable::AutoFlickDirection);
330     QCOMPARE(spy.count(),2);
331
332     flickable->setFlickableDirection(QDeclarative1Flickable::HorizontalFlick);
333     QCOMPARE(flickable->flickableDirection(), QDeclarative1Flickable::HorizontalFlick);
334     QCOMPARE(spy.count(),3);
335
336     flickable->setFlickableDirection(QDeclarative1Flickable::HorizontalFlick);
337     QCOMPARE(flickable->flickableDirection(), QDeclarative1Flickable::HorizontalFlick);
338     QCOMPARE(spy.count(),3);
339 }
340
341 void tst_qdeclarativeflickable::qgraphicswidget()
342 {
343     QDeclarativeEngine engine;
344     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/flickableqgraphicswidget.qml"));
345     QDeclarative1Flickable *flickable = qobject_cast<QDeclarative1Flickable*>(c.create());
346
347     QVERIFY(flickable != 0);
348     QGraphicsWidget *widget = findItem<QGraphicsWidget>(flickable->contentItem(), "widget1");
349     QVERIFY(widget);
350 }
351
352 // QtQuick 1.1
353 void tst_qdeclarativeflickable::resizeContent()
354 {
355     QDeclarativeEngine engine;
356     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/resize.qml"));
357     QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(c.create());
358     QDeclarative1Flickable *obj = findItem<QDeclarative1Flickable>(root, "flick");
359
360     QVERIFY(obj != 0);
361     QCOMPARE(obj->contentX(), 0.);
362     QCOMPARE(obj->contentY(), 0.);
363     QCOMPARE(obj->contentWidth(), 300.);
364     QCOMPARE(obj->contentHeight(), 300.);
365
366     QMetaObject::invokeMethod(root, "resizeContent");
367
368     QCOMPARE(obj->contentX(), 100.);
369     QCOMPARE(obj->contentY(), 100.);
370     QCOMPARE(obj->contentWidth(), 600.);
371     QCOMPARE(obj->contentHeight(), 600.);
372
373     delete root;
374 }
375
376 // QtQuick 1.1
377 void tst_qdeclarativeflickable::returnToBounds()
378 {
379     QDeclarativeEngine engine;
380     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/resize.qml"));
381     QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(c.create());
382     QDeclarative1Flickable *obj = findItem<QDeclarative1Flickable>(root, "flick");
383
384     QVERIFY(obj != 0);
385     QCOMPARE(obj->contentX(), 0.);
386     QCOMPARE(obj->contentY(), 0.);
387     QCOMPARE(obj->contentWidth(), 300.);
388     QCOMPARE(obj->contentHeight(), 300.);
389
390     obj->setContentX(100);
391     obj->setContentY(400);
392     QTRY_COMPARE(obj->contentX(), 100.);
393     QTRY_COMPARE(obj->contentY(), 400.);
394
395     QMetaObject::invokeMethod(root, "returnToBounds");
396
397     QTRY_COMPARE(obj->contentX(), 0.);
398     QTRY_COMPARE(obj->contentY(), 0.);
399
400     delete root;
401 }
402
403 void tst_qdeclarativeflickable::testQtQuick11Attributes()
404 {
405     QFETCH(QString, code);
406     QFETCH(QString, warning);
407     QFETCH(QString, error);
408
409     QDeclarativeEngine engine;
410     QObject *obj;
411
412     QDeclarativeComponent invalid(&engine);
413     invalid.setData("import QtQuick 1.0; Flickable { " + code.toUtf8() + " }", QUrl(""));
414     QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
415     obj = invalid.create();
416     QCOMPARE(invalid.errorString(), error);
417     delete obj;
418
419     QDeclarativeComponent valid(&engine);
420     valid.setData("import QtQuick 1.1; Flickable { " + code.toUtf8() + " }", QUrl(""));
421     obj = valid.create();
422     QVERIFY(obj);
423     QVERIFY(valid.errorString().isEmpty());
424     delete obj;
425 }
426
427 void tst_qdeclarativeflickable::testQtQuick11Attributes_data()
428 {
429     QTest::addColumn<QString>("code");
430     QTest::addColumn<QString>("warning");
431     QTest::addColumn<QString>("error");
432
433     QTest::newRow("resizeContent") << "Component.onCompleted: resizeContent(100,100,Qt.point(50,50))"
434             << "<Unknown File>:1: ReferenceError: Can't find variable: resizeContent"
435             << "";
436
437     QTest::newRow("returnToBounds") << "Component.onCompleted: returnToBounds()"
438             << "<Unknown File>:1: ReferenceError: Can't find variable: returnToBounds"
439             << "";
440
441 }
442
443 void tst_qdeclarativeflickable::wheel()
444 {
445     QDeclarativeView *canvas = new QDeclarativeView;
446     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/wheel.qml"));
447     canvas->show();
448     canvas->setFocus();
449     QVERIFY(canvas->rootObject() != 0);
450
451     QDeclarative1Flickable *flick = canvas->rootObject()->findChild<QDeclarative1Flickable*>("flick");
452     QVERIFY(flick != 0);
453
454     QGraphicsScene *scene = canvas->scene();
455     QGraphicsSceneWheelEvent event(QEvent::GraphicsSceneWheel);
456     event.setScenePos(QPointF(200, 200));
457     event.setDelta(-120);
458     event.setOrientation(Qt::Vertical);
459     event.setAccepted(false);
460     QApplication::sendEvent(scene, &event);
461
462     QTRY_VERIFY(flick->contentY() > 0);
463     QVERIFY(flick->contentX() == 0);
464
465     flick->setContentY(0);
466     QVERIFY(flick->contentY() == 0);
467
468     event.setScenePos(QPointF(200, 200));
469     event.setDelta(-120);
470     event.setOrientation(Qt::Horizontal);
471     event.setAccepted(false);
472     QApplication::sendEvent(scene, &event);
473
474     QTRY_VERIFY(flick->contentX() > 0);
475     QVERIFY(flick->contentY() == 0);
476
477     delete canvas;
478 }
479
480 void tst_qdeclarativeflickable::disabled()
481 {
482     QDeclarativeView *canvas = new QDeclarativeView;
483     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/disabled.qml"));
484     canvas->show();
485     canvas->setFocus();
486     QVERIFY(canvas->rootObject() != 0);
487
488     QDeclarative1Flickable *flick = canvas->rootObject()->findChild<QDeclarative1Flickable*>("flickable");
489     QVERIFY(flick != 0);
490
491     QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50,90)));
492
493     QMouseEvent moveEvent(QEvent::MouseMove, canvas->mapFromScene(QPoint(50, 80)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
494     QApplication::sendEvent(canvas, &moveEvent);
495
496     moveEvent = QMouseEvent(QEvent::MouseMove, canvas->mapFromScene(QPoint(50, 70)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
497     QApplication::sendEvent(canvas, &moveEvent);
498
499     moveEvent = QMouseEvent(QEvent::MouseMove, canvas->mapFromScene(QPoint(50, 60)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
500     QApplication::sendEvent(canvas, &moveEvent);
501
502     QVERIFY(flick->isMoving() == false);
503
504     QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 60)));
505
506     // verify that mouse clicks on other elements still work (QTBUG-20584)
507     QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 10)));
508     QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 10)));
509
510     QVERIFY(canvas->rootObject()->property("clicked").toBool() == true);
511 }
512
513 void tst_qdeclarativeflickable::flickVelocity()
514 {
515 #ifdef Q_WS_MAC
516     QSKIP("Producing flicks on Mac CI impossible due to timing problems");
517 #endif
518
519     QDeclarativeView *canvas = new QDeclarativeView;
520     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/flickable03.qml"));
521     canvas->show();
522     canvas->setFocus();
523     QVERIFY(canvas->rootObject() != 0);
524
525     QDeclarative1Flickable *flickable = qobject_cast<QDeclarative1Flickable*>(canvas->rootObject());
526     QVERIFY(flickable != 0);
527
528     // flick up
529     flick(canvas, QPoint(20,190), QPoint(20, 50), 200);
530     QVERIFY(flickable->verticalVelocity() > 0.0);
531     QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
532
533     // flick down
534     flick(canvas, QPoint(20,10), QPoint(20, 140), 200);
535     QVERIFY(flickable->verticalVelocity() < 0.0);
536     QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
537
538     delete canvas;
539 }
540
541 void tst_qdeclarativeflickable::flick(QGraphicsView *canvas, const QPoint &from, const QPoint &to, int duration)
542 {
543     const int pointCount = 5;
544     QPoint diff = to - from;
545
546     // send press, five equally spaced moves, and release.
547     QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(from));
548
549     for (int i = 0; i < pointCount; ++i) {
550         QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(from + (i+1)*diff/pointCount), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
551         QApplication::sendEvent(canvas->viewport(), &mv);
552         QTest::qWait(duration/pointCount);
553         QCoreApplication::processEvents();
554     }
555
556     QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(to));
557 }
558
559
560 template<typename T>
561 T *tst_qdeclarativeflickable::findItem(QGraphicsObject *parent, const QString &objectName)
562 {
563     const QMetaObject &mo = T::staticMetaObject;
564     //qDebug() << parent->childItems().count() << "children";
565     for (int i = 0; i < parent->childItems().count(); ++i) {
566         QGraphicsObject *item = qobject_cast<QGraphicsObject*>(parent->childItems().at(i));
567         if(!item)
568             continue;
569         //qDebug() << "try" << item;
570         if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
571             return static_cast<T*>(item);
572         }
573         item = findItem<T>(item, objectName);
574         if (item)
575             return static_cast<T*>(item);
576     }
577
578     return 0;
579 }
580
581 QTEST_MAIN(tst_qdeclarativeflickable)
582
583 #include "tst_qdeclarativeflickable.moc"