Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / tests / auto / qtquick2 / 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 <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativecomponent.h>
45 #include <QtDeclarative/qdeclarativecontext.h>
46 #include <QtQuick/qquickview.h>
47 #include <QtQuick/private/qquickrectangle_p.h>
48 #include <private/qquickitem_p.h>
49 #include "../../shared/util.h"
50
51 class tst_QQuickItem : public QDeclarativeDataTest
52 {
53     Q_OBJECT
54 public:
55     tst_QQuickItem();
56
57 private slots:
58     void initTestCase();
59     void keys();
60     void keysProcessingOrder();
61     void keyNavigation();
62     void keyNavigation_RightToLeft();
63     void keyNavigation_skipNotVisible();
64     void keyNavigation_implicitSetting();
65     void layoutMirroring();
66     void layoutMirroringIllegalParent();
67     void smooth();
68     void clip();
69     void mapCoordinates();
70     void mapCoordinates_data();
71     void propertyChanges();
72     void transforms();
73     void transforms_data();
74     void childrenRect();
75     void childrenRectBug();
76     void childrenRectBug2();
77     void childrenRectBug3();
78
79     void childrenProperty();
80     void resourcesProperty();
81
82     void transformCrash();
83     void implicitSize();
84     void qtbug_16871();
85 private:
86     QDeclarativeEngine engine;
87 };
88
89 template<typename T>
90 T *findItem(QQuickItem *parent, const QString &objectName)
91 {
92     if (!parent)
93         return 0;
94
95     const QMetaObject &mo = T::staticMetaObject;
96     //qDebug() << parent->QQuickItem::children().count() << "children";
97     for (int i = 0; i < parent->childItems().count(); ++i) {
98         QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
99         if (!item)
100             continue;
101         //qDebug() << "try" << item;
102         if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
103             return static_cast<T*>(item);
104         item = findItem<T>(item, objectName);
105         if (item)
106             return static_cast<T*>(item);
107     }
108
109     return 0;
110 }
111
112 class KeysTestObject : public QObject
113 {
114     Q_OBJECT
115
116     Q_PROPERTY(bool processLast READ processLast NOTIFY processLastChanged)
117
118 public:
119     KeysTestObject() : mKey(0), mModifiers(0), mForwardedKey(0), mLast(false) {}
120
121     void reset() {
122         mKey = 0;
123         mText = QString();
124         mModifiers = 0;
125         mForwardedKey = 0;
126     }
127
128     bool processLast() const { return mLast; }
129     void setProcessLast(bool b) {
130         if (b != mLast) {
131             mLast = b;
132             emit processLastChanged();
133         }
134     }
135
136 public slots:
137     void keyPress(int key, QString text, int modifiers) {
138         mKey = key;
139         mText = text;
140         mModifiers = modifiers;
141     }
142     void keyRelease(int key, QString text, int modifiers) {
143         mKey = key;
144         mText = text;
145         mModifiers = modifiers;
146     }
147     void forwardedKey(int key) {
148         mForwardedKey = key;
149     }
150
151 signals:
152     void processLastChanged();
153
154 public:
155     int mKey;
156     QString mText;
157     int mModifiers;
158     int mForwardedKey;
159     bool mLast;
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
194 tst_QQuickItem::tst_QQuickItem()
195 {
196 }
197
198 void tst_QQuickItem::initTestCase()
199 {
200     QDeclarativeDataTest::initTestCase();
201     qmlRegisterType<KeyTestItem>("Test",1,0,"KeyTestItem");
202 }
203
204 void tst_QQuickItem::keys()
205 {
206     QQuickView *canvas = new QQuickView(0);
207     canvas->setBaseSize(QSize(240,320));
208
209     KeysTestObject *testObject = new KeysTestObject;
210     canvas->rootContext()->setContextProperty("keysTestObject", testObject);
211
212     canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(true));
213     canvas->rootContext()->setContextProperty("forwardeeVisible", QVariant(true));
214
215     canvas->setSource(testFileUrl("keystest.qml"));
216     canvas->show();
217     canvas->requestActivateWindow();
218     QTest::qWaitForWindowShown(canvas);
219     QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
220
221     QVERIFY(canvas->rootObject());
222     QCOMPARE(canvas->rootObject()->property("isEnabled").toBool(), true);
223
224     QKeyEvent key(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
225     QGuiApplication::sendEvent(canvas, &key);
226     QCOMPARE(testObject->mKey, int(Qt::Key_A));
227     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
228     QCOMPARE(testObject->mText, QLatin1String("A"));
229     QVERIFY(testObject->mModifiers == Qt::NoModifier);
230     QVERIFY(!key.isAccepted());
231
232     testObject->reset();
233
234     key = QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ShiftModifier, "A", false, 1);
235     QGuiApplication::sendEvent(canvas, &key);
236     QCOMPARE(testObject->mKey, int(Qt::Key_A));
237     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
238     QCOMPARE(testObject->mText, QLatin1String("A"));
239     QVERIFY(testObject->mModifiers == Qt::ShiftModifier);
240     QVERIFY(key.isAccepted());
241
242     testObject->reset();
243
244     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
245     QGuiApplication::sendEvent(canvas, &key);
246     QCOMPARE(testObject->mKey, int(Qt::Key_Return));
247     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Return));
248     QCOMPARE(testObject->mText, QLatin1String("Return"));
249     QVERIFY(testObject->mModifiers == Qt::NoModifier);
250     QVERIFY(key.isAccepted());
251
252     testObject->reset();
253
254     key = QKeyEvent(QEvent::KeyPress, Qt::Key_0, Qt::NoModifier, "0", false, 1);
255     QGuiApplication::sendEvent(canvas, &key);
256     QCOMPARE(testObject->mKey, int(Qt::Key_0));
257     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_0));
258     QCOMPARE(testObject->mText, QLatin1String("0"));
259     QVERIFY(testObject->mModifiers == Qt::NoModifier);
260     QVERIFY(key.isAccepted());
261
262     testObject->reset();
263
264     key = QKeyEvent(QEvent::KeyPress, Qt::Key_9, Qt::NoModifier, "9", false, 1);
265     QGuiApplication::sendEvent(canvas, &key);
266     QCOMPARE(testObject->mKey, int(Qt::Key_9));
267     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_9));
268     QCOMPARE(testObject->mText, QLatin1String("9"));
269     QVERIFY(testObject->mModifiers == Qt::NoModifier);
270     QVERIFY(!key.isAccepted());
271
272     testObject->reset();
273
274     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
275     QGuiApplication::sendEvent(canvas, &key);
276     QCOMPARE(testObject->mKey, int(Qt::Key_Tab));
277     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Tab));
278     QCOMPARE(testObject->mText, QLatin1String("Tab"));
279     QVERIFY(testObject->mModifiers == Qt::NoModifier);
280     QVERIFY(key.isAccepted());
281
282     testObject->reset();
283
284     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
285     QGuiApplication::sendEvent(canvas, &key);
286     QCOMPARE(testObject->mKey, int(Qt::Key_Backtab));
287     QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Backtab));
288     QCOMPARE(testObject->mText, QLatin1String("Backtab"));
289     QVERIFY(testObject->mModifiers == Qt::NoModifier);
290     QVERIFY(key.isAccepted());
291
292     testObject->reset();
293
294     canvas->rootContext()->setContextProperty("forwardeeVisible", QVariant(false));
295     key = QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
296     QGuiApplication::sendEvent(canvas, &key);
297     QCOMPARE(testObject->mKey, int(Qt::Key_A));
298     QCOMPARE(testObject->mForwardedKey, 0);
299     QCOMPARE(testObject->mText, QLatin1String("A"));
300     QVERIFY(testObject->mModifiers == Qt::NoModifier);
301     QVERIFY(!key.isAccepted());
302
303     testObject->reset();
304
305     canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(false));
306     QCOMPARE(canvas->rootObject()->property("isEnabled").toBool(), false);
307
308     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
309     QGuiApplication::sendEvent(canvas, &key);
310     QCOMPARE(testObject->mKey, 0);
311     QVERIFY(!key.isAccepted());
312
313     canvas->rootContext()->setContextProperty("enableKeyHanding", QVariant(true));
314     QCOMPARE(canvas->rootObject()->property("isEnabled").toBool(), true);
315
316     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
317     QGuiApplication::sendEvent(canvas, &key);
318     QCOMPARE(testObject->mKey, int(Qt::Key_Return));
319     QVERIFY(key.isAccepted());
320
321     delete canvas;
322     delete testObject;
323 }
324
325 void tst_QQuickItem::keysProcessingOrder()
326 {
327     QQuickView *canvas = new QQuickView(0);
328     canvas->setBaseSize(QSize(240,320));
329
330     KeysTestObject *testObject = new KeysTestObject;
331     canvas->rootContext()->setContextProperty("keysTestObject", testObject);
332
333     canvas->setSource(testFileUrl("keyspriority.qml"));
334     canvas->show();
335     canvas->requestActivateWindow();
336     QTest::qWaitForWindowShown(canvas);
337     QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
338
339     KeyTestItem *testItem = qobject_cast<KeyTestItem*>(canvas->rootObject());
340     QVERIFY(testItem);
341
342     QKeyEvent key(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
343     QGuiApplication::sendEvent(canvas, &key);
344     QCOMPARE(testObject->mKey, int(Qt::Key_A));
345     QCOMPARE(testObject->mText, QLatin1String("A"));
346     QVERIFY(testObject->mModifiers == Qt::NoModifier);
347     QVERIFY(key.isAccepted());
348
349     testObject->reset();
350
351     testObject->setProcessLast(true);
352
353     key = QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
354     QGuiApplication::sendEvent(canvas, &key);
355     QCOMPARE(testObject->mKey, 0);
356     QVERIFY(key.isAccepted());
357
358     testObject->reset();
359
360     key = QKeyEvent(QEvent::KeyPress, Qt::Key_B, Qt::NoModifier, "B", false, 1);
361     QGuiApplication::sendEvent(canvas, &key);
362     QCOMPARE(testObject->mKey, int(Qt::Key_B));
363     QCOMPARE(testObject->mText, QLatin1String("B"));
364     QVERIFY(testObject->mModifiers == Qt::NoModifier);
365     QVERIFY(!key.isAccepted());
366
367     testObject->reset();
368
369     key = QKeyEvent(QEvent::KeyRelease, Qt::Key_B, Qt::NoModifier, "B", false, 1);
370     QGuiApplication::sendEvent(canvas, &key);
371     QCOMPARE(testObject->mKey, 0);
372     QVERIFY(key.isAccepted());
373
374     delete canvas;
375     delete testObject;
376 }
377
378 QQuickItemPrivate *childPrivate(QQuickItem *rootItem, const char * itemString)
379 {
380     QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
381     QQuickItemPrivate* itemPrivate = QQuickItemPrivate::get(item);
382     return itemPrivate;
383 }
384
385 QVariant childProperty(QQuickItem *rootItem, const char * itemString, const char * property)
386 {
387     QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
388     return item->property(property);
389 }
390
391 bool anchorsMirrored(QQuickItem *rootItem, const char * itemString)
392 {
393     QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
394     QQuickItemPrivate* itemPrivate = QQuickItemPrivate::get(item);
395     return itemPrivate->anchors()->mirrored();
396 }
397
398 void tst_QQuickItem::layoutMirroring()
399 {
400     QQuickView *canvas = new QQuickView(0);
401     canvas->setSource(testFileUrl("layoutmirroring.qml"));
402     canvas->show();
403
404     QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
405     QVERIFY(rootItem);
406     QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(rootItem);
407     QVERIFY(rootPrivate);
408
409     QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
410     QCOMPARE(childPrivate(rootItem, "mirrored2")->effectiveLayoutMirror, true);
411     QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
412     QCOMPARE(childPrivate(rootItem, "notMirrored2")->effectiveLayoutMirror, false);
413     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
414     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
415
416     QCOMPARE(anchorsMirrored(rootItem, "mirrored1"), true);
417     QCOMPARE(anchorsMirrored(rootItem, "mirrored2"), true);
418     QCOMPARE(anchorsMirrored(rootItem, "notMirrored1"), false);
419     QCOMPARE(anchorsMirrored(rootItem, "notMirrored2"), false);
420     QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror1"), true);
421     QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror2"), true);
422
423     QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
424     QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritedLayoutMirror, false);
425     QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
426     QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritedLayoutMirror, false);
427     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
428     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
429
430     QCOMPARE(childPrivate(rootItem, "mirrored1")->isMirrorImplicit, false);
431     QCOMPARE(childPrivate(rootItem, "mirrored2")->isMirrorImplicit, false);
432     QCOMPARE(childPrivate(rootItem, "notMirrored1")->isMirrorImplicit, false);
433     QCOMPARE(childPrivate(rootItem, "notMirrored2")->isMirrorImplicit, true);
434     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->isMirrorImplicit, true);
435     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->isMirrorImplicit, true);
436
437     QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromParent, true);
438     QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromParent, false);
439     QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromParent, true);
440     QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromParent, false);
441     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromParent, true);
442     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromParent, true);
443
444     QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromItem, true);
445     QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromItem, false);
446     QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromItem, false);
447     QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromItem, false);
448     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromItem, false);
449     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromItem, false);
450
451     // load dynamic content using Loader that needs to inherit mirroring
452     rootItem->setProperty("state", "newContent");
453     QCOMPARE(childPrivate(rootItem, "notMirrored3")->effectiveLayoutMirror, false);
454     QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->effectiveLayoutMirror, true);
455
456     QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritedLayoutMirror, true);
457     QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritedLayoutMirror, true);
458
459     QCOMPARE(childPrivate(rootItem, "notMirrored3")->isMirrorImplicit, false);
460     QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->isMirrorImplicit, true);
461
462     QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromParent, true);
463     QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritMirrorFromParent, true);
464
465     QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
466     QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
467
468     // disable inheritance
469     rootItem->setProperty("childrenInherit", false);
470
471     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, false);
472     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, false);
473     QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
474     QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
475
476     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, false);
477     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, false);
478     QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, false);
479     QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, false);
480
481     // re-enable inheritance
482     rootItem->setProperty("childrenInherit", true);
483
484     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
485     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
486     QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
487     QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
488
489     QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
490     QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
491     QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
492     QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
493
494     //
495     // dynamic parenting
496     //
497     QQuickItem *parentItem1 = new QQuickItem();
498     QQuickItemPrivate::get(parentItem1)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
499     QQuickItemPrivate::get(parentItem1)->isMirrorImplicit = false;
500     QQuickItemPrivate::get(parentItem1)->inheritMirrorFromItem = true; // LayoutMirroring.childrenInherit: true
501     QQuickItemPrivate::get(parentItem1)->resolveLayoutMirror();
502
503     // inherit in constructor
504     QQuickItem *childItem1 = new QQuickItem(parentItem1);
505     QCOMPARE(QQuickItemPrivate::get(childItem1)->effectiveLayoutMirror, true);
506     QCOMPARE(QQuickItemPrivate::get(childItem1)->inheritMirrorFromParent, true);
507
508     // inherit through a parent change
509     QQuickItem *childItem2 = new QQuickItem();
510     QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
511     QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
512     childItem2->setParentItem(parentItem1);
513     QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, true);
514     QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, true);
515
516     // stop inherting through a parent change
517     QQuickItem *parentItem2 = new QQuickItem();
518     QQuickItemPrivate::get(parentItem2)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
519     QQuickItemPrivate::get(parentItem2)->resolveLayoutMirror();
520     childItem2->setParentItem(parentItem2);
521     QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
522     QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
523
524     delete parentItem1;
525     delete parentItem2;
526 }
527
528 void tst_QQuickItem::layoutMirroringIllegalParent()
529 {
530     QDeclarativeComponent component(&engine);
531     component.setData("import QtQuick 2.0; QtObject { LayoutMirroring.enabled: true; LayoutMirroring.childrenInherit: true }", QUrl::fromLocalFile(""));
532     QTest::ignoreMessage(QtWarningMsg, "file::1:21: QML QtObject: LayoutDirection attached property only works with Items");
533     QObject *object = component.create();
534     QVERIFY(object != 0);
535 }
536
537 void tst_QQuickItem::keyNavigation()
538 {
539     QQuickView *canvas = new QQuickView(0);
540     canvas->setBaseSize(QSize(240,320));
541
542     canvas->setSource(testFileUrl("keynavigationtest.qml"));
543     canvas->show();
544     canvas->requestActivateWindow();
545     QTest::qWaitForWindowShown(canvas);
546     QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
547
548     QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item1");
549     QVERIFY(item);
550     QVERIFY(item->hasActiveFocus());
551
552     QVariant result;
553     QVERIFY(QMetaObject::invokeMethod(canvas->rootObject(), "verify",
554             Q_RETURN_ARG(QVariant, result)));
555     QVERIFY(result.toBool());
556
557     // right
558     QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
559     QGuiApplication::sendEvent(canvas, &key);
560     QVERIFY(key.isAccepted());
561
562     item = findItem<QQuickItem>(canvas->rootObject(), "item2");
563     QVERIFY(item);
564     QVERIFY(item->hasActiveFocus());
565
566     // down
567     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
568     QGuiApplication::sendEvent(canvas, &key);
569     QVERIFY(key.isAccepted());
570
571     item = findItem<QQuickItem>(canvas->rootObject(), "item4");
572     QVERIFY(item);
573     QVERIFY(item->hasActiveFocus());
574
575     // left
576     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
577     QGuiApplication::sendEvent(canvas, &key);
578     QVERIFY(key.isAccepted());
579
580     item = findItem<QQuickItem>(canvas->rootObject(), "item3");
581     QVERIFY(item);
582     QVERIFY(item->hasActiveFocus());
583
584     // up
585     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
586     QGuiApplication::sendEvent(canvas, &key);
587     QVERIFY(key.isAccepted());
588
589     item = findItem<QQuickItem>(canvas->rootObject(), "item1");
590     QVERIFY(item);
591     QVERIFY(item->hasActiveFocus());
592
593     // tab
594     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
595     QGuiApplication::sendEvent(canvas, &key);
596     QVERIFY(key.isAccepted());
597
598     item = findItem<QQuickItem>(canvas->rootObject(), "item2");
599     QVERIFY(item);
600     QVERIFY(item->hasActiveFocus());
601
602     // backtab
603     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
604     QGuiApplication::sendEvent(canvas, &key);
605     QVERIFY(key.isAccepted());
606
607     item = findItem<QQuickItem>(canvas->rootObject(), "item1");
608     QVERIFY(item);
609     QVERIFY(item->hasActiveFocus());
610
611     delete canvas;
612 }
613
614 void tst_QQuickItem::keyNavigation_RightToLeft()
615 {
616     QQuickView *canvas = new QQuickView(0);
617     canvas->setBaseSize(QSize(240,320));
618
619     canvas->setSource(testFileUrl("keynavigationtest.qml"));
620     canvas->show();
621     canvas->requestActivateWindow();
622     QTest::qWaitForWindowShown(canvas);
623     QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
624
625     QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
626     QVERIFY(rootItem);
627     QQuickItemPrivate* rootItemPrivate = QQuickItemPrivate::get(rootItem);
628
629     rootItemPrivate->effectiveLayoutMirror = true; // LayoutMirroring.mirror: true
630     rootItemPrivate->isMirrorImplicit = false;
631     rootItemPrivate->inheritMirrorFromItem = true; // LayoutMirroring.inherit: true
632     rootItemPrivate->resolveLayoutMirror();
633
634     QEvent wa(QEvent::WindowActivate);
635     QGuiApplication::sendEvent(canvas, &wa);
636     QFocusEvent fe(QEvent::FocusIn);
637     QGuiApplication::sendEvent(canvas, &fe);
638
639     QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item1");
640     QVERIFY(item);
641     QVERIFY(item->hasActiveFocus());
642
643     QVariant result;
644     QVERIFY(QMetaObject::invokeMethod(canvas->rootObject(), "verify",
645             Q_RETURN_ARG(QVariant, result)));
646     QVERIFY(result.toBool());
647
648     // right
649     QKeyEvent key(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
650     QGuiApplication::sendEvent(canvas, &key);
651     QVERIFY(key.isAccepted());
652
653     item = findItem<QQuickItem>(canvas->rootObject(), "item2");
654     QVERIFY(item);
655     QVERIFY(item->hasActiveFocus());
656
657     // left
658     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
659     QGuiApplication::sendEvent(canvas, &key);
660     QVERIFY(key.isAccepted());
661
662     item = findItem<QQuickItem>(canvas->rootObject(), "item1");
663     QVERIFY(item);
664     QVERIFY(item->hasActiveFocus());
665
666     delete canvas;
667 }
668
669 void tst_QQuickItem::keyNavigation_skipNotVisible()
670 {
671     QQuickView *canvas = new QQuickView(0);
672     canvas->setBaseSize(QSize(240,320));
673
674     canvas->setSource(testFileUrl("keynavigationtest.qml"));
675     canvas->show();
676     canvas->requestActivateWindow();
677     QTest::qWaitForWindowShown(canvas);
678     QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
679
680     QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item1");
681     QVERIFY(item);
682     QVERIFY(item->hasActiveFocus());
683
684     // Set item 2 to not visible
685     item = findItem<QQuickItem>(canvas->rootObject(), "item2");
686     QVERIFY(item);
687     item->setVisible(false);
688     QVERIFY(!item->isVisible());
689
690     // right
691     QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
692     QGuiApplication::sendEvent(canvas, &key);
693     QVERIFY(key.isAccepted());
694
695     item = findItem<QQuickItem>(canvas->rootObject(), "item1");
696     QVERIFY(item);
697     QVERIFY(item->hasActiveFocus());
698
699     // tab
700     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
701     QGuiApplication::sendEvent(canvas, &key);
702     QVERIFY(key.isAccepted());
703
704     item = findItem<QQuickItem>(canvas->rootObject(), "item3");
705     QVERIFY(item);
706     QVERIFY(item->hasActiveFocus());
707
708     // backtab
709     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
710     QGuiApplication::sendEvent(canvas, &key);
711     QVERIFY(key.isAccepted());
712
713     item = findItem<QQuickItem>(canvas->rootObject(), "item1");
714     QVERIFY(item);
715     QVERIFY(item->hasActiveFocus());
716
717     //Set item 3 to not visible
718     item = findItem<QQuickItem>(canvas->rootObject(), "item3");
719     QVERIFY(item);
720     item->setVisible(false);
721     QVERIFY(!item->isVisible());
722
723     // tab
724     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
725     QGuiApplication::sendEvent(canvas, &key);
726     QVERIFY(key.isAccepted());
727
728     item = findItem<QQuickItem>(canvas->rootObject(), "item4");
729     QVERIFY(item);
730     QVERIFY(item->hasActiveFocus());
731
732     // backtab
733     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
734     QGuiApplication::sendEvent(canvas, &key);
735     QVERIFY(key.isAccepted());
736
737     item = findItem<QQuickItem>(canvas->rootObject(), "item1");
738     QVERIFY(item);
739     QVERIFY(item->hasActiveFocus());
740
741     delete canvas;
742 }
743
744 void tst_QQuickItem::keyNavigation_implicitSetting()
745 {
746     QQuickView *canvas = new QQuickView(0);
747     canvas->setBaseSize(QSize(240,320));
748
749     canvas->setSource(testFileUrl("keynavigationtest_implicit.qml"));
750     canvas->show();
751     canvas->requestActivateWindow();
752     QTest::qWaitForWindowShown(canvas);
753     QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
754
755     QEvent wa(QEvent::WindowActivate);
756     QGuiApplication::sendEvent(canvas, &wa);
757     QFocusEvent fe(QEvent::FocusIn);
758     QGuiApplication::sendEvent(canvas, &fe);
759
760     QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item1");
761     QVERIFY(item);
762     QVERIFY(item->hasActiveFocus());
763
764     QVariant result;
765     QVERIFY(QMetaObject::invokeMethod(canvas->rootObject(), "verify",
766             Q_RETURN_ARG(QVariant, result)));
767     QVERIFY(result.toBool());
768
769     // right
770     QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
771     QGuiApplication::sendEvent(canvas, &key);
772     QVERIFY(key.isAccepted());
773
774     item = findItem<QQuickItem>(canvas->rootObject(), "item2");
775     QVERIFY(item);
776     QVERIFY(item->hasActiveFocus());
777
778     // back to item1
779     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
780     QGuiApplication::sendEvent(canvas, &key);
781     QVERIFY(key.isAccepted());
782
783     item = findItem<QQuickItem>(canvas->rootObject(), "item1");
784     QVERIFY(item);
785     QVERIFY(item->hasActiveFocus());
786
787     // down
788     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
789     QGuiApplication::sendEvent(canvas, &key);
790     QVERIFY(key.isAccepted());
791
792     item = findItem<QQuickItem>(canvas->rootObject(), "item3");
793     QVERIFY(item);
794     QVERIFY(item->hasActiveFocus());
795
796     // move to item4
797     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
798     QGuiApplication::sendEvent(canvas, &key);
799     QVERIFY(key.isAccepted());
800
801     item = findItem<QQuickItem>(canvas->rootObject(), "item4");
802     QVERIFY(item);
803     QVERIFY(item->hasActiveFocus());
804
805     // left
806     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
807     QGuiApplication::sendEvent(canvas, &key);
808     QVERIFY(key.isAccepted());
809
810     item = findItem<QQuickItem>(canvas->rootObject(), "item3");
811     QVERIFY(item);
812     QVERIFY(item->hasActiveFocus());
813
814     // back to item4
815     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
816     QGuiApplication::sendEvent(canvas, &key);
817     QVERIFY(key.isAccepted());
818
819     item = findItem<QQuickItem>(canvas->rootObject(), "item4");
820     QVERIFY(item);
821     QVERIFY(item->hasActiveFocus());
822
823     // up
824     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
825     QGuiApplication::sendEvent(canvas, &key);
826     QVERIFY(key.isAccepted());
827
828     item = findItem<QQuickItem>(canvas->rootObject(), "item2");
829     QVERIFY(item);
830     QVERIFY(item->hasActiveFocus());
831
832     // back to item4
833     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
834     QGuiApplication::sendEvent(canvas, &key);
835     QVERIFY(key.isAccepted());
836
837     item = findItem<QQuickItem>(canvas->rootObject(), "item4");
838     QVERIFY(item);
839     QVERIFY(item->hasActiveFocus());
840
841     // tab
842     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
843     QGuiApplication::sendEvent(canvas, &key);
844     QVERIFY(key.isAccepted());
845
846     item = findItem<QQuickItem>(canvas->rootObject(), "item1");
847     QVERIFY(item);
848     QVERIFY(item->hasActiveFocus());
849
850     // back to item4
851     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
852     QGuiApplication::sendEvent(canvas, &key);
853     QVERIFY(key.isAccepted());
854
855     item = findItem<QQuickItem>(canvas->rootObject(), "item4");
856     QVERIFY(item);
857     QVERIFY(item->hasActiveFocus());
858
859     // backtab
860     key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
861     QGuiApplication::sendEvent(canvas, &key);
862     QVERIFY(key.isAccepted());
863
864     item = findItem<QQuickItem>(canvas->rootObject(), "item3");
865     QVERIFY(item);
866     QVERIFY(item->hasActiveFocus());
867
868     delete canvas;
869 }
870
871 void tst_QQuickItem::smooth()
872 {
873     QDeclarativeComponent component(&engine);
874     component.setData("import QtQuick 2.0; Item { smooth: false; }", QUrl::fromLocalFile(""));
875     QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
876     QSignalSpy spy(item, SIGNAL(smoothChanged(bool)));
877
878     QVERIFY(item);
879     QVERIFY(!item->smooth());
880
881     item->setSmooth(true);
882     QVERIFY(item->smooth());
883     QCOMPARE(spy.count(),1);
884     QList<QVariant> arguments = spy.first();
885     QVERIFY(arguments.count() == 1);
886     QVERIFY(arguments.at(0).toBool() == true);
887
888     item->setSmooth(true);
889     QCOMPARE(spy.count(),1);
890
891     item->setSmooth(false);
892     QVERIFY(!item->smooth());
893     QCOMPARE(spy.count(),2);
894     item->setSmooth(false);
895     QCOMPARE(spy.count(),2);
896
897     delete item;
898 }
899
900 void tst_QQuickItem::clip()
901 {
902     QDeclarativeComponent component(&engine);
903     component.setData("import QtQuick 2.0\nItem { clip: false\n }", QUrl::fromLocalFile(""));
904     QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
905     QSignalSpy spy(item, SIGNAL(clipChanged(bool)));
906
907     QVERIFY(item);
908     QVERIFY(!item->clip());
909
910     item->setClip(true);
911     QVERIFY(item->clip());
912
913     QList<QVariant> arguments = spy.first();
914     QVERIFY(arguments.count() == 1);
915     QVERIFY(arguments.at(0).toBool() == true);
916
917     QCOMPARE(spy.count(),1);
918     item->setClip(true);
919     QCOMPARE(spy.count(),1);
920
921     item->setClip(false);
922     QVERIFY(!item->clip());
923     QCOMPARE(spy.count(),2);
924     item->setClip(false);
925     QCOMPARE(spy.count(),2);
926
927     delete item;
928 }
929
930 void tst_QQuickItem::mapCoordinates()
931 {
932     QFETCH(int, x);
933     QFETCH(int, y);
934
935     QQuickView *canvas = new QQuickView(0);
936     canvas->setBaseSize(QSize(300, 300));
937     canvas->setSource(testFileUrl("mapCoordinates.qml"));
938     canvas->show();
939     qApp->processEvents();
940
941     QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
942     QVERIFY(root != 0);
943     QQuickItem *a = findItem<QQuickItem>(canvas->rootObject(), "itemA");
944     QVERIFY(a != 0);
945     QQuickItem *b = findItem<QQuickItem>(canvas->rootObject(), "itemB");
946     QVERIFY(b != 0);
947
948     QVariant result;
949
950     QVERIFY(QMetaObject::invokeMethod(root, "mapAToB",
951             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
952     QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToItem(b, QPointF(x, y)));
953
954     QVERIFY(QMetaObject::invokeMethod(root, "mapAFromB",
955             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
956     QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromItem(b, QPointF(x, y)));
957
958     QVERIFY(QMetaObject::invokeMethod(root, "mapAToNull",
959             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
960     QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToScene(QPointF(x, y)));
961
962     QVERIFY(QMetaObject::invokeMethod(root, "mapAFromNull",
963             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
964     QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromScene(QPointF(x, y)));
965
966     QString warning1 = testFileUrl("mapCoordinates.qml").toString() + ":48:5: QML Item: mapToItem() given argument \"1122\" which is neither null nor an Item";
967     QString warning2 = testFileUrl("mapCoordinates.qml").toString() + ":48:5: QML Item: mapFromItem() given argument \"1122\" which is neither null nor an Item";
968
969     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
970     QVERIFY(QMetaObject::invokeMethod(root, "checkMapAToInvalid",
971             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
972     QVERIFY(result.toBool());
973
974     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
975     QVERIFY(QMetaObject::invokeMethod(root, "checkMapAFromInvalid",
976             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
977     QVERIFY(result.toBool());
978
979     delete canvas;
980 }
981
982 void tst_QQuickItem::mapCoordinates_data()
983 {
984     QTest::addColumn<int>("x");
985     QTest::addColumn<int>("y");
986
987     for (int i=-20; i<=20; i+=10)
988         QTest::newRow(QTest::toString(i)) << i << i;
989 }
990
991 void tst_QQuickItem::transforms_data()
992 {
993     QTest::addColumn<QByteArray>("qml");
994     QTest::addColumn<QTransform>("transform");
995     QTest::newRow("translate") << QByteArray("Translate { x: 10; y: 20 }")
996         << QTransform(1,0,0,0,1,0,10,20,1);
997     QTest::newRow("rotation") << QByteArray("Rotation { angle: 90 }")
998         << QTransform(0,1,0,-1,0,0,0,0,1);
999     QTest::newRow("scale") << QByteArray("Scale { xScale: 1.5; yScale: -2  }")
1000         << QTransform(1.5,0,0,0,-2,0,0,0,1);
1001     QTest::newRow("sequence") << QByteArray("[ Translate { x: 10; y: 20 }, Scale { xScale: 1.5; yScale: -2  } ]")
1002         << QTransform(1,0,0,0,1,0,10,20,1) * QTransform(1.5,0,0,0,-2,0,0,0,1);
1003 }
1004
1005 void tst_QQuickItem::transforms()
1006 {
1007     QFETCH(QByteArray, qml);
1008     QFETCH(QTransform, transform);
1009     QDeclarativeComponent component(&engine);
1010     component.setData("import QtQuick 2.0\nItem { transform: "+qml+"}", QUrl::fromLocalFile(""));
1011     QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
1012     QVERIFY(item);
1013     QCOMPARE(item->itemTransform(0,0), transform);
1014 }
1015
1016 void tst_QQuickItem::childrenProperty()
1017 {
1018     QDeclarativeComponent component(&engine, testFileUrl("childrenProperty.qml"));
1019
1020     QObject *o = component.create();
1021     QVERIFY(o != 0);
1022
1023     QCOMPARE(o->property("test1").toBool(), true);
1024     QCOMPARE(o->property("test2").toBool(), true);
1025     QCOMPARE(o->property("test3").toBool(), true);
1026     QCOMPARE(o->property("test4").toBool(), true);
1027     QCOMPARE(o->property("test5").toBool(), true);
1028     delete o;
1029 }
1030
1031 void tst_QQuickItem::resourcesProperty()
1032 {
1033     QDeclarativeComponent component(&engine, testFileUrl("resourcesProperty.qml"));
1034
1035     QObject *o = component.create();
1036     QVERIFY(o != 0);
1037
1038     QCOMPARE(o->property("test1").toBool(), true);
1039     QCOMPARE(o->property("test2").toBool(), true);
1040     QCOMPARE(o->property("test3").toBool(), true);
1041     QCOMPARE(o->property("test4").toBool(), true);
1042     QCOMPARE(o->property("test5").toBool(), true);
1043     delete o;
1044 }
1045
1046 void tst_QQuickItem::propertyChanges()
1047 {
1048     QQuickView *canvas = new QQuickView(0);
1049     canvas->setBaseSize(QSize(300, 300));
1050     canvas->setSource(testFileUrl("propertychanges.qml"));
1051     canvas->show();
1052     canvas->requestActivateWindow();
1053     QTest::qWaitForWindowShown(canvas);
1054     QTRY_VERIFY(QGuiApplication::focusWindow() == canvas);
1055
1056     QQuickItem *item = findItem<QQuickItem>(canvas->rootObject(), "item");
1057     QQuickItem *parentItem = findItem<QQuickItem>(canvas->rootObject(), "parentItem");
1058
1059     QVERIFY(item);
1060     QVERIFY(parentItem);
1061
1062     QSignalSpy parentSpy(item, SIGNAL(parentChanged(QQuickItem *)));
1063     QSignalSpy widthSpy(item, SIGNAL(widthChanged()));
1064     QSignalSpy heightSpy(item, SIGNAL(heightChanged()));
1065     QSignalSpy baselineOffsetSpy(item, SIGNAL(baselineOffsetChanged(qreal)));
1066     QSignalSpy childrenRectSpy(parentItem, SIGNAL(childrenRectChanged(QRectF)));
1067     QSignalSpy focusSpy(item, SIGNAL(focusChanged(bool)));
1068     QSignalSpy wantsFocusSpy(parentItem, SIGNAL(activeFocusChanged(bool)));
1069     QSignalSpy childrenChangedSpy(parentItem, SIGNAL(childrenChanged()));
1070     QSignalSpy xSpy(item, SIGNAL(xChanged()));
1071     QSignalSpy ySpy(item, SIGNAL(yChanged()));
1072
1073     item->setParentItem(parentItem);
1074     item->setWidth(100.0);
1075     item->setHeight(200.0);
1076     item->setFocus(true);
1077     item->setBaselineOffset(10.0);
1078
1079     QCOMPARE(item->parentItem(), parentItem);
1080     QCOMPARE(parentSpy.count(),1);
1081     QList<QVariant> parentArguments = parentSpy.first();
1082     QVERIFY(parentArguments.count() == 1);
1083     QCOMPARE(item->parentItem(), qvariant_cast<QQuickItem *>(parentArguments.at(0)));
1084     QCOMPARE(childrenChangedSpy.count(),1);
1085
1086     item->setParentItem(parentItem);
1087     QCOMPARE(childrenChangedSpy.count(),1);
1088
1089     QCOMPARE(item->width(), 100.0);
1090     QCOMPARE(widthSpy.count(),1);
1091
1092     QCOMPARE(item->height(), 200.0);
1093     QCOMPARE(heightSpy.count(),1);
1094
1095     QCOMPARE(item->baselineOffset(), 10.0);
1096     QCOMPARE(baselineOffsetSpy.count(),1);
1097     QList<QVariant> baselineOffsetArguments = baselineOffsetSpy.first();
1098     QVERIFY(baselineOffsetArguments.count() == 1);
1099     QCOMPARE(item->baselineOffset(), baselineOffsetArguments.at(0).toReal());
1100
1101     QCOMPARE(parentItem->childrenRect(), QRectF(0.0,0.0,100.0,200.0));
1102     QCOMPARE(childrenRectSpy.count(),1);
1103     QList<QVariant> childrenRectArguments = childrenRectSpy.at(0);
1104     QVERIFY(childrenRectArguments.count() == 1);
1105     QCOMPARE(parentItem->childrenRect(), childrenRectArguments.at(0).toRectF());
1106
1107     QCOMPARE(item->hasActiveFocus(), true);
1108     QCOMPARE(focusSpy.count(),1);
1109     QList<QVariant> focusArguments = focusSpy.first();
1110     QVERIFY(focusArguments.count() == 1);
1111     QCOMPARE(focusArguments.at(0).toBool(), true);
1112
1113     QCOMPARE(parentItem->hasActiveFocus(), false);
1114     QCOMPARE(parentItem->hasFocus(), false);
1115     QCOMPARE(wantsFocusSpy.count(),0);
1116
1117     item->setX(10.0);
1118     QCOMPARE(item->x(), 10.0);
1119     QCOMPARE(xSpy.count(), 1);
1120
1121     item->setY(10.0);
1122     QCOMPARE(item->y(), 10.0);
1123     QCOMPARE(ySpy.count(), 1);
1124
1125     delete canvas;
1126 }
1127
1128 void tst_QQuickItem::childrenRect()
1129 {
1130     QQuickView *canvas = new QQuickView(0);
1131     canvas->setSource(testFileUrl("childrenRect.qml"));
1132     canvas->setBaseSize(QSize(240,320));
1133     canvas->show();
1134
1135     QQuickItem *o = canvas->rootObject();
1136     QQuickItem *item = o->findChild<QQuickItem*>("testItem");
1137     QCOMPARE(item->width(), qreal(0));
1138     QCOMPARE(item->height(), qreal(0));
1139
1140     o->setProperty("childCount", 1);
1141     QCOMPARE(item->width(), qreal(10));
1142     QCOMPARE(item->height(), qreal(20));
1143
1144     o->setProperty("childCount", 5);
1145     QCOMPARE(item->width(), qreal(50));
1146     QCOMPARE(item->height(), qreal(100));
1147
1148     o->setProperty("childCount", 0);
1149     QCOMPARE(item->width(), qreal(0));
1150     QCOMPARE(item->height(), qreal(0));
1151
1152     delete o;
1153     delete canvas;
1154 }
1155
1156 // QTBUG-11383
1157 void tst_QQuickItem::childrenRectBug()
1158 {
1159     QQuickView *canvas = new QQuickView(0);
1160
1161     QString warning = testFileUrl("childrenRectBug.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"height\"";
1162     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
1163     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
1164
1165     canvas->setSource(testFileUrl("childrenRectBug.qml"));
1166     canvas->show();
1167
1168     QQuickItem *o = canvas->rootObject();
1169     QQuickItem *item = o->findChild<QQuickItem*>("theItem");
1170     QCOMPARE(item->width(), qreal(200));
1171     QCOMPARE(item->height(), qreal(100));
1172     QCOMPARE(item->x(), qreal(100));
1173
1174     delete canvas;
1175 }
1176
1177 // QTBUG-11465
1178 void tst_QQuickItem::childrenRectBug2()
1179 {
1180     QQuickView *canvas = new QQuickView(0);
1181
1182     QString warning1 = testFileUrl("childrenRectBug2.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"width\"";
1183     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
1184     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
1185
1186     QString warning2 = testFileUrl("childrenRectBug2.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"height\"";
1187     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1188     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1189     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1190     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1191
1192     canvas->setSource(testFileUrl("childrenRectBug2.qml"));
1193     canvas->show();
1194
1195     QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(canvas->rootObject());
1196     QVERIFY(rect);
1197     QQuickItem *item = rect->findChild<QQuickItem*>("theItem");
1198     QCOMPARE(item->width(), qreal(100));
1199     QCOMPARE(item->height(), qreal(110));
1200     QCOMPARE(item->x(), qreal(130));
1201
1202     QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1203     rectPrivate->setState("row");
1204     QCOMPARE(item->width(), qreal(210));
1205     QCOMPARE(item->height(), qreal(50));
1206     QCOMPARE(item->x(), qreal(75));
1207
1208     delete canvas;
1209 }
1210
1211 // QTBUG-12722
1212 void tst_QQuickItem::childrenRectBug3()
1213 {
1214     QQuickView *canvas = new QQuickView(0);
1215     canvas->setSource(testFileUrl("childrenRectBug3.qml"));
1216     canvas->show();
1217
1218     //don't crash on delete
1219     delete canvas;
1220 }
1221
1222 // QTBUG-13893
1223 void tst_QQuickItem::transformCrash()
1224 {
1225     QQuickView *canvas = new QQuickView(0);
1226     canvas->setSource(testFileUrl("transformCrash.qml"));
1227     canvas->show();
1228
1229     delete canvas;
1230 }
1231
1232 void tst_QQuickItem::implicitSize()
1233 {
1234     QQuickView *canvas = new QQuickView(0);
1235     canvas->setSource(testFileUrl("implicitsize.qml"));
1236     canvas->show();
1237
1238     QQuickItem *item = qobject_cast<QQuickItem*>(canvas->rootObject());
1239     QVERIFY(item);
1240     QCOMPARE(item->width(), qreal(80));
1241     QCOMPARE(item->height(), qreal(60));
1242
1243     QCOMPARE(item->implicitWidth(), qreal(200));
1244     QCOMPARE(item->implicitHeight(), qreal(100));
1245
1246     QMetaObject::invokeMethod(item, "resetSize");
1247
1248     QCOMPARE(item->width(), qreal(200));
1249     QCOMPARE(item->height(), qreal(100));
1250
1251     QMetaObject::invokeMethod(item, "changeImplicit");
1252
1253     QCOMPARE(item->implicitWidth(), qreal(150));
1254     QCOMPARE(item->implicitHeight(), qreal(80));
1255     QCOMPARE(item->width(), qreal(150));
1256     QCOMPARE(item->height(), qreal(80));
1257
1258     delete canvas;
1259 }
1260
1261 void tst_QQuickItem::qtbug_16871()
1262 {
1263     QDeclarativeComponent component(&engine, testFileUrl("qtbug_16871.qml"));
1264     QObject *o = component.create();
1265     QVERIFY(o != 0);
1266     delete o;
1267 }
1268
1269 QTEST_MAIN(tst_QQuickItem)
1270
1271 #include "tst_qquickitem.moc"