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