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