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