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