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