a90870ce809c1bdae139cfca9ee1ae252113cfc3
[profile/ivi/qtdeclarative.git] / tests / auto / qtquick2 / qquickflickable / tst_qquickflickable.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 <QtQuick/qquickview.h>
46 #include <private/qquickflickable_p.h>
47 #include <private/qdeclarativevaluetype_p.h>
48 #include <math.h>
49 #include "../../shared/util.h"
50 #include <QtOpenGL/QGLShaderProgram>
51
52 class tst_qquickflickable : public QDeclarativeDataTest
53 {
54     Q_OBJECT
55 public:
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 nestedPressDelay();
67     void flickableDirection();
68     void resizeContent();
69     void returnToBounds();
70     void wheel();
71     void movingAndDragging();
72     void disabled();
73     void flickVelocity();
74     void margins();
75
76 private:
77     QDeclarativeEngine engine;
78
79     void flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration);
80     template<typename T>
81     T *findItem(QQuickItem *parent, const QString &objectName);
82 };
83
84 void tst_qquickflickable::create()
85 {
86     QDeclarativeEngine engine;
87     QDeclarativeComponent c(&engine, testFileUrl("flickable01.qml"));
88     QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
89
90     QVERIFY(obj != 0);
91     QCOMPARE(obj->isAtXBeginning(), true);
92     QCOMPARE(obj->isAtXEnd(), false);
93     QCOMPARE(obj->isAtYBeginning(), true);
94     QCOMPARE(obj->isAtYEnd(), false);
95     QCOMPARE(obj->contentX(), 0.);
96     QCOMPARE(obj->contentY(), 0.);
97
98     QCOMPARE(obj->horizontalVelocity(), 0.);
99     QCOMPARE(obj->verticalVelocity(), 0.);
100
101     QCOMPARE(obj->isInteractive(), true);
102     QCOMPARE(obj->boundsBehavior(), QQuickFlickable::DragAndOvershootBounds);
103     QCOMPARE(obj->pressDelay(), 0);
104     QCOMPARE(obj->maximumFlickVelocity(), 2500.);
105
106     delete obj;
107 }
108
109 void tst_qquickflickable::horizontalViewportSize()
110 {
111     QDeclarativeEngine engine;
112     QDeclarativeComponent c(&engine, testFileUrl("flickable02.qml"));
113     QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
114
115     QVERIFY(obj != 0);
116     QCOMPARE(obj->contentWidth(), 800.);
117     QCOMPARE(obj->contentHeight(), 300.);
118     QCOMPARE(obj->isAtXBeginning(), true);
119     QCOMPARE(obj->isAtXEnd(), false);
120     QCOMPARE(obj->isAtYBeginning(), true);
121     QCOMPARE(obj->isAtYEnd(), false);
122
123     delete obj;
124 }
125
126 void tst_qquickflickable::verticalViewportSize()
127 {
128     QDeclarativeEngine engine;
129     QDeclarativeComponent c(&engine, testFileUrl("flickable03.qml"));
130     QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
131
132     QVERIFY(obj != 0);
133     QCOMPARE(obj->contentWidth(), 200.);
134     QCOMPARE(obj->contentHeight(), 1200.);
135     QCOMPARE(obj->isAtXBeginning(), true);
136     QCOMPARE(obj->isAtXEnd(), false);
137     QCOMPARE(obj->isAtYBeginning(), true);
138     QCOMPARE(obj->isAtYEnd(), false);
139
140     delete obj;
141 }
142
143 void tst_qquickflickable::properties()
144 {
145     QDeclarativeEngine engine;
146     QDeclarativeComponent c(&engine, testFileUrl("flickable04.qml"));
147     QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
148
149     QVERIFY(obj != 0);
150     QCOMPARE(obj->isInteractive(), false);
151     QCOMPARE(obj->boundsBehavior(), QQuickFlickable::StopAtBounds);
152     QCOMPARE(obj->pressDelay(), 200);
153     QCOMPARE(obj->maximumFlickVelocity(), 2000.);
154
155     QVERIFY(obj->property("ok").toBool() == false);
156     QMetaObject::invokeMethod(obj, "check");
157     QVERIFY(obj->property("ok").toBool() == true);
158
159     delete obj;
160 }
161
162 void tst_qquickflickable::boundsBehavior()
163 {
164     QDeclarativeComponent component(&engine);
165     component.setData("import QtQuick 2.0; Flickable { boundsBehavior: Flickable.StopAtBounds }", QUrl::fromLocalFile(""));
166     QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
167     QSignalSpy spy(flickable, SIGNAL(boundsBehaviorChanged()));
168
169     QVERIFY(flickable);
170     QVERIFY(flickable->boundsBehavior() == QQuickFlickable::StopAtBounds);
171
172     flickable->setBoundsBehavior(QQuickFlickable::DragAndOvershootBounds);
173     QVERIFY(flickable->boundsBehavior() == QQuickFlickable::DragAndOvershootBounds);
174     QCOMPARE(spy.count(),1);
175     flickable->setBoundsBehavior(QQuickFlickable::DragAndOvershootBounds);
176     QCOMPARE(spy.count(),1);
177
178     flickable->setBoundsBehavior(QQuickFlickable::DragOverBounds);
179     QVERIFY(flickable->boundsBehavior() == QQuickFlickable::DragOverBounds);
180     QCOMPARE(spy.count(),2);
181     flickable->setBoundsBehavior(QQuickFlickable::DragOverBounds);
182     QCOMPARE(spy.count(),2);
183
184     flickable->setBoundsBehavior(QQuickFlickable::StopAtBounds);
185     QVERIFY(flickable->boundsBehavior() == QQuickFlickable::StopAtBounds);
186     QCOMPARE(spy.count(),3);
187     flickable->setBoundsBehavior(QQuickFlickable::StopAtBounds);
188     QCOMPARE(spy.count(),3);
189 }
190
191 void tst_qquickflickable::maximumFlickVelocity()
192 {
193     QDeclarativeComponent component(&engine);
194     component.setData("import QtQuick 2.0; Flickable { maximumFlickVelocity: 1.0; }", QUrl::fromLocalFile(""));
195     QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
196     QSignalSpy spy(flickable, SIGNAL(maximumFlickVelocityChanged()));
197
198     QVERIFY(flickable);
199     QCOMPARE(flickable->maximumFlickVelocity(), 1.0);
200
201     flickable->setMaximumFlickVelocity(2.0);
202     QCOMPARE(flickable->maximumFlickVelocity(), 2.0);
203     QCOMPARE(spy.count(),1);
204     flickable->setMaximumFlickVelocity(2.0);
205     QCOMPARE(spy.count(),1);
206 }
207
208 void tst_qquickflickable::flickDeceleration()
209 {
210     QDeclarativeComponent component(&engine);
211     component.setData("import QtQuick 2.0; Flickable { flickDeceleration: 1.0; }", QUrl::fromLocalFile(""));
212     QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
213     QSignalSpy spy(flickable, SIGNAL(flickDecelerationChanged()));
214
215     QVERIFY(flickable);
216     QCOMPARE(flickable->flickDeceleration(), 1.0);
217
218     flickable->setFlickDeceleration(2.0);
219     QCOMPARE(flickable->flickDeceleration(), 2.0);
220     QCOMPARE(spy.count(),1);
221     flickable->setFlickDeceleration(2.0);
222     QCOMPARE(spy.count(),1);
223 }
224
225 void tst_qquickflickable::pressDelay()
226 {
227     QDeclarativeComponent component(&engine);
228     component.setData("import QtQuick 2.0; Flickable { pressDelay: 100; }", QUrl::fromLocalFile(""));
229     QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
230     QSignalSpy spy(flickable, SIGNAL(pressDelayChanged()));
231
232     QVERIFY(flickable);
233     QCOMPARE(flickable->pressDelay(), 100);
234
235     flickable->setPressDelay(200);
236     QCOMPARE(flickable->pressDelay(), 200);
237     QCOMPARE(spy.count(),1);
238     flickable->setPressDelay(200);
239     QCOMPARE(spy.count(),1);
240 }
241
242 // QTBUG-17361
243 void tst_qquickflickable::nestedPressDelay()
244 {
245     QQuickView *canvas = new QQuickView;
246     canvas->setSource(testFileUrl("nestedPressDelay.qml"));
247     canvas->show();
248     canvas->requestActivateWindow();
249     QVERIFY(canvas->rootObject() != 0);
250
251     QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(canvas->rootObject());
252     QVERIFY(outer != 0);
253
254     QQuickFlickable *inner = canvas->rootObject()->findChild<QQuickFlickable*>("innerFlickable");
255     QVERIFY(inner != 0);
256
257     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(150, 150));
258     // the MouseArea is not pressed immediately
259     QVERIFY(outer->property("pressed").toBool() == false);
260
261     // The outer pressDelay will prevail (50ms, vs. 10sec)
262     // QTRY_VERIFY() has 5sec timeout, so will timeout well within 10sec.
263     QTRY_VERIFY(outer->property("pressed").toBool() == true);
264
265     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(150, 150));
266
267     delete canvas;
268 }
269
270 void tst_qquickflickable::flickableDirection()
271 {
272     QDeclarativeComponent component(&engine);
273     component.setData("import QtQuick 2.0; Flickable { flickableDirection: Flickable.VerticalFlick; }", QUrl::fromLocalFile(""));
274     QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(component.create());
275     QSignalSpy spy(flickable, SIGNAL(flickableDirectionChanged()));
276
277     QVERIFY(flickable);
278     QCOMPARE(flickable->flickableDirection(), QQuickFlickable::VerticalFlick);
279
280     flickable->setFlickableDirection(QQuickFlickable::HorizontalAndVerticalFlick);
281     QCOMPARE(flickable->flickableDirection(), QQuickFlickable::HorizontalAndVerticalFlick);
282     QCOMPARE(spy.count(),1);
283
284     flickable->setFlickableDirection(QQuickFlickable::AutoFlickDirection);
285     QCOMPARE(flickable->flickableDirection(), QQuickFlickable::AutoFlickDirection);
286     QCOMPARE(spy.count(),2);
287
288     flickable->setFlickableDirection(QQuickFlickable::HorizontalFlick);
289     QCOMPARE(flickable->flickableDirection(), QQuickFlickable::HorizontalFlick);
290     QCOMPARE(spy.count(),3);
291
292     flickable->setFlickableDirection(QQuickFlickable::HorizontalFlick);
293     QCOMPARE(flickable->flickableDirection(), QQuickFlickable::HorizontalFlick);
294     QCOMPARE(spy.count(),3);
295 }
296
297 // QtQuick 1.1
298 void tst_qquickflickable::resizeContent()
299 {
300     QDeclarativeEngine engine;
301     QDeclarativeComponent c(&engine, testFileUrl("resize.qml"));
302     QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
303     QQuickFlickable *obj = findItem<QQuickFlickable>(root, "flick");
304
305     QVERIFY(obj != 0);
306     QCOMPARE(obj->contentX(), 0.);
307     QCOMPARE(obj->contentY(), 0.);
308     QCOMPARE(obj->contentWidth(), 300.);
309     QCOMPARE(obj->contentHeight(), 300.);
310
311     QMetaObject::invokeMethod(root, "resizeContent");
312
313     QCOMPARE(obj->contentX(), 100.);
314     QCOMPARE(obj->contentY(), 100.);
315     QCOMPARE(obj->contentWidth(), 600.);
316     QCOMPARE(obj->contentHeight(), 600.);
317
318     delete root;
319 }
320
321 // QtQuick 1.1
322 void tst_qquickflickable::returnToBounds()
323 {
324     QDeclarativeEngine engine;
325     QDeclarativeComponent c(&engine, testFileUrl("resize.qml"));
326     QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
327     QQuickFlickable *obj = findItem<QQuickFlickable>(root, "flick");
328
329     QVERIFY(obj != 0);
330     QCOMPARE(obj->contentX(), 0.);
331     QCOMPARE(obj->contentY(), 0.);
332     QCOMPARE(obj->contentWidth(), 300.);
333     QCOMPARE(obj->contentHeight(), 300.);
334
335     obj->setContentX(100);
336     obj->setContentY(400);
337     QTRY_COMPARE(obj->contentX(), 100.);
338     QTRY_COMPARE(obj->contentY(), 400.);
339
340     QMetaObject::invokeMethod(root, "returnToBounds");
341
342     QTRY_COMPARE(obj->contentX(), 0.);
343     QTRY_COMPARE(obj->contentY(), 0.);
344
345     delete root;
346 }
347
348 void tst_qquickflickable::wheel()
349 {
350     QQuickView *canvas = new QQuickView;
351     canvas->setSource(testFileUrl("wheel.qml"));
352     canvas->show();
353     canvas->requestActivateWindow();
354     QVERIFY(canvas->rootObject() != 0);
355
356     QQuickFlickable *flick = canvas->rootObject()->findChild<QQuickFlickable*>("flick");
357     QVERIFY(flick != 0);
358
359     {
360         QWheelEvent event(QPoint(200, 200), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical);
361         event.setAccepted(false);
362         QGuiApplication::sendEvent(canvas, &event);
363     }
364
365     QTRY_VERIFY(flick->contentY() > 0);
366     QVERIFY(flick->contentX() == 0);
367
368     flick->setContentY(0);
369     QVERIFY(flick->contentY() == 0);
370
371     {
372         QWheelEvent event(QPoint(200, 200), -120, Qt::NoButton, Qt::NoModifier, Qt::Horizontal);
373         event.setAccepted(false);
374         QGuiApplication::sendEvent(canvas, &event);
375     }
376
377     QTRY_VERIFY(flick->contentX() > 0);
378     QVERIFY(flick->contentY() == 0);
379
380     delete canvas;
381 }
382
383 void tst_qquickflickable::movingAndDragging()
384 {
385     QQuickView *canvas = new QQuickView;
386     canvas->setSource(testFileUrl("flickable03.qml"));
387     canvas->show();
388     canvas->requestActivateWindow();
389     QTest::qWaitForWindowShown(canvas);
390     QVERIFY(canvas->rootObject() != 0);
391
392     QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject());
393     QVERIFY(flickable != 0);
394
395     QSignalSpy vDragSpy(flickable, SIGNAL(draggingVerticallyChanged()));
396     QSignalSpy hDragSpy(flickable, SIGNAL(draggingHorizontallyChanged()));
397     QSignalSpy dragSpy(flickable, SIGNAL(draggingChanged()));
398     QSignalSpy vMoveSpy(flickable, SIGNAL(movingVerticallyChanged()));
399     QSignalSpy hMoveSpy(flickable, SIGNAL(movingHorizontallyChanged()));
400     QSignalSpy moveSpy(flickable, SIGNAL(movingChanged()));
401     QSignalSpy dragStartSpy(flickable, SIGNAL(dragStarted()));
402     QSignalSpy dragEndSpy(flickable, SIGNAL(dragEnded()));
403
404     //Vertical
405     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 90));
406
407     QTest::mouseMove(canvas, QPoint(50, 80));
408     QTest::mouseMove(canvas, QPoint(50, 70));
409     QTest::mouseMove(canvas, QPoint(50, 60));
410
411     QMouseEvent moveEvent(QEvent::MouseMove, QPoint(50, 80), Qt::LeftButton, Qt::LeftButton, 0);
412
413     QVERIFY(!flickable->isDraggingHorizontally());
414     QVERIFY(flickable->isDraggingVertically());
415     QVERIFY(flickable->isDragging());
416     QCOMPARE(vDragSpy.count(), 1);
417     QCOMPARE(dragSpy.count(), 1);
418     QCOMPARE(hDragSpy.count(), 0);
419     QCOMPARE(dragStartSpy.count(), 1);
420     QCOMPARE(dragEndSpy.count(), 0);
421
422     QVERIFY(!flickable->isMovingHorizontally());
423     QVERIFY(flickable->isMovingVertically());
424     QVERIFY(flickable->isMoving());
425     QCOMPARE(vMoveSpy.count(), 1);
426     QCOMPARE(moveSpy.count(), 1);
427     QCOMPARE(hMoveSpy.count(), 0);
428
429     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 60));
430
431     QTRY_VERIFY(!flickable->isDraggingVertically());
432     QVERIFY(!flickable->isDragging());
433     QCOMPARE(vDragSpy.count(), 2);
434     QCOMPARE(dragSpy.count(), 2);
435     QCOMPARE(hDragSpy.count(), 0);
436     QCOMPARE(dragStartSpy.count(), 1);
437     QCOMPARE(dragEndSpy.count(), 1);
438
439     // wait for any motion to end
440     QTRY_VERIFY(flickable->isMoving() == false);
441
442     //Horizontal
443     vDragSpy.clear();
444     hDragSpy.clear();
445     dragSpy.clear();
446     vMoveSpy.clear();
447     hMoveSpy.clear();
448     moveSpy.clear();
449     dragStartSpy.clear();
450     dragEndSpy.clear();
451
452     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(90, 50));
453
454     QTest::mouseMove(canvas, QPoint(80, 50));
455     QTest::mouseMove(canvas, QPoint(70, 50));
456     QTest::mouseMove(canvas, QPoint(60, 50));
457
458     QVERIFY(flickable->isDraggingHorizontally());
459     QVERIFY(flickable->isDragging());
460     QCOMPARE(vDragSpy.count(), 0);
461     QCOMPARE(dragSpy.count(), 1);
462     QCOMPARE(hDragSpy.count(), 1);
463     QCOMPARE(dragStartSpy.count(), 1);
464     QCOMPARE(dragEndSpy.count(), 0);
465
466     QVERIFY(!flickable->isMovingVertically());
467     QVERIFY(flickable->isMovingHorizontally());
468     QVERIFY(flickable->isMoving());
469     QCOMPARE(vMoveSpy.count(), 0);
470     QCOMPARE(moveSpy.count(), 1);
471     QCOMPARE(hMoveSpy.count(), 1);
472
473     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(60, 50));
474
475     QTRY_VERIFY(!flickable->isDraggingHorizontally());
476     QVERIFY(!flickable->isDragging());
477     QCOMPARE(vDragSpy.count(), 0);
478     QCOMPARE(dragSpy.count(), 2);
479     QCOMPARE(hDragSpy.count(), 2);
480     QCOMPARE(dragStartSpy.count(), 1);
481     QCOMPARE(dragEndSpy.count(), 1);
482
483     // Don't test moving because a flick could occur
484
485     delete canvas;
486 }
487
488 void tst_qquickflickable::disabled()
489 {
490     QQuickView *canvas = new QQuickView;
491     canvas->setSource(testFileUrl("disabled.qml"));
492     canvas->show();
493     canvas->requestActivateWindow();
494     QVERIFY(canvas->rootObject() != 0);
495
496     QQuickFlickable *flick = canvas->rootObject()->findChild<QQuickFlickable*>("flickable");
497     QVERIFY(flick != 0);
498
499     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 90));
500
501     QTest::mouseMove(canvas, QPoint(50, 80));
502     QTest::mouseMove(canvas, QPoint(50, 70));
503     QTest::mouseMove(canvas, QPoint(50, 60));
504
505     QVERIFY(flick->isMoving() == false);
506
507     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 60));
508
509     // verify that mouse clicks on other elements still work (QTBUG-20584)
510     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 10));
511     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 10));
512
513     QTRY_VERIFY(canvas->rootObject()->property("clicked").toBool() == true);
514 }
515
516 void tst_qquickflickable::flickVelocity()
517 {
518 #ifdef Q_OS_MAC
519     QSKIP("Producing flicks on Mac CI impossible due to timing problems");
520 #endif
521
522     QQuickView *canvas = new QQuickView;
523     canvas->setSource(testFileUrl("flickable03.qml"));
524     canvas->show();
525     canvas->requestActivateWindow();
526     QVERIFY(canvas->rootObject() != 0);
527
528     QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject());
529     QVERIFY(flickable != 0);
530
531     // flick up
532     flick(canvas, QPoint(20,190), QPoint(20, 50), 200);
533     QVERIFY(flickable->verticalVelocity() > 0.0);
534     QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
535
536     // flick down
537     flick(canvas, QPoint(20,10), QPoint(20, 140), 200);
538     QVERIFY(flickable->verticalVelocity() < 0.0);
539     QTRY_VERIFY(flickable->verticalVelocity() == 0.0);
540
541     delete canvas;
542 }
543
544 void tst_qquickflickable::margins()
545 {
546     QDeclarativeEngine engine;
547     QDeclarativeComponent c(&engine, testFileUrl("margins.qml"));
548     QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
549     QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(root);
550     QVERIFY(obj != 0);
551
552     // starting state
553     QCOMPARE(obj->contentX(), -40.);
554     QCOMPARE(obj->contentY(), -20.);
555     QCOMPARE(obj->contentWidth(), 1600.);
556     QCOMPARE(obj->contentHeight(), 600.);
557     QCOMPARE(obj->xOrigin(), 0.);
558     QCOMPARE(obj->yOrigin(), 0.);
559
560     // Reduce left margin
561     obj->setLeftMargin(30);
562     QTRY_COMPARE(obj->contentX(), -30.);
563
564     // Reduce top margin
565     obj->setTopMargin(20);
566     QTRY_COMPARE(obj->contentY(), -20.);
567
568     // position to the far right, including margin
569     obj->setContentX(1600 + 50 - obj->width());
570     obj->returnToBounds();
571     QTest::qWait(200);
572     QCOMPARE(obj->contentX(), 1600. + 50. - obj->width());
573
574     // position beyond the far right, including margin
575     obj->setContentX(1600 + 50 - obj->width() + 1.);
576     obj->returnToBounds();
577     QTRY_COMPARE(obj->contentX(), 1600. + 50. - obj->width());
578
579     // Reduce right margin
580     obj->setRightMargin(40);
581     QTRY_COMPARE(obj->contentX(), 1600. + 40. - obj->width());
582     QCOMPARE(obj->contentWidth(), 1600.);
583
584     // position to the far bottom, including margin
585     obj->setContentY(600 + 30 - obj->height());
586     obj->returnToBounds();
587     QTest::qWait(200);
588     QCOMPARE(obj->contentY(), 600. + 30. - obj->height());
589
590     // position beyond the far bottom, including margin
591     obj->setContentY(600 + 30 - obj->height() + 1.);
592     obj->returnToBounds();
593     QTRY_COMPARE(obj->contentY(), 600. + 30. - obj->height());
594
595     // Reduce bottom margin
596     obj->setBottomMargin(20);
597     QTRY_COMPARE(obj->contentY(), 600. + 20. - obj->height());
598     QCOMPARE(obj->contentHeight(), 600.);
599
600     delete root;
601 }
602
603 void tst_qquickflickable::flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration)
604 {
605     const int pointCount = 5;
606     QPoint diff = to - from;
607
608     // send press, five equally spaced moves, and release.
609     QTest::mousePress(canvas, Qt::LeftButton, 0, from);
610
611     for (int i = 0; i < pointCount; ++i) {
612         QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
613         QGuiApplication::sendEvent(canvas, &mv);
614         QTest::qWait(duration/pointCount);
615         QCoreApplication::processEvents();
616     }
617
618     QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
619 }
620
621 template<typename T>
622 T *tst_qquickflickable::findItem(QQuickItem *parent, const QString &objectName)
623 {
624     const QMetaObject &mo = T::staticMetaObject;
625     //qDebug() << parent->childItems().count() << "children";
626     for (int i = 0; i < parent->childItems().count(); ++i) {
627         QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
628         if (!item)
629             continue;
630         //qDebug() << "try" << item;
631         if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
632             return static_cast<T*>(item);
633         }
634         item = findItem<T>(item, objectName);
635         if (item)
636             return static_cast<T*>(item);
637     }
638
639     return 0;
640 }
641
642 QTEST_MAIN(tst_qquickflickable)
643
644 #include "tst_qquickflickable.moc"