QQuickCanvas renames
[profile/ivi/qtdeclarative.git] / tests / auto / quick / qquickitem2 / tst_qquickitem.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 #include <qtest.h>
42 #include <QtTest/QSignalSpy>
43 #include <QtQml/qqmlengine.h>
44 #include <QtQml/qqmlcomponent.h>
45 #include <QtQml/qqmlcontext.h>
46 #include <QtQuick/qquickview.h>
47 #include <QtGui/private/qinputmethod_p.h>
48 #include <QtQuick/private/qquickrectangle_p.h>
49 #include <QtQuick/private/qquicktextinput_p.h>
50 #include <private/qquickitem_p.h>
51 #include "../../shared/util.h"
52 #include "../shared/visualtestutil.h"
53 #include "../../shared/platforminputcontext.h"
54
55 using namespace QQuickVisualTestUtil;
56
57 class tst_QQuickItem : public QQmlDataTest
58 {
59     Q_OBJECT
60 public:
61     tst_QQuickItem();
62
63 private slots:
64     void initTestCase();
65     void cleanup();
66
67     void keys();
68     void keysProcessingOrder();
69     void keysim();
70     void keyNavigation();
71     void keyNavigation_RightToLeft();
72     void keyNavigation_skipNotVisible();
73     void keyNavigation_implicitSetting();
74     void layoutMirroring();
75     void layoutMirroringIllegalParent();
76     void smooth();
77     void clip();
78     void mapCoordinates();
79     void mapCoordinates_data();
80     void mapCoordinatesRect();
81     void mapCoordinatesRect_data();
82     void propertyChanges();
83     void transforms();
84     void transforms_data();
85     void childrenRect();
86     void childrenRectBug();
87     void childrenRectBug2();
88     void childrenRectBug3();
89
90     void childrenProperty();
91     void resourcesProperty();
92
93     void transformCrash();
94     void implicitSize();
95     void qtbug_16871();
96     void visibleChildren();
97     void parentLoop();
98     void contains_data();
99     void contains();
100
101 private:
102     QQmlEngine engine;
103 };
104
105 class KeysTestObject : public QObject
106 {
107     Q_OBJECT
108
109     Q_PROPERTY(bool processLast READ processLast NOTIFY processLastChanged)
110
111 public:
112     KeysTestObject() : mKey(0), mModifiers(0), mForwardedKey(0), mLast(false), mNativeScanCode(0) {}
113
114     void reset() {
115         mKey = 0;
116         mText = QString();
117         mModifiers = 0;
118         mForwardedKey = 0;
119         mNativeScanCode = 0;
120     }
121
122     bool processLast() const { return mLast; }
123     void setProcessLast(bool b) {
124         if (b != mLast) {
125             mLast = b;
126             emit processLastChanged();
127         }
128     }
129
130 public slots:
131     void keyPress(int key, QString text, int modifiers) {
132         mKey = key;
133         mText = text;
134         mModifiers = modifiers;
135     }
136     void keyRelease(int key, QString text, int modifiers) {
137         mKey = key;
138         mText = text;
139         mModifiers = modifiers;
140     }
141     void forwardedKey(int key) {
142         mForwardedKey = key;
143     }
144     void specialKey(int key, QString text, quint32 nativeScanCode) {
145         mKey = key;
146         mText = text;
147         mNativeScanCode = nativeScanCode;
148     }
149
150 signals:
151     void processLastChanged();
152
153 public:
154     int mKey;
155     QString mText;
156     int mModifiers;
157     int mForwardedKey;
158     bool mLast;
159     quint32 mNativeScanCode;
160
161 private:
162 };
163
164 class KeyTestItem : public QQuickItem
165 {
166     Q_OBJECT
167 public:
168     KeyTestItem(QQuickItem *parent=0) : QQuickItem(parent), mKey(0) {}
169
170 protected:
171     void keyPressEvent(QKeyEvent *e) {
172         mKey = e->key();
173
174         if (e->key() == Qt::Key_A)
175             e->accept();
176         else
177             e->ignore();
178     }
179
180     void keyReleaseEvent(QKeyEvent *e) {
181         if (e->key() == Qt::Key_B)
182             e->accept();
183         else
184             e->ignore();
185     }
186
187 public:
188     int mKey;
189 };
190
191 QML_DECLARE_TYPE(KeyTestItem);
192
193 class HollowTestItem : public QQuickItem
194 {
195     Q_OBJECT
196     Q_PROPERTY(bool circle READ isCircle WRITE setCircle)
197     Q_PROPERTY(qreal holeRadius READ holeRadius WRITE setHoleRadius)
198
199 public:
200     HollowTestItem(QQuickItem *parent = 0)
201         : QQuickItem(parent),
202           m_isPressed(false),
203           m_isHovered(false),
204           m_isCircle(false),
205           m_holeRadius(50)
206     {
207         setAcceptHoverEvents(true);
208         setAcceptedMouseButtons(Qt::LeftButton);
209     }
210
211     bool isPressed() const { return m_isPressed; }
212     bool isHovered() const { return m_isHovered; }
213
214     bool isCircle() const { return m_isCircle; }
215     void setCircle(bool circle) { m_isCircle = circle; }
216
217     qreal holeRadius() const { return m_holeRadius; }
218     void setHoleRadius(qreal radius) { m_holeRadius = radius; }
219
220     bool contains(const QPointF &point) const {
221         const qreal w = width();
222         const qreal h = height();
223         const qreal r = m_holeRadius;
224
225         // check boundaries
226         if (!QRectF(0, 0, w, h).contains(point))
227             return false;
228
229         // square shape
230         if (!m_isCircle)
231             return !QRectF(w / 2 - r, h / 2 - r, r * 2, r * 2).contains(point);
232
233         // circle shape
234         const qreal dx = point.x() - (w / 2);
235         const qreal dy = point.y() - (h / 2);
236         const qreal dd = (dx * dx) + (dy * dy);
237         const qreal outerRadius = qMin<qreal>(w / 2, h / 2);
238         return dd > (r * r) && dd <= outerRadius * outerRadius;
239     }
240
241 protected:
242     void hoverEnterEvent(QHoverEvent *) { m_isHovered = true; }
243     void hoverLeaveEvent(QHoverEvent *) { m_isHovered = false; }
244     void mousePressEvent(QMouseEvent *) { m_isPressed = true; }
245     void mouseReleaseEvent(QMouseEvent *) { m_isPressed = false; }
246
247 private:
248     bool m_isPressed;
249     bool m_isHovered;
250     bool m_isCircle;
251     qreal m_holeRadius;
252 };
253
254 QML_DECLARE_TYPE(HollowTestItem);
255
256
257 tst_QQuickItem::tst_QQuickItem()
258 {
259 }
260
261 void tst_QQuickItem::initTestCase()
262 {
263     QQmlDataTest::initTestCase();
264     qmlRegisterType<KeyTestItem>("Test",1,0,"KeyTestItem");
265     qmlRegisterType<HollowTestItem>("Test", 1, 0, "HollowTestItem");
266 }
267
268 void tst_QQuickItem::cleanup()
269 {
270     QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
271     inputMethodPrivate->testContext = 0;
272 }
273
274 void tst_QQuickItem::keys()
275 {
276     QQuickView *window = new QQuickView(0);
277     window->setBaseSize(QSize(240,320));
278
279     KeysTestObject *testObject = new KeysTestObject;
280     window->rootContext()->setContextProperty("keysTestObject", testObject);
281
282     window->rootContext()->setContextProperty("enableKeyHanding", QVariant(true));
283     window->rootContext()->setContextProperty("forwardeeVisible", QVariant(true));
284
285     window->setSource(testFileUrl("keystest.qml"));
286     window->show();
287     window->requestActivateWindow();
288     QTest::qWaitForWindowShown(window);
289     QTRY_VERIFY(QGuiApplication::focusWindow() == window);
290
291     QVERIFY(window->rootObject());
292     QCOMPARE(window->rootObject()->property("isEnabled").toBool(), true);
293
294     QKeyEvent key(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
295     QGuiApplication::sendEvent(window, &key);
296     QCOMPARE(testObject->mKey, int(Qt::Key_A));
297     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
298     QCOMPARE(testObject->mText, QLatin1String("A"));
299     QVERIFY(testObject->mModifiers == Qt::NoModifier);
300     QVERIFY(!key.isAccepted());
301
302     testObject->reset();
303
304     key = QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ShiftModifier, "A", false, 1);
305     QGuiApplication::sendEvent(window, &key);
306     QCOMPARE(testObject->mKey, int(Qt::Key_A));
307     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
308     QCOMPARE(testObject->mText, QLatin1String("A"));
309     QVERIFY(testObject->mModifiers == Qt::ShiftModifier);
310     QVERIFY(key.isAccepted());
311
312     testObject->reset();
313
314     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
315     QGuiApplication::sendEvent(window, &key);
316     QCOMPARE(testObject->mKey, int(Qt::Key_Return));
317     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Return));
318     QCOMPARE(testObject->mText, QLatin1String("Return"));
319     QVERIFY(testObject->mModifiers == Qt::NoModifier);
320     QVERIFY(key.isAccepted());
321
322     testObject->reset();
323
324     key = QKeyEvent(QEvent::KeyPress, Qt::Key_0, Qt::NoModifier, "0", false, 1);
325     QGuiApplication::sendEvent(window, &key);
326     QCOMPARE(testObject->mKey, int(Qt::Key_0));
327     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_0));
328     QCOMPARE(testObject->mText, QLatin1String("0"));
329     QVERIFY(testObject->mModifiers == Qt::NoModifier);
330     QVERIFY(key.isAccepted());
331
332     testObject->reset();
333
334     key = QKeyEvent(QEvent::KeyPress, Qt::Key_9, Qt::NoModifier, "9", false, 1);
335     QGuiApplication::sendEvent(window, &key);
336     QCOMPARE(testObject->mKey, int(Qt::Key_9));
337     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_9));
338     QCOMPARE(testObject->mText, QLatin1String("9"));
339     QVERIFY(testObject->mModifiers == Qt::NoModifier);
340     QVERIFY(!key.isAccepted());
341
342     testObject->reset();
343
344     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
345     QGuiApplication::sendEvent(window, &key);
346     QCOMPARE(testObject->mKey, int(Qt::Key_Tab));
347     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Tab));
348     QCOMPARE(testObject->mText, QLatin1String("Tab"));
349     QVERIFY(testObject->mModifiers == Qt::NoModifier);
350     QVERIFY(key.isAccepted());
351
352     testObject->reset();
353
354     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
355     QGuiApplication::sendEvent(window, &key);
356     QCOMPARE(testObject->mKey, int(Qt::Key_Backtab));
357     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Backtab));
358     QCOMPARE(testObject->mText, QLatin1String("Backtab"));
359     QVERIFY(testObject->mModifiers == Qt::NoModifier);
360     QVERIFY(key.isAccepted());
361
362     testObject->reset();
363
364     key = QKeyEvent(QEvent::KeyPress, Qt::Key_VolumeUp, Qt::NoModifier, 1234, 0, 0);
365     QGuiApplication::sendEvent(window, &key);
366     QCOMPARE(testObject->mKey, int(Qt::Key_VolumeUp));
367     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_VolumeUp));
368     QVERIFY(testObject->mModifiers == Qt::NoModifier);
369     QVERIFY(testObject->mNativeScanCode == 1234);
370     QVERIFY(key.isAccepted());
371
372     testObject->reset();
373
374     window->rootContext()->setContextProperty("forwardeeVisible", QVariant(false));
375     key = QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
376     QGuiApplication::sendEvent(window, &key);
377     QCOMPARE(testObject->mKey, int(Qt::Key_A));
378     QCOMPARE(testObject->mForwardedKey, 0);
379     QCOMPARE(testObject->mText, QLatin1String("A"));
380     QVERIFY(testObject->mModifiers == Qt::NoModifier);
381     QVERIFY(!key.isAccepted());
382
383     testObject->reset();
384
385     window->rootContext()->setContextProperty("enableKeyHanding", QVariant(false));
386     QCOMPARE(window->rootObject()->property("isEnabled").toBool(), false);
387
388     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
389     QGuiApplication::sendEvent(window, &key);
390     QCOMPARE(testObject->mKey, 0);
391     QVERIFY(!key.isAccepted());
392
393     window->rootContext()->setContextProperty("enableKeyHanding", QVariant(true));
394     QCOMPARE(window->rootObject()->property("isEnabled").toBool(), true);
395
396     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
397     QGuiApplication::sendEvent(window, &key);
398     QCOMPARE(testObject->mKey, int(Qt::Key_Return));
399     QVERIFY(key.isAccepted());
400
401     delete window;
402     delete testObject;
403 }
404
405 void tst_QQuickItem::keysProcessingOrder()
406 {
407     QQuickView *window = new QQuickView(0);
408     window->setBaseSize(QSize(240,320));
409
410     KeysTestObject *testObject = new KeysTestObject;
411     window->rootContext()->setContextProperty("keysTestObject", testObject);
412
413     window->setSource(testFileUrl("keyspriority.qml"));
414     window->show();
415     window->requestActivateWindow();
416     QTest::qWaitForWindowShown(window);
417     QTRY_VERIFY(QGuiApplication::focusWindow() == window);
418
419     KeyTestItem *testItem = qobject_cast<KeyTestItem*>(window->rootObject());
420     QVERIFY(testItem);
421
422     QCOMPARE(testItem->property("priorityTest").toInt(), 0);
423
424     QKeyEvent key(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
425     QGuiApplication::sendEvent(window, &key);
426     QCOMPARE(testObject->mKey, int(Qt::Key_A));
427     QCOMPARE(testObject->mText, QLatin1String("A"));
428     QVERIFY(testObject->mModifiers == Qt::NoModifier);
429     QVERIFY(key.isAccepted());
430
431     testObject->reset();
432
433     testObject->setProcessLast(true);
434
435     QCOMPARE(testItem->property("priorityTest").toInt(), 1);
436
437     key = QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
438     QGuiApplication::sendEvent(window, &key);
439     QCOMPARE(testObject->mKey, 0);
440     QVERIFY(key.isAccepted());
441
442     testObject->reset();
443
444     key = QKeyEvent(QEvent::KeyPress, Qt::Key_B, Qt::NoModifier, "B", false, 1);
445     QGuiApplication::sendEvent(window, &key);
446     QCOMPARE(testObject->mKey, int(Qt::Key_B));
447     QCOMPARE(testObject->mText, QLatin1String("B"));
448     QVERIFY(testObject->mModifiers == Qt::NoModifier);
449     QVERIFY(!key.isAccepted());
450
451     testObject->reset();
452
453     key = QKeyEvent(QEvent::KeyRelease, Qt::Key_B, Qt::NoModifier, "B", false, 1);
454     QGuiApplication::sendEvent(window, &key);
455     QCOMPARE(testObject->mKey, 0);
456     QVERIFY(key.isAccepted());
457
458     delete window;
459     delete testObject;
460 }
461
462 void tst_QQuickItem::keysim()
463 {
464     PlatformInputContext platformInputContext;
465     QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
466     inputMethodPrivate->testContext = &platformInputContext;
467
468     QQuickView *window = new QQuickView(0);
469     window->setBaseSize(QSize(240,320));
470
471     window->setSource(testFileUrl("keysim.qml"));
472     window->show();
473     window->requestActivateWindow();
474     QTest::qWaitForWindowShown(window);
475     QTRY_VERIFY(QGuiApplication::focusWindow() == window);
476
477     QVERIFY(window->rootObject());
478     QVERIFY(window->rootObject()->hasFocus() && window->rootObject()->hasActiveFocus());
479
480     QQuickTextInput *input = window->rootObject()->findChild<QQuickTextInput*>();
481     QVERIFY(input);
482
483     QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>());
484     QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev);
485
486     QEXPECT_FAIL("", "QTBUG-24280", Continue);
487     QCOMPARE(input->text(), QLatin1String("Hello world!"));
488
489     delete window;
490 }
491
492 QQuickItemPrivate *childPrivate(QQuickItem *rootItem, const char * itemString)
493 {
494     QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
495     QQuickItemPrivate* itemPrivate = QQuickItemPrivate::get(item);
496     return itemPrivate;
497 }
498
499 QVariant childProperty(QQuickItem *rootItem, const char * itemString, const char * property)
500 {
501     QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
502     return item->property(property);
503 }
504
505 bool anchorsMirrored(QQuickItem *rootItem, const char * itemString)
506 {
507     QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
508     QQuickItemPrivate* itemPrivate = QQuickItemPrivate::get(item);
509     return itemPrivate->anchors()->mirrored();
510 }
511
512 void tst_QQuickItem::layoutMirroring()
513 {
514     QQuickView *window = new QQuickView(0);
515     window->setSource(testFileUrl("layoutmirroring.qml"));
516     window->show();
517
518     QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject());
519     QVERIFY(rootItem);
520     QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(rootItem);
521     QVERIFY(rootPrivate);
522
523     QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
524     QCOMPARE(childPrivate(rootItem, "mirrored2")->effectiveLayoutMirror, true);
525     QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
526     QCOMPARE(childPrivate(rootItem, "notMirrored2")->effectiveLayoutMirror, false);
527     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
528     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
529
530     QCOMPARE(anchorsMirrored(rootItem, "mirrored1"), true);
531     QCOMPARE(anchorsMirrored(rootItem, "mirrored2"), true);
532     QCOMPARE(anchorsMirrored(rootItem, "notMirrored1"), false);
533     QCOMPARE(anchorsMirrored(rootItem, "notMirrored2"), false);
534     QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror1"), true);
535     QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror2"), true);
536
537     QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
538     QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritedLayoutMirror, false);
539     QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
540     QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritedLayoutMirror, false);
541     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
542     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
543
544     QCOMPARE(childPrivate(rootItem, "mirrored1")->isMirrorImplicit, false);
545     QCOMPARE(childPrivate(rootItem, "mirrored2")->isMirrorImplicit, false);
546     QCOMPARE(childPrivate(rootItem, "notMirrored1")->isMirrorImplicit, false);
547     QCOMPARE(childPrivate(rootItem, "notMirrored2")->isMirrorImplicit, true);
548     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->isMirrorImplicit, true);
549     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->isMirrorImplicit, true);
550
551     QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromParent, true);
552     QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromParent, false);
553     QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromParent, true);
554     QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromParent, false);
555     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromParent, true);
556     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromParent, true);
557
558     QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromItem, true);
559     QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromItem, false);
560     QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromItem, false);
561     QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromItem, false);
562     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromItem, false);
563     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromItem, false);
564
565     // load dynamic content using Loader that needs to inherit mirroring
566     rootItem->setProperty("state", "newContent");
567     QCOMPARE(childPrivate(rootItem, "notMirrored3")->effectiveLayoutMirror, false);
568     QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->effectiveLayoutMirror, true);
569
570     QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritedLayoutMirror, true);
571     QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritedLayoutMirror, true);
572
573     QCOMPARE(childPrivate(rootItem, "notMirrored3")->isMirrorImplicit, false);
574     QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->isMirrorImplicit, true);
575
576     QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromParent, true);
577     QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritMirrorFromParent, true);
578
579     QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
580     QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
581
582     // disable inheritance
583     rootItem->setProperty("childrenInherit", false);
584
585     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, false);
586     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, false);
587     QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
588     QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
589
590     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, false);
591     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, false);
592     QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, false);
593     QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, false);
594
595     // re-enable inheritance
596     rootItem->setProperty("childrenInherit", true);
597
598     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
599     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
600     QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
601     QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
602
603     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
604     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
605     QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
606     QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
607
608     //
609     // dynamic parenting
610     //
611     QQuickItem *parentItem1 = new QQuickItem();
612     QQuickItemPrivate::get(parentItem1)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
613     QQuickItemPrivate::get(parentItem1)->isMirrorImplicit = false;
614     QQuickItemPrivate::get(parentItem1)->inheritMirrorFromItem = true; // LayoutMirroring.childrenInherit: true
615     QQuickItemPrivate::get(parentItem1)->resolveLayoutMirror();
616
617     // inherit in constructor
618     QQuickItem *childItem1 = new QQuickItem(parentItem1);
619     QCOMPARE(QQuickItemPrivate::get(childItem1)->effectiveLayoutMirror, true);
620     QCOMPARE(QQuickItemPrivate::get(childItem1)->inheritMirrorFromParent, true);
621
622     // inherit through a parent change
623     QQuickItem *childItem2 = new QQuickItem();
624     QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
625     QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
626     childItem2->setParentItem(parentItem1);
627     QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, true);
628     QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, true);
629
630     // stop inherting through a parent change
631     QQuickItem *parentItem2 = new QQuickItem();
632     QQuickItemPrivate::get(parentItem2)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
633     QQuickItemPrivate::get(parentItem2)->resolveLayoutMirror();
634     childItem2->setParentItem(parentItem2);
635     QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
636     QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
637
638     delete parentItem1;
639     delete parentItem2;
640 }
641
642 void tst_QQuickItem::layoutMirroringIllegalParent()
643 {
644     QQmlComponent component(&engine);
645     component.setData("import QtQuick 2.0; QtObject { LayoutMirroring.enabled: true; LayoutMirroring.childrenInherit: true }", QUrl::fromLocalFile(""));
646     QTest::ignoreMessage(QtWarningMsg, "file::1:21: QML QtObject: LayoutDirection attached property only works with Items");
647     QObject *object = component.create();
648     QVERIFY(object != 0);
649 }
650
651 void tst_QQuickItem::keyNavigation()
652 {
653     QQuickView *window = new QQuickView(0);
654     window->setBaseSize(QSize(240,320));
655
656     window->setSource(testFileUrl("keynavigationtest.qml"));
657     window->show();
658     window->requestActivateWindow();
659     QTest::qWaitForWindowShown(window);
660     QTRY_VERIFY(QGuiApplication::focusWindow() == window);
661
662     QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
663     QVERIFY(item);
664     QVERIFY(item->hasActiveFocus());
665
666     QVariant result;
667     QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "verify",
668             Q_RETURN_ARG(QVariant, result)));
669     QVERIFY(result.toBool());
670
671     // right
672     QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
673     QGuiApplication::sendEvent(window, &key);
674     QVERIFY(key.isAccepted());
675
676     item = findItem<QQuickItem>(window->rootObject(), "item2");
677     QVERIFY(item);
678     QVERIFY(item->hasActiveFocus());
679
680     // down
681     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
682     QGuiApplication::sendEvent(window, &key);
683     QVERIFY(key.isAccepted());
684
685     item = findItem<QQuickItem>(window->rootObject(), "item4");
686     QVERIFY(item);
687     QVERIFY(item->hasActiveFocus());
688
689     // left
690     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
691     QGuiApplication::sendEvent(window, &key);
692     QVERIFY(key.isAccepted());
693
694     item = findItem<QQuickItem>(window->rootObject(), "item3");
695     QVERIFY(item);
696     QVERIFY(item->hasActiveFocus());
697
698     // up
699     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
700     QGuiApplication::sendEvent(window, &key);
701     QVERIFY(key.isAccepted());
702
703     item = findItem<QQuickItem>(window->rootObject(), "item1");
704     QVERIFY(item);
705     QVERIFY(item->hasActiveFocus());
706
707     // tab
708     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
709     QGuiApplication::sendEvent(window, &key);
710     QVERIFY(key.isAccepted());
711
712     item = findItem<QQuickItem>(window->rootObject(), "item2");
713     QVERIFY(item);
714     QVERIFY(item->hasActiveFocus());
715
716     // backtab
717     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
718     QGuiApplication::sendEvent(window, &key);
719     QVERIFY(key.isAccepted());
720
721     item = findItem<QQuickItem>(window->rootObject(), "item1");
722     QVERIFY(item);
723     QVERIFY(item->hasActiveFocus());
724
725     delete window;
726 }
727
728 void tst_QQuickItem::keyNavigation_RightToLeft()
729 {
730     QQuickView *window = new QQuickView(0);
731     window->setBaseSize(QSize(240,320));
732
733     window->setSource(testFileUrl("keynavigationtest.qml"));
734     window->show();
735     window->requestActivateWindow();
736     QTest::qWaitForWindowShown(window);
737     QTRY_VERIFY(QGuiApplication::focusWindow() == window);
738
739     QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject());
740     QVERIFY(rootItem);
741     QQuickItemPrivate* rootItemPrivate = QQuickItemPrivate::get(rootItem);
742
743     rootItemPrivate->effectiveLayoutMirror = true; // LayoutMirroring.mirror: true
744     rootItemPrivate->isMirrorImplicit = false;
745     rootItemPrivate->inheritMirrorFromItem = true; // LayoutMirroring.inherit: true
746     rootItemPrivate->resolveLayoutMirror();
747
748     QEvent wa(QEvent::WindowActivate);
749     QGuiApplication::sendEvent(window, &wa);
750     QFocusEvent fe(QEvent::FocusIn);
751     QGuiApplication::sendEvent(window, &fe);
752
753     QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
754     QVERIFY(item);
755     QVERIFY(item->hasActiveFocus());
756
757     QVariant result;
758     QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "verify",
759             Q_RETURN_ARG(QVariant, result)));
760     QVERIFY(result.toBool());
761
762     // right
763     QKeyEvent key(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
764     QGuiApplication::sendEvent(window, &key);
765     QVERIFY(key.isAccepted());
766
767     item = findItem<QQuickItem>(window->rootObject(), "item2");
768     QVERIFY(item);
769     QVERIFY(item->hasActiveFocus());
770
771     // left
772     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
773     QGuiApplication::sendEvent(window, &key);
774     QVERIFY(key.isAccepted());
775
776     item = findItem<QQuickItem>(window->rootObject(), "item1");
777     QVERIFY(item);
778     QVERIFY(item->hasActiveFocus());
779
780     delete window;
781 }
782
783 void tst_QQuickItem::keyNavigation_skipNotVisible()
784 {
785     QQuickView *window = new QQuickView(0);
786     window->setBaseSize(QSize(240,320));
787
788     window->setSource(testFileUrl("keynavigationtest.qml"));
789     window->show();
790     window->requestActivateWindow();
791     QTest::qWaitForWindowShown(window);
792     QTRY_VERIFY(QGuiApplication::focusWindow() == window);
793
794     QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
795     QVERIFY(item);
796     QVERIFY(item->hasActiveFocus());
797
798     // Set item 2 to not visible
799     item = findItem<QQuickItem>(window->rootObject(), "item2");
800     QVERIFY(item);
801     item->setVisible(false);
802     QVERIFY(!item->isVisible());
803
804     // right
805     QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
806     QGuiApplication::sendEvent(window, &key);
807     QVERIFY(key.isAccepted());
808
809     item = findItem<QQuickItem>(window->rootObject(), "item1");
810     QVERIFY(item);
811     QVERIFY(item->hasActiveFocus());
812
813     // tab
814     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
815     QGuiApplication::sendEvent(window, &key);
816     QVERIFY(key.isAccepted());
817
818     item = findItem<QQuickItem>(window->rootObject(), "item3");
819     QVERIFY(item);
820     QVERIFY(item->hasActiveFocus());
821
822     // backtab
823     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
824     QGuiApplication::sendEvent(window, &key);
825     QVERIFY(key.isAccepted());
826
827     item = findItem<QQuickItem>(window->rootObject(), "item1");
828     QVERIFY(item);
829     QVERIFY(item->hasActiveFocus());
830
831     //Set item 3 to not visible
832     item = findItem<QQuickItem>(window->rootObject(), "item3");
833     QVERIFY(item);
834     item->setVisible(false);
835     QVERIFY(!item->isVisible());
836
837     // tab
838     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
839     QGuiApplication::sendEvent(window, &key);
840     QVERIFY(key.isAccepted());
841
842     item = findItem<QQuickItem>(window->rootObject(), "item4");
843     QVERIFY(item);
844     QVERIFY(item->hasActiveFocus());
845
846     // backtab
847     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
848     QGuiApplication::sendEvent(window, &key);
849     QVERIFY(key.isAccepted());
850
851     item = findItem<QQuickItem>(window->rootObject(), "item1");
852     QVERIFY(item);
853     QVERIFY(item->hasActiveFocus());
854
855     delete window;
856 }
857
858 void tst_QQuickItem::keyNavigation_implicitSetting()
859 {
860     QQuickView *window = new QQuickView(0);
861     window->setBaseSize(QSize(240,320));
862
863     window->setSource(testFileUrl("keynavigationtest_implicit.qml"));
864     window->show();
865     window->requestActivateWindow();
866     QTest::qWaitForWindowShown(window);
867     QTRY_VERIFY(QGuiApplication::focusWindow() == window);
868
869     QEvent wa(QEvent::WindowActivate);
870     QGuiApplication::sendEvent(window, &wa);
871     QFocusEvent fe(QEvent::FocusIn);
872     QGuiApplication::sendEvent(window, &fe);
873
874     QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
875     QVERIFY(item);
876     QVERIFY(item->hasActiveFocus());
877
878     QVariant result;
879     QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "verify",
880             Q_RETURN_ARG(QVariant, result)));
881     QVERIFY(result.toBool());
882
883     // right
884     QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
885     QGuiApplication::sendEvent(window, &key);
886     QVERIFY(key.isAccepted());
887
888     item = findItem<QQuickItem>(window->rootObject(), "item2");
889     QVERIFY(item);
890     QVERIFY(item->hasActiveFocus());
891
892     // back to item1
893     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
894     QGuiApplication::sendEvent(window, &key);
895     QVERIFY(key.isAccepted());
896
897     item = findItem<QQuickItem>(window->rootObject(), "item1");
898     QVERIFY(item);
899     QVERIFY(item->hasActiveFocus());
900
901     // down
902     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
903     QGuiApplication::sendEvent(window, &key);
904     QVERIFY(key.isAccepted());
905
906     item = findItem<QQuickItem>(window->rootObject(), "item3");
907     QVERIFY(item);
908     QVERIFY(item->hasActiveFocus());
909
910     // move to item4
911     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
912     QGuiApplication::sendEvent(window, &key);
913     QVERIFY(key.isAccepted());
914
915     item = findItem<QQuickItem>(window->rootObject(), "item4");
916     QVERIFY(item);
917     QVERIFY(item->hasActiveFocus());
918
919     // left
920     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
921     QGuiApplication::sendEvent(window, &key);
922     QVERIFY(key.isAccepted());
923
924     item = findItem<QQuickItem>(window->rootObject(), "item3");
925     QVERIFY(item);
926     QVERIFY(item->hasActiveFocus());
927
928     // back to item4
929     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
930     QGuiApplication::sendEvent(window, &key);
931     QVERIFY(key.isAccepted());
932
933     item = findItem<QQuickItem>(window->rootObject(), "item4");
934     QVERIFY(item);
935     QVERIFY(item->hasActiveFocus());
936
937     // up
938     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
939     QGuiApplication::sendEvent(window, &key);
940     QVERIFY(key.isAccepted());
941
942     item = findItem<QQuickItem>(window->rootObject(), "item2");
943     QVERIFY(item);
944     QVERIFY(item->hasActiveFocus());
945
946     // back to item4
947     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
948     QGuiApplication::sendEvent(window, &key);
949     QVERIFY(key.isAccepted());
950
951     item = findItem<QQuickItem>(window->rootObject(), "item4");
952     QVERIFY(item);
953     QVERIFY(item->hasActiveFocus());
954
955     // tab
956     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
957     QGuiApplication::sendEvent(window, &key);
958     QVERIFY(key.isAccepted());
959
960     item = findItem<QQuickItem>(window->rootObject(), "item1");
961     QVERIFY(item);
962     QVERIFY(item->hasActiveFocus());
963
964     // back to item4
965     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
966     QGuiApplication::sendEvent(window, &key);
967     QVERIFY(key.isAccepted());
968
969     item = findItem<QQuickItem>(window->rootObject(), "item4");
970     QVERIFY(item);
971     QVERIFY(item->hasActiveFocus());
972
973     // backtab
974     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
975     QGuiApplication::sendEvent(window, &key);
976     QVERIFY(key.isAccepted());
977
978     item = findItem<QQuickItem>(window->rootObject(), "item3");
979     QVERIFY(item);
980     QVERIFY(item->hasActiveFocus());
981
982     delete window;
983 }
984
985 void tst_QQuickItem::smooth()
986 {
987     QQmlComponent component(&engine);
988     component.setData("import QtQuick 2.0; Item { smooth: false; }", QUrl::fromLocalFile(""));
989     QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
990     QSignalSpy spy(item, SIGNAL(smoothChanged(bool)));
991
992     QVERIFY(item);
993     QVERIFY(!item->smooth());
994
995     item->setSmooth(true);
996     QVERIFY(item->smooth());
997     QCOMPARE(spy.count(),1);
998     QList<QVariant> arguments = spy.first();
999     QVERIFY(arguments.count() == 1);
1000     QVERIFY(arguments.at(0).toBool() == true);
1001
1002     item->setSmooth(true);
1003     QCOMPARE(spy.count(),1);
1004
1005     item->setSmooth(false);
1006     QVERIFY(!item->smooth());
1007     QCOMPARE(spy.count(),2);
1008     item->setSmooth(false);
1009     QCOMPARE(spy.count(),2);
1010
1011     delete item;
1012 }
1013
1014 void tst_QQuickItem::clip()
1015 {
1016     QQmlComponent component(&engine);
1017     component.setData("import QtQuick 2.0\nItem { clip: false\n }", QUrl::fromLocalFile(""));
1018     QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
1019     QSignalSpy spy(item, SIGNAL(clipChanged(bool)));
1020
1021     QVERIFY(item);
1022     QVERIFY(!item->clip());
1023
1024     item->setClip(true);
1025     QVERIFY(item->clip());
1026
1027     QList<QVariant> arguments = spy.first();
1028     QVERIFY(arguments.count() == 1);
1029     QVERIFY(arguments.at(0).toBool() == true);
1030
1031     QCOMPARE(spy.count(),1);
1032     item->setClip(true);
1033     QCOMPARE(spy.count(),1);
1034
1035     item->setClip(false);
1036     QVERIFY(!item->clip());
1037     QCOMPARE(spy.count(),2);
1038     item->setClip(false);
1039     QCOMPARE(spy.count(),2);
1040
1041     delete item;
1042 }
1043
1044 void tst_QQuickItem::mapCoordinates()
1045 {
1046     QFETCH(int, x);
1047     QFETCH(int, y);
1048
1049     QQuickView *window = new QQuickView(0);
1050     window->setBaseSize(QSize(300, 300));
1051     window->setSource(testFileUrl("mapCoordinates.qml"));
1052     window->show();
1053     qApp->processEvents();
1054
1055     QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
1056     QVERIFY(root != 0);
1057     QQuickItem *a = findItem<QQuickItem>(window->rootObject(), "itemA");
1058     QVERIFY(a != 0);
1059     QQuickItem *b = findItem<QQuickItem>(window->rootObject(), "itemB");
1060     QVERIFY(b != 0);
1061
1062     QVariant result;
1063
1064     QVERIFY(QMetaObject::invokeMethod(root, "mapAToB",
1065             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
1066     QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToItem(b, QPointF(x, y)));
1067
1068     QVERIFY(QMetaObject::invokeMethod(root, "mapAFromB",
1069             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
1070     QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromItem(b, QPointF(x, y)));
1071
1072     QVERIFY(QMetaObject::invokeMethod(root, "mapAToNull",
1073             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
1074     QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToScene(QPointF(x, y)));
1075
1076     QVERIFY(QMetaObject::invokeMethod(root, "mapAFromNull",
1077             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
1078     QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromScene(QPointF(x, y)));
1079
1080     QString warning1 = testFileUrl("mapCoordinates.qml").toString() + ":48:5: QML Item: mapToItem() given argument \"1122\" which is neither null nor an Item";
1081     QString warning2 = testFileUrl("mapCoordinates.qml").toString() + ":48:5: QML Item: mapFromItem() given argument \"1122\" which is neither null nor an Item";
1082
1083     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
1084     QVERIFY(QMetaObject::invokeMethod(root, "checkMapAToInvalid",
1085             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
1086     QVERIFY(result.toBool());
1087
1088     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1089     QVERIFY(QMetaObject::invokeMethod(root, "checkMapAFromInvalid",
1090             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
1091     QVERIFY(result.toBool());
1092
1093     delete window;
1094 }
1095
1096 void tst_QQuickItem::mapCoordinates_data()
1097 {
1098     QTest::addColumn<int>("x");
1099     QTest::addColumn<int>("y");
1100
1101     for (int i=-20; i<=20; i+=10)
1102         QTest::newRow(QTest::toString(i)) << i << i;
1103 }
1104
1105 void tst_QQuickItem::mapCoordinatesRect()
1106 {
1107     QFETCH(int, x);
1108     QFETCH(int, y);
1109     QFETCH(int, width);
1110     QFETCH(int, height);
1111
1112     QQuickView *window = new QQuickView(0);
1113     window->setBaseSize(QSize(300, 300));
1114     window->setSource(testFileUrl("mapCoordinatesRect.qml"));
1115     window->show();
1116     qApp->processEvents();
1117
1118     QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
1119     QVERIFY(root != 0);
1120     QQuickItem *a = findItem<QQuickItem>(window->rootObject(), "itemA");
1121     QVERIFY(a != 0);
1122     QQuickItem *b = findItem<QQuickItem>(window->rootObject(), "itemB");
1123     QVERIFY(b != 0);
1124
1125     QVariant result;
1126
1127     QVERIFY(QMetaObject::invokeMethod(root, "mapAToB",
1128             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
1129     QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectToItem(b, QRectF(x, y, width, height)));
1130
1131     QVERIFY(QMetaObject::invokeMethod(root, "mapAFromB",
1132             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
1133     QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectFromItem(b, QRectF(x, y, width, height)));
1134
1135     QVERIFY(QMetaObject::invokeMethod(root, "mapAToNull",
1136             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
1137     QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectToScene(QRectF(x, y, width, height)));
1138
1139     QVERIFY(QMetaObject::invokeMethod(root, "mapAFromNull",
1140             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
1141     QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectFromScene(QRectF(x, y, width, height)));
1142
1143     QString warning1 = testFileUrl("mapCoordinatesRect.qml").toString() + ":48:5: QML Item: mapToItem() given argument \"1122\" which is neither null nor an Item";
1144     QString warning2 = testFileUrl("mapCoordinatesRect.qml").toString() + ":48:5: QML Item: mapFromItem() given argument \"1122\" which is neither null nor an Item";
1145
1146     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
1147     QVERIFY(QMetaObject::invokeMethod(root, "checkMapAToInvalid",
1148             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
1149     QVERIFY(result.toBool());
1150
1151     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1152     QVERIFY(QMetaObject::invokeMethod(root, "checkMapAFromInvalid",
1153             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
1154     QVERIFY(result.toBool());
1155
1156     delete window;
1157 }
1158
1159 void tst_QQuickItem::mapCoordinatesRect_data()
1160 {
1161     QTest::addColumn<int>("x");
1162     QTest::addColumn<int>("y");
1163     QTest::addColumn<int>("width");
1164     QTest::addColumn<int>("height");
1165
1166     for (int i=-20; i<=20; i+=5)
1167         QTest::newRow(QTest::toString(i)) << i << i << i << i;
1168 }
1169
1170 void tst_QQuickItem::transforms_data()
1171 {
1172     QTest::addColumn<QByteArray>("qml");
1173     QTest::addColumn<QTransform>("transform");
1174     QTest::newRow("translate") << QByteArray("Translate { x: 10; y: 20 }")
1175         << QTransform(1,0,0,0,1,0,10,20,1);
1176     QTest::newRow("rotation") << QByteArray("Rotation { angle: 90 }")
1177         << QTransform(0,1,0,-1,0,0,0,0,1);
1178     QTest::newRow("scale") << QByteArray("Scale { xScale: 1.5; yScale: -2  }")
1179         << QTransform(1.5,0,0,0,-2,0,0,0,1);
1180     QTest::newRow("sequence") << QByteArray("[ Translate { x: 10; y: 20 }, Scale { xScale: 1.5; yScale: -2  } ]")
1181         << QTransform(1,0,0,0,1,0,10,20,1) * QTransform(1.5,0,0,0,-2,0,0,0,1);
1182 }
1183
1184 void tst_QQuickItem::transforms()
1185 {
1186     QFETCH(QByteArray, qml);
1187     QFETCH(QTransform, transform);
1188     QQmlComponent component(&engine);
1189     component.setData("import QtQuick 2.0\nItem { transform: "+qml+"}", QUrl::fromLocalFile(""));
1190     QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
1191     QVERIFY(item);
1192     QCOMPARE(item->itemTransform(0,0), transform);
1193 }
1194
1195 void tst_QQuickItem::childrenProperty()
1196 {
1197     QQmlComponent component(&engine, testFileUrl("childrenProperty.qml"));
1198
1199     QObject *o = component.create();
1200     QVERIFY(o != 0);
1201
1202     QCOMPARE(o->property("test1").toBool(), true);
1203     QCOMPARE(o->property("test2").toBool(), true);
1204     QCOMPARE(o->property("test3").toBool(), true);
1205     QCOMPARE(o->property("test4").toBool(), true);
1206     QCOMPARE(o->property("test5").toBool(), true);
1207     delete o;
1208 }
1209
1210 void tst_QQuickItem::resourcesProperty()
1211 {
1212     QQmlComponent component(&engine, testFileUrl("resourcesProperty.qml"));
1213
1214     QObject *o = component.create();
1215     QVERIFY(o != 0);
1216
1217     QCOMPARE(o->property("test1").toBool(), true);
1218     QCOMPARE(o->property("test2").toBool(), true);
1219     QCOMPARE(o->property("test3").toBool(), true);
1220     QCOMPARE(o->property("test4").toBool(), true);
1221     QCOMPARE(o->property("test5").toBool(), true);
1222     delete o;
1223 }
1224
1225 void tst_QQuickItem::propertyChanges()
1226 {
1227     QQuickView *window = new QQuickView(0);
1228     window->setBaseSize(QSize(300, 300));
1229     window->setSource(testFileUrl("propertychanges.qml"));
1230     window->show();
1231     window->requestActivateWindow();
1232     QTest::qWaitForWindowShown(window);
1233     QTRY_VERIFY(QGuiApplication::focusWindow() == window);
1234
1235     QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item");
1236     QQuickItem *parentItem = findItem<QQuickItem>(window->rootObject(), "parentItem");
1237
1238     QVERIFY(item);
1239     QVERIFY(parentItem);
1240
1241     QSignalSpy parentSpy(item, SIGNAL(parentChanged(QQuickItem *)));
1242     QSignalSpy widthSpy(item, SIGNAL(widthChanged()));
1243     QSignalSpy heightSpy(item, SIGNAL(heightChanged()));
1244     QSignalSpy baselineOffsetSpy(item, SIGNAL(baselineOffsetChanged(qreal)));
1245     QSignalSpy childrenRectSpy(parentItem, SIGNAL(childrenRectChanged(QRectF)));
1246     QSignalSpy focusSpy(item, SIGNAL(focusChanged(bool)));
1247     QSignalSpy wantsFocusSpy(parentItem, SIGNAL(activeFocusChanged(bool)));
1248     QSignalSpy childrenChangedSpy(parentItem, SIGNAL(childrenChanged()));
1249     QSignalSpy xSpy(item, SIGNAL(xChanged()));
1250     QSignalSpy ySpy(item, SIGNAL(yChanged()));
1251
1252     item->setParentItem(parentItem);
1253     item->setWidth(100.0);
1254     item->setHeight(200.0);
1255     item->setFocus(true);
1256     item->setBaselineOffset(10.0);
1257
1258     QCOMPARE(item->parentItem(), parentItem);
1259     QCOMPARE(parentSpy.count(),1);
1260     QList<QVariant> parentArguments = parentSpy.first();
1261     QVERIFY(parentArguments.count() == 1);
1262     QCOMPARE(item->parentItem(), qvariant_cast<QQuickItem *>(parentArguments.at(0)));
1263     QCOMPARE(childrenChangedSpy.count(),1);
1264
1265     item->setParentItem(parentItem);
1266     QCOMPARE(childrenChangedSpy.count(),1);
1267
1268     QCOMPARE(item->width(), 100.0);
1269     QCOMPARE(widthSpy.count(),1);
1270
1271     QCOMPARE(item->height(), 200.0);
1272     QCOMPARE(heightSpy.count(),1);
1273
1274     QCOMPARE(item->baselineOffset(), 10.0);
1275     QCOMPARE(baselineOffsetSpy.count(),1);
1276     QList<QVariant> baselineOffsetArguments = baselineOffsetSpy.first();
1277     QVERIFY(baselineOffsetArguments.count() == 1);
1278     QCOMPARE(item->baselineOffset(), baselineOffsetArguments.at(0).toReal());
1279
1280     QCOMPARE(parentItem->childrenRect(), QRectF(0.0,0.0,100.0,200.0));
1281     QCOMPARE(childrenRectSpy.count(),1);
1282     QList<QVariant> childrenRectArguments = childrenRectSpy.at(0);
1283     QVERIFY(childrenRectArguments.count() == 1);
1284     QCOMPARE(parentItem->childrenRect(), childrenRectArguments.at(0).toRectF());
1285
1286     QCOMPARE(item->hasActiveFocus(), true);
1287     QCOMPARE(focusSpy.count(),1);
1288     QList<QVariant> focusArguments = focusSpy.first();
1289     QVERIFY(focusArguments.count() == 1);
1290     QCOMPARE(focusArguments.at(0).toBool(), true);
1291
1292     QCOMPARE(parentItem->hasActiveFocus(), false);
1293     QCOMPARE(parentItem->hasFocus(), false);
1294     QCOMPARE(wantsFocusSpy.count(),0);
1295
1296     item->setX(10.0);
1297     QCOMPARE(item->x(), 10.0);
1298     QCOMPARE(xSpy.count(), 1);
1299
1300     item->setY(10.0);
1301     QCOMPARE(item->y(), 10.0);
1302     QCOMPARE(ySpy.count(), 1);
1303
1304     delete window;
1305 }
1306
1307 void tst_QQuickItem::childrenRect()
1308 {
1309     QQuickView *window = new QQuickView(0);
1310     window->setSource(testFileUrl("childrenRect.qml"));
1311     window->setBaseSize(QSize(240,320));
1312     window->show();
1313
1314     QQuickItem *o = window->rootObject();
1315     QQuickItem *item = o->findChild<QQuickItem*>("testItem");
1316     QCOMPARE(item->width(), qreal(0));
1317     QCOMPARE(item->height(), qreal(0));
1318
1319     o->setProperty("childCount", 1);
1320     QCOMPARE(item->width(), qreal(10));
1321     QCOMPARE(item->height(), qreal(20));
1322
1323     o->setProperty("childCount", 5);
1324     QCOMPARE(item->width(), qreal(50));
1325     QCOMPARE(item->height(), qreal(100));
1326
1327     o->setProperty("childCount", 0);
1328     QCOMPARE(item->width(), qreal(0));
1329     QCOMPARE(item->height(), qreal(0));
1330
1331     delete o;
1332     delete window;
1333 }
1334
1335 // QTBUG-11383
1336 void tst_QQuickItem::childrenRectBug()
1337 {
1338     QQuickView *window = new QQuickView(0);
1339
1340     QString warning = testFileUrl("childrenRectBug.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"height\"";
1341     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
1342     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
1343
1344     window->setSource(testFileUrl("childrenRectBug.qml"));
1345     window->show();
1346
1347     QQuickItem *o = window->rootObject();
1348     QQuickItem *item = o->findChild<QQuickItem*>("theItem");
1349     QCOMPARE(item->width(), qreal(200));
1350     QCOMPARE(item->height(), qreal(100));
1351     QCOMPARE(item->x(), qreal(100));
1352
1353     delete window;
1354 }
1355
1356 // QTBUG-11465
1357 void tst_QQuickItem::childrenRectBug2()
1358 {
1359     QQuickView *window = new QQuickView(0);
1360
1361     QString warning1 = testFileUrl("childrenRectBug2.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"width\"";
1362     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
1363     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
1364
1365     QString warning2 = testFileUrl("childrenRectBug2.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"height\"";
1366     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1367     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1368     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1369     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1370
1371     window->setSource(testFileUrl("childrenRectBug2.qml"));
1372     window->show();
1373
1374     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(window->rootObject());
1375     QVERIFY(rect);
1376     QQuickItem *item = rect->findChild<QQuickItem*>("theItem");
1377     QCOMPARE(item->width(), qreal(100));
1378     QCOMPARE(item->height(), qreal(110));
1379     QCOMPARE(item->x(), qreal(130));
1380
1381     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1382     rectPrivate->setState("row");
1383     QCOMPARE(item->width(), qreal(210));
1384     QCOMPARE(item->height(), qreal(50));
1385     QCOMPARE(item->x(), qreal(75));
1386
1387     delete window;
1388 }
1389
1390 // QTBUG-12722
1391 void tst_QQuickItem::childrenRectBug3()
1392 {
1393     QQuickView *window = new QQuickView(0);
1394     window->setSource(testFileUrl("childrenRectBug3.qml"));
1395     window->show();
1396
1397     //don't crash on delete
1398     delete window;
1399 }
1400
1401 // QTBUG-13893
1402 void tst_QQuickItem::transformCrash()
1403 {
1404     QQuickView *window = new QQuickView(0);
1405     window->setSource(testFileUrl("transformCrash.qml"));
1406     window->show();
1407
1408     delete window;
1409 }
1410
1411 void tst_QQuickItem::implicitSize()
1412 {
1413     QQuickView *window = new QQuickView(0);
1414     window->setSource(testFileUrl("implicitsize.qml"));
1415     window->show();
1416
1417     QQuickItem *item = qobject_cast<QQuickItem*>(window->rootObject());
1418     QVERIFY(item);
1419     QCOMPARE(item->width(), qreal(80));
1420     QCOMPARE(item->height(), qreal(60));
1421
1422     QCOMPARE(item->implicitWidth(), qreal(200));
1423     QCOMPARE(item->implicitHeight(), qreal(100));
1424
1425     QMetaObject::invokeMethod(item, "resetSize");
1426
1427     QCOMPARE(item->width(), qreal(200));
1428     QCOMPARE(item->height(), qreal(100));
1429
1430     QMetaObject::invokeMethod(item, "changeImplicit");
1431
1432     QCOMPARE(item->implicitWidth(), qreal(150));
1433     QCOMPARE(item->implicitHeight(), qreal(80));
1434     QCOMPARE(item->width(), qreal(150));
1435     QCOMPARE(item->height(), qreal(80));
1436
1437     QMetaObject::invokeMethod(item, "assignImplicitBinding");
1438
1439     QCOMPARE(item->implicitWidth(), qreal(150));
1440     QCOMPARE(item->implicitHeight(), qreal(80));
1441     QCOMPARE(item->width(), qreal(150));
1442     QCOMPARE(item->height(), qreal(80));
1443
1444     QMetaObject::invokeMethod(item, "increaseImplicit");
1445
1446     QCOMPARE(item->implicitWidth(), qreal(200));
1447     QCOMPARE(item->implicitHeight(), qreal(100));
1448     QCOMPARE(item->width(), qreal(175));
1449     QCOMPARE(item->height(), qreal(90));
1450
1451     QMetaObject::invokeMethod(item, "changeImplicit");
1452
1453     QCOMPARE(item->implicitWidth(), qreal(150));
1454     QCOMPARE(item->implicitHeight(), qreal(80));
1455     QCOMPARE(item->width(), qreal(150));
1456     QCOMPARE(item->height(), qreal(80));
1457
1458     QMetaObject::invokeMethod(item, "assignUndefinedBinding");
1459
1460     QCOMPARE(item->implicitWidth(), qreal(150));
1461     QCOMPARE(item->implicitHeight(), qreal(80));
1462     QCOMPARE(item->width(), qreal(150));
1463     QCOMPARE(item->height(), qreal(80));
1464
1465     QMetaObject::invokeMethod(item, "increaseImplicit");
1466
1467     QCOMPARE(item->implicitWidth(), qreal(200));
1468     QCOMPARE(item->implicitHeight(), qreal(100));
1469     QCOMPARE(item->width(), qreal(175));
1470     QCOMPARE(item->height(), qreal(90));
1471
1472     QMetaObject::invokeMethod(item, "changeImplicit");
1473
1474     QCOMPARE(item->implicitWidth(), qreal(150));
1475     QCOMPARE(item->implicitHeight(), qreal(80));
1476     QCOMPARE(item->width(), qreal(150));
1477     QCOMPARE(item->height(), qreal(80));
1478
1479     delete window;
1480 }
1481
1482 void tst_QQuickItem::qtbug_16871()
1483 {
1484     QQmlComponent component(&engine, testFileUrl("qtbug_16871.qml"));
1485     QObject *o = component.create();
1486     QVERIFY(o != 0);
1487     delete o;
1488 }
1489
1490
1491 void tst_QQuickItem::visibleChildren()
1492 {
1493     QQuickView *window = new QQuickView(0);
1494     window->setSource(testFileUrl("visiblechildren.qml"));
1495     window->show();
1496
1497     QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
1498     QVERIFY(root);
1499
1500     QCOMPARE(root->property("test1_1").toBool(), true);
1501     QCOMPARE(root->property("test1_2").toBool(), true);
1502     QCOMPARE(root->property("test1_3").toBool(), true);
1503     QCOMPARE(root->property("test1_4").toBool(), true);
1504
1505     QMetaObject::invokeMethod(root, "hideFirstAndLastRowChild");
1506     QCOMPARE(root->property("test2_1").toBool(), true);
1507     QCOMPARE(root->property("test2_2").toBool(), true);
1508     QCOMPARE(root->property("test2_3").toBool(), true);
1509     QCOMPARE(root->property("test2_4").toBool(), true);
1510
1511     QMetaObject::invokeMethod(root, "showLastRowChildsLastChild");
1512     QCOMPARE(root->property("test3_1").toBool(), true);
1513     QCOMPARE(root->property("test3_2").toBool(), true);
1514     QCOMPARE(root->property("test3_3").toBool(), true);
1515     QCOMPARE(root->property("test3_4").toBool(), true);
1516
1517     QMetaObject::invokeMethod(root, "showLastRowChild");
1518     QCOMPARE(root->property("test4_1").toBool(), true);
1519     QCOMPARE(root->property("test4_2").toBool(), true);
1520     QCOMPARE(root->property("test4_3").toBool(), true);
1521     QCOMPARE(root->property("test4_4").toBool(), true);
1522
1523     QString warning1 = testFileUrl("visiblechildren.qml").toString() + ":96:32: QML Item: QQuickItem: visibleChildren property is readonly and cannot be assigned to.";
1524     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
1525     QMetaObject::invokeMethod(root, "tryWriteToReadonlyVisibleChildren");
1526     QCOMPARE(root->property("test5_1").toBool(), true);
1527
1528     QMetaObject::invokeMethod(root, "reparentVisibleItem3");
1529     QCOMPARE(root->property("test6_1").toBool(), true);
1530     QCOMPARE(root->property("test6_2").toBool(), true);
1531     QCOMPARE(root->property("test6_3").toBool(), true);
1532     QCOMPARE(root->property("test6_4").toBool(), true);
1533
1534     QMetaObject::invokeMethod(root, "reparentImlicitlyInvisibleItem4_1");
1535     QCOMPARE(root->property("test7_1").toBool(), true);
1536     QCOMPARE(root->property("test7_2").toBool(), true);
1537     QCOMPARE(root->property("test7_3").toBool(), true);
1538     QCOMPARE(root->property("test7_4").toBool(), true);
1539
1540     // FINALLY TEST THAT EVERYTHING IS AS EXPECTED
1541     QCOMPARE(root->property("test8_1").toBool(), true);
1542     QCOMPARE(root->property("test8_2").toBool(), true);
1543     QCOMPARE(root->property("test8_3").toBool(), true);
1544     QCOMPARE(root->property("test8_4").toBool(), true);
1545     QCOMPARE(root->property("test8_5").toBool(), true);
1546
1547     delete window;
1548 }
1549
1550 void tst_QQuickItem::parentLoop()
1551 {
1552     QQuickView *window = new QQuickView(0);
1553
1554     QTest::ignoreMessage(QtWarningMsg, "QQuickItem::setParentItem: Parent is already part of this items subtree.");
1555     window->setSource(testFileUrl("parentLoop.qml"));
1556
1557     QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
1558     QVERIFY(root);
1559
1560     QQuickItem *item1 = root->findChild<QQuickItem*>("item1");
1561     QVERIFY(item1);
1562     QCOMPARE(item1->parentItem(), root);
1563
1564     QQuickItem *item2 = root->findChild<QQuickItem*>("item2");
1565     QVERIFY(item2);
1566     QCOMPARE(item2->parentItem(), item1);
1567
1568     delete window;
1569 }
1570
1571 void tst_QQuickItem::contains_data()
1572 {
1573     QTest::addColumn<bool>("circleTest");
1574     QTest::addColumn<bool>("insideTarget");
1575     QTest::addColumn<QList<QPoint> >("points");
1576
1577     QList<QPoint> points;
1578
1579     points << QPoint(176, 176)
1580            << QPoint(176, 226)
1581            << QPoint(226, 176)
1582            << QPoint(226, 226)
1583            << QPoint(150, 200)
1584            << QPoint(200, 150)
1585            << QPoint(200, 250)
1586            << QPoint(250, 200);
1587     QTest::newRow("hollow square: testing points inside") << false << true << points;
1588
1589     points.clear();
1590     points << QPoint(162, 162)
1591            << QPoint(162, 242)
1592            << QPoint(242, 162)
1593            << QPoint(242, 242)
1594            << QPoint(200, 200)
1595            << QPoint(175, 200)
1596            << QPoint(200, 175)
1597            << QPoint(200, 228)
1598            << QPoint(228, 200)
1599            << QPoint(200, 122)
1600            << QPoint(122, 200)
1601            << QPoint(200, 280)
1602            << QPoint(280, 200);
1603     QTest::newRow("hollow square: testing points outside") << false << false << points;
1604
1605     points.clear();
1606     points << QPoint(174, 174)
1607            << QPoint(174, 225)
1608            << QPoint(225, 174)
1609            << QPoint(225, 225)
1610            << QPoint(165, 200)
1611            << QPoint(200, 165)
1612            << QPoint(200, 235)
1613            << QPoint(235, 200);
1614     QTest::newRow("hollow circle: testing points inside") << true << true << points;
1615
1616     points.clear();
1617     points << QPoint(160, 160)
1618            << QPoint(160, 240)
1619            << QPoint(240, 160)
1620            << QPoint(240, 240)
1621            << QPoint(200, 200)
1622            << QPoint(185, 185)
1623            << QPoint(185, 216)
1624            << QPoint(216, 185)
1625            << QPoint(216, 216)
1626            << QPoint(145, 200)
1627            << QPoint(200, 145)
1628            << QPoint(255, 200)
1629            << QPoint(200, 255);
1630     QTest::newRow("hollow circle: testing points outside") << true << false << points;
1631 }
1632
1633 void tst_QQuickItem::contains()
1634 {
1635     QFETCH(bool, circleTest);
1636     QFETCH(bool, insideTarget);
1637     QFETCH(QList<QPoint>, points);
1638
1639     QQuickView *window = new QQuickView(0);
1640     window->rootContext()->setContextProperty("circleShapeTest", circleTest);
1641     window->setBaseSize(QSize(400, 400));
1642     window->setSource(testFileUrl("hollowTestItem.qml"));
1643     window->show();
1644     window->requestActivateWindow();
1645     QTest::qWaitForWindowShown(window);
1646     QTRY_VERIFY(QGuiApplication::focusWindow() == window);
1647
1648     QQuickItem *root = qobject_cast<QQuickItem *>(window->rootObject());
1649     QVERIFY(root);
1650
1651     HollowTestItem *hollowItem = root->findChild<HollowTestItem *>("hollowItem");
1652     QVERIFY(hollowItem);
1653
1654     foreach (const QPoint &point, points) {
1655         // check mouse hover
1656         QTest::mouseMove(window, point);
1657         QTest::qWait(10);
1658         QCOMPARE(hollowItem->isHovered(), insideTarget);
1659
1660         // check mouse press
1661         QTest::mousePress(window, Qt::LeftButton, 0, point);
1662         QTest::qWait(10);
1663         QCOMPARE(hollowItem->isPressed(), insideTarget);
1664
1665         // check mouse release
1666         QTest::mouseRelease(window, Qt::LeftButton, 0, point);
1667         QTest::qWait(10);
1668         QCOMPARE(hollowItem->isPressed(), false);
1669     }
1670
1671     delete window;
1672 }
1673
1674
1675 QTEST_MAIN(tst_QQuickItem)
1676
1677 #include "tst_qquickitem.moc"