Doc: Moved all content in the doc directory.
[profile/ivi/qtdeclarative.git] / tests / auto / quick / qquickpincharea / tst_qquickpincharea.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtTest/QtTest>
43 #include <QtTest/QSignalSpy>
44 #include <QtGui/QStyleHints>
45 #include <qpa/qwindowsysteminterface.h>
46 #include <private/qquickpincharea_p.h>
47 #include <QtQuick/private/qquickrectangle_p.h>
48 #include <QtQuick/qquickview.h>
49 #include <QtQml/qqmlcontext.h>
50 #include "../../shared/util.h"
51
52 class tst_QQuickPinchArea: public QQmlDataTest
53 {
54     Q_OBJECT
55 public:
56     tst_QQuickPinchArea() : device(0) { }
57 private slots:
58     void initTestCase();
59     void cleanupTestCase();
60     void pinchProperties();
61     void scale();
62     void pan();
63     void retouch();
64     void transformedPinchArea_data();
65     void transformedPinchArea();
66
67 private:
68     QQuickView *createView();
69     QTouchDevice *device;
70 };
71 void tst_QQuickPinchArea::initTestCase()
72 {
73     QQmlDataTest::initTestCase();
74     if (!device) {
75         device = new QTouchDevice;
76         device->setType(QTouchDevice::TouchScreen);
77         QWindowSystemInterface::registerTouchDevice(device);
78     }
79 }
80
81 void tst_QQuickPinchArea::cleanupTestCase()
82 {
83
84 }
85 void tst_QQuickPinchArea::pinchProperties()
86 {
87     QQuickView *window = createView();
88     window->setSource(testFileUrl("pinchproperties.qml"));
89     window->show();
90     window->requestActivateWindow();
91     QVERIFY(window->rootObject() != 0);
92
93     QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
94     QQuickPinch *pinch = pinchArea->pinch();
95     QVERIFY(pinchArea != 0);
96     QVERIFY(pinch != 0);
97
98     // target
99     QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
100     QVERIFY(blackRect != 0);
101     QVERIFY(blackRect == pinch->target());
102     QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject());
103     QVERIFY(rootItem != 0);
104     QSignalSpy targetSpy(pinch, SIGNAL(targetChanged()));
105     pinch->setTarget(rootItem);
106     QCOMPARE(targetSpy.count(),1);
107     pinch->setTarget(rootItem);
108     QCOMPARE(targetSpy.count(),1);
109
110     // axis
111     QCOMPARE(pinch->axis(), QQuickPinch::XandYAxis);
112     QSignalSpy axisSpy(pinch, SIGNAL(dragAxisChanged()));
113     pinch->setAxis(QQuickPinch::XAxis);
114     QCOMPARE(pinch->axis(), QQuickPinch::XAxis);
115     QCOMPARE(axisSpy.count(),1);
116     pinch->setAxis(QQuickPinch::XAxis);
117     QCOMPARE(axisSpy.count(),1);
118
119     // minimum and maximum drag properties
120     QSignalSpy xminSpy(pinch, SIGNAL(minimumXChanged()));
121     QSignalSpy xmaxSpy(pinch, SIGNAL(maximumXChanged()));
122     QSignalSpy yminSpy(pinch, SIGNAL(minimumYChanged()));
123     QSignalSpy ymaxSpy(pinch, SIGNAL(maximumYChanged()));
124
125     QCOMPARE(pinch->xmin(), 0.0);
126     QCOMPARE(pinch->xmax(), rootItem->width()-blackRect->width());
127     QCOMPARE(pinch->ymin(), 0.0);
128     QCOMPARE(pinch->ymax(), rootItem->height()-blackRect->height());
129
130     pinch->setXmin(10);
131     pinch->setXmax(10);
132     pinch->setYmin(10);
133     pinch->setYmax(10);
134
135     QCOMPARE(pinch->xmin(), 10.0);
136     QCOMPARE(pinch->xmax(), 10.0);
137     QCOMPARE(pinch->ymin(), 10.0);
138     QCOMPARE(pinch->ymax(), 10.0);
139
140     QCOMPARE(xminSpy.count(),1);
141     QCOMPARE(xmaxSpy.count(),1);
142     QCOMPARE(yminSpy.count(),1);
143     QCOMPARE(ymaxSpy.count(),1);
144
145     pinch->setXmin(10);
146     pinch->setXmax(10);
147     pinch->setYmin(10);
148     pinch->setYmax(10);
149
150     QCOMPARE(xminSpy.count(),1);
151     QCOMPARE(xmaxSpy.count(),1);
152     QCOMPARE(yminSpy.count(),1);
153     QCOMPARE(ymaxSpy.count(),1);
154
155     // minimum and maximum scale properties
156     QSignalSpy scaleMinSpy(pinch, SIGNAL(minimumScaleChanged()));
157     QSignalSpy scaleMaxSpy(pinch, SIGNAL(maximumScaleChanged()));
158
159     QCOMPARE(pinch->minimumScale(), 1.0);
160     QCOMPARE(pinch->maximumScale(), 2.0);
161
162     pinch->setMinimumScale(0.5);
163     pinch->setMaximumScale(1.5);
164
165     QCOMPARE(pinch->minimumScale(), 0.5);
166     QCOMPARE(pinch->maximumScale(), 1.5);
167
168     QCOMPARE(scaleMinSpy.count(),1);
169     QCOMPARE(scaleMaxSpy.count(),1);
170
171     pinch->setMinimumScale(0.5);
172     pinch->setMaximumScale(1.5);
173
174     QCOMPARE(scaleMinSpy.count(),1);
175     QCOMPARE(scaleMaxSpy.count(),1);
176
177     // minimum and maximum rotation properties
178     QSignalSpy rotMinSpy(pinch, SIGNAL(minimumRotationChanged()));
179     QSignalSpy rotMaxSpy(pinch, SIGNAL(maximumRotationChanged()));
180
181     QCOMPARE(pinch->minimumRotation(), 0.0);
182     QCOMPARE(pinch->maximumRotation(), 90.0);
183
184     pinch->setMinimumRotation(-90.0);
185     pinch->setMaximumRotation(45.0);
186
187     QCOMPARE(pinch->minimumRotation(), -90.0);
188     QCOMPARE(pinch->maximumRotation(), 45.0);
189
190     QCOMPARE(rotMinSpy.count(),1);
191     QCOMPARE(rotMaxSpy.count(),1);
192
193     pinch->setMinimumRotation(-90.0);
194     pinch->setMaximumRotation(45.0);
195
196     QCOMPARE(rotMinSpy.count(),1);
197     QCOMPARE(rotMaxSpy.count(),1);
198
199     delete window;
200 }
201
202 QTouchEvent::TouchPoint makeTouchPoint(int id, QPoint p, QQuickView *v, QQuickItem *i)
203 {
204     QTouchEvent::TouchPoint touchPoint(id);
205     touchPoint.setPos(i->mapFromScene(p));
206     touchPoint.setScreenPos(v->mapToGlobal(p));
207     touchPoint.setScenePos(p);
208     return touchPoint;
209 }
210
211 void tst_QQuickPinchArea::scale()
212 {
213     QQuickView *window = createView();
214     window->setSource(testFileUrl("pinchproperties.qml"));
215     window->show();
216     window->requestActivateWindow();
217     QVERIFY(QTest::qWaitForWindowActive(window));
218     QVERIFY(window->rootObject() != 0);
219     qApp->processEvents();
220
221     QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
222     QQuickPinch *pinch = pinchArea->pinch();
223     QVERIFY(pinchArea != 0);
224     QVERIFY(pinch != 0);
225
226     QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
227     QVERIFY(root != 0);
228
229     // target
230     QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
231     QVERIFY(blackRect != 0);
232
233     QPoint p1(80, 80);
234     QPoint p2(100, 100);
235     {
236         QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
237         pinchSequence.press(0, p1, window).commit();
238         // In order for the stationary point to remember its previous position,
239         // we have to reuse the same pinchSequence object.  Otherwise if we let it
240         // be destroyed and then start a new sequence, point 0 will default to being
241         // stationary at 0, 0, and PinchArea will filter out that touchpoint because
242         // it is outside its bounds.
243         pinchSequence.stationary(0).press(1, p2, window).commit();
244         p1 -= QPoint(10,10);
245         p2 += QPoint(10,10);
246         pinchSequence.move(0, p1,window).move(1, p2,window).commit();
247
248         QCOMPARE(root->property("scale").toReal(), 1.0);
249         QVERIFY(root->property("pinchActive").toBool());
250
251         p1 -= QPoint(10,10);
252         p2 += QPoint(10,10);
253         pinchSequence.move(0, p1,window).move(1, p2,window).commit();
254
255         QCOMPARE(root->property("scale").toReal(), 1.5);
256         QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50
257         QCOMPARE(blackRect->scale(), 1.5);
258     }
259
260     // scale beyond bound
261     p1 -= QPoint(50,50);
262     p2 += QPoint(50,50);
263     {
264         QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
265         pinchSequence.move(0, p1, window).move(1, p2, window).commit();
266         QCOMPARE(blackRect->scale(), 2.0);
267         pinchSequence.release(0, p1, window).release(1, p2, window).commit();
268     }
269     QVERIFY(!root->property("pinchActive").toBool());
270
271     delete window;
272 }
273
274 void tst_QQuickPinchArea::pan()
275 {
276     QQuickView *window = createView();
277     window->setSource(testFileUrl("pinchproperties.qml"));
278     window->show();
279     window->requestActivateWindow();
280     QVERIFY(QTest::qWaitForWindowActive(window));
281     QVERIFY(window->rootObject() != 0);
282     qApp->processEvents();
283
284     QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
285     QQuickPinch *pinch = pinchArea->pinch();
286     QVERIFY(pinchArea != 0);
287     QVERIFY(pinch != 0);
288
289     QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
290     QVERIFY(root != 0);
291
292     // target
293     QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
294     QVERIFY(blackRect != 0);
295
296     QPoint p1(80, 80);
297     QPoint p2(100, 100);
298     {
299         QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
300         pinchSequence.press(0, p1, window).commit();
301         // In order for the stationary point to remember its previous position,
302         // we have to reuse the same pinchSequence object.
303         pinchSequence.stationary(0).press(1, p2, window).commit();
304         p1 += QPoint(10,10);
305         p2 += QPoint(10,10);
306         pinchSequence.move(0, p1,window).move(1, p2,window).commit();
307
308         QCOMPARE(root->property("scale").toReal(), 1.0);
309         QVERIFY(root->property("pinchActive").toBool());
310
311         p1 += QPoint(10,10);
312         p2 += QPoint(10,10);
313         pinchSequence.move(0, p1,window).move(1, p2,window).commit();
314     }
315
316     QCOMPARE(root->property("center").toPointF(), QPointF(60, 60)); // blackrect is at 50,50
317     QCOMPARE(blackRect->x(), 60.0);
318     QCOMPARE(blackRect->y(), 60.0);
319
320     // pan x beyond bound
321     p1 += QPoint(100,100);
322     p2 += QPoint(100,100);
323     QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
324
325     QCOMPARE(blackRect->x(), 140.0);
326     QCOMPARE(blackRect->y(), 160.0);
327
328     QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window);
329     QVERIFY(!root->property("pinchActive").toBool());
330
331     delete window;
332 }
333
334 // test pinch, release one point, touch again to continue pinch
335 void tst_QQuickPinchArea::retouch()
336 {
337     QQuickView *window = createView();
338     window->setSource(testFileUrl("pinchproperties.qml"));
339     window->show();
340     window->requestActivateWindow();
341     QVERIFY(QTest::qWaitForWindowActive(window));
342     QVERIFY(window->rootObject() != 0);
343     qApp->processEvents();
344
345     QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
346     QQuickPinch *pinch = pinchArea->pinch();
347     QVERIFY(pinchArea != 0);
348     QVERIFY(pinch != 0);
349
350     QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
351     QVERIFY(root != 0);
352
353     QSignalSpy startedSpy(pinchArea, SIGNAL(pinchStarted(QQuickPinchEvent *)));
354     QSignalSpy finishedSpy(pinchArea, SIGNAL(pinchFinished(QQuickPinchEvent *)));
355
356     // target
357     QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
358     QVERIFY(blackRect != 0);
359
360     QPoint p1(80, 80);
361     QPoint p2(100, 100);
362     {
363         QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
364         pinchSequence.press(0, p1, window).commit();
365         // In order for the stationary point to remember its previous position,
366         // we have to reuse the same pinchSequence object.
367         pinchSequence.stationary(0).press(1, p2, window).commit();
368         p1 -= QPoint(10,10);
369         p2 += QPoint(10,10);
370         pinchSequence.move(0, p1,window).move(1, p2,window).commit();
371
372         QCOMPARE(root->property("scale").toReal(), 1.0);
373         QVERIFY(root->property("pinchActive").toBool());
374
375         p1 -= QPoint(10,10);
376         p2 += QPoint(10,10);
377         pinchSequence.move(0, p1,window).move(1, p2,window).commit();
378
379         QCOMPARE(startedSpy.count(), 1);
380
381         QCOMPARE(root->property("scale").toReal(), 1.5);
382         QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50
383         QCOMPARE(blackRect->scale(), 1.5);
384
385         QCOMPARE(window->rootObject()->property("pointCount").toInt(), 2);
386
387         QCOMPARE(startedSpy.count(), 1);
388         QCOMPARE(finishedSpy.count(), 0);
389
390         // Hold down the first finger but release the second one
391         pinchSequence.stationary(0).release(1, p2, window).commit();
392
393         QCOMPARE(startedSpy.count(), 1);
394         QCOMPARE(finishedSpy.count(), 0);
395
396         QCOMPARE(window->rootObject()->property("pointCount").toInt(), 1);
397
398         // Keep holding down the first finger and re-touch the second one, then move them both
399         pinchSequence.stationary(0).press(1, p2, window).commit();
400         p1 -= QPoint(10,10);
401         p2 += QPoint(10,10);
402         pinchSequence.move(0, p1, window).move(1, p2, window).commit();
403
404         // Lifting and retouching results in onPinchStarted being called again
405         QCOMPARE(startedSpy.count(), 2);
406         QCOMPARE(finishedSpy.count(), 0);
407
408         QCOMPARE(window->rootObject()->property("pointCount").toInt(), 2);
409
410         pinchSequence.release(0, p1, window).release(1, p2, window).commit();
411
412         QVERIFY(!root->property("pinchActive").toBool());
413         QCOMPARE(startedSpy.count(), 2);
414         QCOMPARE(finishedSpy.count(), 1);
415     }
416
417     delete window;
418 }
419
420 void tst_QQuickPinchArea::transformedPinchArea_data()
421 {
422     QTest::addColumn<QPoint>("p1");
423     QTest::addColumn<QPoint>("p2");
424     QTest::addColumn<bool>("shouldPinch");
425
426     QTest::newRow("checking inner pinch 1")
427         << QPoint(200, 140) << QPoint(200, 260) << true;
428
429     QTest::newRow("checking inner pinch 2")
430         << QPoint(140, 200) << QPoint(200, 140) << true;
431
432     QTest::newRow("checking inner pinch 3")
433         << QPoint(140, 200) << QPoint(260, 200) << true;
434
435     QTest::newRow("checking outer pinch 1")
436         << QPoint(140, 140) << QPoint(260, 260) << false;
437
438     QTest::newRow("checking outer pinch 2")
439         << QPoint(140, 140) << QPoint(200, 200) << false;
440
441     QTest::newRow("checking outer pinch 3")
442         << QPoint(140, 260) << QPoint(260, 260) << false;
443 }
444
445 void tst_QQuickPinchArea::transformedPinchArea()
446 {
447     QFETCH(QPoint, p1);
448     QFETCH(QPoint, p2);
449     QFETCH(bool, shouldPinch);
450
451     QQuickView *view = createView();
452     view->setSource(testFileUrl("transformedPinchArea.qml"));
453     view->show();
454     view->requestActivateWindow();
455     QVERIFY(QTest::qWaitForWindowActive(view));
456     QVERIFY(view->rootObject() != 0);
457     qApp->processEvents();
458
459     QQuickPinchArea *pinchArea = view->rootObject()->findChild<QQuickPinchArea*>("pinchArea");
460     QVERIFY(pinchArea != 0);
461
462     const int threshold = qApp->styleHints()->startDragDistance();
463
464     {
465         QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(view, device);
466         // start pinch
467         pinchSequence.press(0, p1, view).commit();
468         // In order for the stationary point to remember its previous position,
469         // we have to reuse the same pinchSequence object.
470         pinchSequence.stationary(0).press(1, p2, view).commit();
471         pinchSequence.stationary(0).move(1, p2 + QPoint(threshold * 2, 0), view).commit();
472         QCOMPARE(pinchArea->property("pinching").toBool(), shouldPinch);
473
474         // release pinch
475         pinchSequence.release(0, p1, view).release(1, p2, view).commit();
476         QCOMPARE(pinchArea->property("pinching").toBool(), false);
477     }
478
479     delete view;
480 }
481
482 QQuickView *tst_QQuickPinchArea::createView()
483 {
484     QQuickView *window = new QQuickView(0);
485     window->setGeometry(0,0,240,320);
486
487     return window;
488 }
489
490 QTEST_MAIN(tst_QQuickPinchArea)
491
492 #include "tst_qquickpincharea.moc"