9fdfa785595fed8eaea493c07dc325b32d834af9
[profile/ivi/qtdeclarative.git] / tests / auto / quick / qquickitem / 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
42 #include <qtest.h>
43
44 #include <QtQuick/qquickitem.h>
45 #include <QtQuick/qquickcanvas.h>
46 #include <QtQuick/qquickview.h>
47 #include <QtWidgets/QGraphicsSceneMouseEvent>
48 #include "private/qquickfocusscope_p.h"
49 #include "private/qquickitem_p.h"
50 #include <QDebug>
51 #include <QTimer>
52 #include "../../shared/util.h"
53
54 class TestItem : public QQuickItem
55 {
56 Q_OBJECT
57 public:
58     TestItem(QQuickItem *parent = 0)
59         : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0)
60         , wheelCount(0), acceptIncomingTouchEvents(true)
61         , touchEventReached(false) {}
62
63     bool focused;
64     int pressCount;
65     int releaseCount;
66     int wheelCount;
67     bool acceptIncomingTouchEvents;
68     bool touchEventReached;
69 protected:
70     virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
71     virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
72     virtual void mousePressEvent(QMouseEvent *event) { event->accept(); ++pressCount; }
73     virtual void mouseReleaseEvent(QMouseEvent *event) { event->accept(); ++releaseCount; }
74     virtual void touchEvent(QTouchEvent *event) {
75         touchEventReached = true;
76         event->setAccepted(acceptIncomingTouchEvents);
77     }
78     virtual void wheelEvent(QWheelEvent *event) { event->accept(); ++wheelCount; }
79 };
80
81 class TestCanvas: public QQuickCanvas
82 {
83 public:
84     TestCanvas()
85         : QQuickCanvas()
86     {}
87
88     virtual bool event(QEvent *event)
89     {
90         return QQuickCanvas::event(event);
91     }
92 };
93
94 class TestPolishItem : public QQuickItem
95 {
96 Q_OBJECT
97 public:
98     TestPolishItem(QQuickItem *parent = 0)
99     : QQuickItem(parent), wasPolished(false) {
100
101     }
102
103     bool wasPolished;
104
105 protected:
106     virtual void updatePolish() {
107         wasPolished = true;
108     }
109
110 public slots:
111     void doPolish() {
112         polish();
113     }
114 };
115
116 class TestFocusScope : public QQuickFocusScope
117 {
118 Q_OBJECT
119 public:
120     TestFocusScope(QQuickItem *parent = 0) : QQuickFocusScope(parent), focused(false) {}
121
122     bool focused;
123 protected:
124     virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
125     virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
126 };
127
128 class tst_qquickitem : public QQmlDataTest
129 {
130     Q_OBJECT
131 public:
132
133 private slots:
134     void initTestCase();
135
136     void noCanvas();
137     void simpleFocus();
138     void scopedFocus();
139     void addedToCanvas();
140     void changeParent();
141     void multipleFocusClears();
142
143     void constructor();
144     void setParentItem();
145
146     void visible();
147     void enabled();
148     void enabledFocus();
149
150     void mouseGrab();
151     void touchEventAcceptIgnore_data();
152     void touchEventAcceptIgnore();
153     void polishOutsideAnimation();
154     void polishOnCompleted();
155
156     void wheelEvent_data();
157     void wheelEvent();
158     void hoverEvent_data();
159     void hoverEvent();
160     void hoverEventInParent();
161
162     void paintOrder_data();
163     void paintOrder();
164
165 private:
166
167     enum PaintOrderOp {
168         NoOp, Append, Remove, StackBefore, StackAfter, SetZ
169     };
170
171     void ensureFocus(QWindow *w) {
172         w->show();
173         w->requestActivateWindow();
174         qApp->processEvents();
175     }
176 };
177
178 void tst_qquickitem::initTestCase()
179 {
180     QQmlDataTest::initTestCase();
181     qmlRegisterType<TestPolishItem>("Qt.test", 1, 0, "TestPolishItem");
182 }
183
184 // Focus has no effect when outside a canvas
185 void tst_qquickitem::noCanvas()
186 {
187     QQuickItem *root = new TestItem;
188     QQuickItem *child = new TestItem(root);
189     QQuickItem *scope = new TestItem(root);
190     QQuickFocusScope *scopedChild = new TestFocusScope(scope);
191     QQuickFocusScope *scopedChild2 = new TestFocusScope(scope);
192
193     QCOMPARE(root->hasFocus(), false);
194     QCOMPARE(child->hasFocus(), false);
195     QCOMPARE(scope->hasFocus(), false);
196     QCOMPARE(scopedChild->hasFocus(), false);
197     QCOMPARE(scopedChild2->hasFocus(), false);
198
199     root->setFocus(true);
200     scope->setFocus(true);
201     scopedChild2->setFocus(true);
202     QCOMPARE(root->hasFocus(), true);
203     QCOMPARE(child->hasFocus(), false);
204     QCOMPARE(scope->hasFocus(), true);
205     QCOMPARE(scopedChild->hasFocus(), false);
206     QCOMPARE(scopedChild2->hasFocus(), true);
207
208     root->setFocus(false);
209     child->setFocus(true);
210     scopedChild->setFocus(true);
211     scope->setFocus(false);
212     QCOMPARE(root->hasFocus(), false);
213     QCOMPARE(child->hasFocus(), true);
214     QCOMPARE(scope->hasFocus(), false);
215     QCOMPARE(scopedChild->hasFocus(), true);
216     QCOMPARE(scopedChild2->hasFocus(), true);
217
218     delete root;
219 }
220
221 struct FocusData {
222     FocusData() : focus(false), activeFocus(false) {}
223
224     void set(bool f, bool af) { focus = f; activeFocus = af; }
225     bool focus;
226     bool activeFocus;
227 };
228 struct FocusState : public QHash<QQuickItem *, FocusData>
229 {
230     FocusState() : activeFocusItem(0) {}
231     FocusState &operator<<(QQuickItem *item) {
232         insert(item, FocusData());
233         return *this;
234     }
235
236     void active(QQuickItem *i) {
237         activeFocusItem = i;
238     }
239     QQuickItem *activeFocusItem;
240 };
241
242 #define FVERIFY() \
243     do { \
244         if (focusState.activeFocusItem) { \
245             QCOMPARE(canvas.activeFocusItem(), focusState.activeFocusItem); \
246             if (qobject_cast<TestItem *>(canvas.activeFocusItem())) \
247                 QCOMPARE(qobject_cast<TestItem *>(canvas.activeFocusItem())->focused, true); \
248             else if (qobject_cast<TestFocusScope *>(canvas.activeFocusItem())) \
249                 QCOMPARE(qobject_cast<TestFocusScope *>(canvas.activeFocusItem())->focused, true); \
250         } else { \
251             QCOMPARE(canvas.activeFocusItem(), canvas.rootItem()); \
252         } \
253         for (QHash<QQuickItem *, FocusData>::Iterator iter = focusState.begin(); \
254             iter != focusState.end(); \
255             iter++) { \
256             QCOMPARE(iter.key()->hasFocus(), iter.value().focus); \
257             QCOMPARE(iter.key()->hasActiveFocus(), iter.value().activeFocus); \
258         } \
259     } while (false)
260
261 // Tests a simple set of top-level scoped items
262 void tst_qquickitem::simpleFocus()
263 {
264     QQuickCanvas canvas;
265     ensureFocus(&canvas);
266
267 #ifdef Q_OS_MAC
268     QSKIP("QTBUG-24094: fails on Mac OS X 10.7");
269 #endif
270
271     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
272
273     QQuickItem *l1c1 = new TestItem(canvas.rootItem());
274     QQuickItem *l1c2 = new TestItem(canvas.rootItem());
275     QQuickItem *l1c3 = new TestItem(canvas.rootItem());
276
277     QQuickItem *l2c1 = new TestItem(l1c1);
278     QQuickItem *l2c2 = new TestItem(l1c1);
279     QQuickItem *l2c3 = new TestItem(l1c3);
280
281     FocusState focusState;
282     focusState << l1c1 << l1c2 << l1c3
283                << l2c1 << l2c2 << l2c3;
284     FVERIFY();
285
286     l1c1->setFocus(true);
287     focusState[l1c1].set(true, true);
288     focusState.active(l1c1);
289     FVERIFY();
290
291     l2c3->setFocus(true);
292     focusState[l1c1].set(false, false);
293     focusState[l2c3].set(true, true);
294     focusState.active(l2c3);
295     FVERIFY();
296
297     l1c3->setFocus(true);
298     focusState[l2c3].set(false, false);
299     focusState[l1c3].set(true, true);
300     focusState.active(l1c3);
301     FVERIFY();
302
303     l1c2->setFocus(false);
304     FVERIFY();
305
306     l1c3->setFocus(false);
307     focusState[l1c3].set(false, false);
308     focusState.active(0);
309     FVERIFY();
310
311     l2c1->setFocus(true);
312     focusState[l2c1].set(true, true);
313     focusState.active(l2c1);
314     FVERIFY();
315 }
316
317 // Items with a focus scope
318 void tst_qquickitem::scopedFocus()
319 {
320     QQuickCanvas canvas;
321     ensureFocus(&canvas);
322     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
323
324     QQuickItem *l1c1 = new TestItem(canvas.rootItem());
325     QQuickItem *l1c2 = new TestItem(canvas.rootItem());
326     QQuickItem *l1c3 = new TestItem(canvas.rootItem());
327
328     QQuickItem *l2c1 = new TestItem(l1c1);
329     QQuickItem *l2c2 = new TestItem(l1c1);
330     QQuickItem *l2c3 = new TestFocusScope(l1c3);
331
332     QQuickItem *l3c1 = new TestItem(l2c3);
333     QQuickItem *l3c2 = new TestFocusScope(l2c3);
334
335     QQuickItem *l4c1 = new TestItem(l3c2);
336     QQuickItem *l4c2 = new TestItem(l3c2);
337
338     FocusState focusState;
339     focusState << l1c1 << l1c2 << l1c3
340                << l2c1 << l2c2 << l2c3
341                << l3c1 << l3c2
342                << l4c1 << l4c2;
343     FVERIFY();
344
345     l4c2->setFocus(true);
346     focusState[l4c2].set(true, false);
347     FVERIFY();
348
349     l4c1->setFocus(true);
350     focusState[l4c2].set(false, false);
351     focusState[l4c1].set(true, false);
352     FVERIFY();
353
354     l1c1->setFocus(true);
355     focusState[l1c1].set(true, true);
356     focusState.active(l1c1);
357     FVERIFY();
358
359     l3c2->setFocus(true);
360     focusState[l3c2].set(true, false);
361     FVERIFY();
362
363     l2c3->setFocus(true);
364     focusState[l1c1].set(false, false);
365     focusState[l2c3].set(true, true);
366     focusState[l3c2].set(true, true);
367     focusState[l4c1].set(true, true);
368     focusState.active(l4c1);
369     FVERIFY();
370
371     l3c2->setFocus(false);
372     focusState[l3c2].set(false, false);
373     focusState[l4c1].set(true, false);
374     focusState.active(l2c3);
375     FVERIFY();
376
377     l3c2->setFocus(true);
378     focusState[l3c2].set(true, true);
379     focusState[l4c1].set(true, true);
380     focusState.active(l4c1);
381     FVERIFY();
382
383     l4c1->setFocus(false);
384     focusState[l4c1].set(false, false);
385     focusState.active(l3c2);
386     FVERIFY();
387
388     l1c3->setFocus(true);
389     focusState[l1c3].set(true, true);
390     focusState[l2c3].set(false, false);
391     focusState[l3c2].set(true, false);
392     focusState.active(l1c3);
393     FVERIFY();
394 }
395
396 // Tests focus corrects itself when a tree is added to a canvas for the first time
397 void tst_qquickitem::addedToCanvas()
398 {
399     {
400     QQuickCanvas canvas;
401     ensureFocus(&canvas);
402     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
403
404     QQuickItem *item = new TestItem;
405
406     FocusState focusState;
407     focusState << item;
408
409     item->setFocus(true);
410     focusState[item].set(true, false);
411     FVERIFY();
412
413     item->setParentItem(canvas.rootItem());
414     focusState[item].set(true, true);
415     focusState.active(item);
416     FVERIFY();
417     }
418
419     {
420     QQuickCanvas canvas;
421     ensureFocus(&canvas);
422     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
423
424     QQuickItem *item = new TestItem(canvas.rootItem());
425
426     QQuickItem *tree = new TestItem;
427     QQuickItem *c1 = new TestItem(tree);
428     QQuickItem *c2 = new TestItem(tree);
429
430     FocusState focusState;
431     focusState << item << tree << c1 << c2;
432
433     item->setFocus(true);
434     c1->setFocus(true);
435     c2->setFocus(true);
436     focusState[item].set(true, true);
437     focusState[c1].set(true, false);
438     focusState[c2].set(true, false);
439     focusState.active(item);
440     FVERIFY();
441
442     tree->setParentItem(item);
443     focusState[c1].set(false, false);
444     focusState[c2].set(false, false);
445     FVERIFY();
446     }
447
448     {
449     QQuickCanvas canvas;
450     ensureFocus(&canvas);
451     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
452
453     QQuickItem *tree = new TestItem;
454     QQuickItem *c1 = new TestItem(tree);
455     QQuickItem *c2 = new TestItem(tree);
456
457     FocusState focusState;
458     focusState << tree << c1 << c2;
459     c1->setFocus(true);
460     c2->setFocus(true);
461     focusState[c1].set(true, false);
462     focusState[c2].set(true, false);
463     FVERIFY();
464
465     tree->setParentItem(canvas.rootItem());
466     focusState[c1].set(true, true);
467     focusState[c2].set(false, false);
468     focusState.active(c1);
469     FVERIFY();
470     }
471
472     {
473     QQuickCanvas canvas;
474     ensureFocus(&canvas);
475     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
476     QQuickItem *tree = new TestFocusScope;
477     QQuickItem *c1 = new TestItem(tree);
478     QQuickItem *c2 = new TestItem(tree);
479
480     FocusState focusState;
481     focusState << tree << c1 << c2;
482     c1->setFocus(true);
483     c2->setFocus(true);
484     focusState[c1].set(true, false);
485     focusState[c2].set(true, false);
486     FVERIFY();
487
488     tree->setParentItem(canvas.rootItem());
489     focusState[c1].set(true, false);
490     focusState[c2].set(false, false);
491     FVERIFY();
492
493     tree->setFocus(true);
494     focusState[tree].set(true, true);
495     focusState[c1].set(true, true);
496     focusState.active(c1);
497     FVERIFY();
498     }
499
500     {
501     QQuickCanvas canvas;
502     ensureFocus(&canvas);
503     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
504     QQuickItem *tree = new TestFocusScope;
505     QQuickItem *c1 = new TestItem(tree);
506     QQuickItem *c2 = new TestItem(tree);
507
508     FocusState focusState;
509     focusState << tree << c1 << c2;
510     tree->setFocus(true);
511     c1->setFocus(true);
512     c2->setFocus(true);
513     focusState[tree].set(true, false);
514     focusState[c1].set(true, false);
515     focusState[c2].set(true, false);
516     FVERIFY();
517
518     tree->setParentItem(canvas.rootItem());
519     focusState[tree].set(true, true);
520     focusState[c1].set(true, true);
521     focusState[c2].set(false, false);
522     focusState.active(c1);
523     FVERIFY();
524     }
525
526     {
527     QQuickCanvas canvas;
528     ensureFocus(&canvas);
529     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
530     QQuickItem *child = new TestItem(canvas.rootItem());
531     QQuickItem *tree = new TestFocusScope;
532     QQuickItem *c1 = new TestItem(tree);
533     QQuickItem *c2 = new TestItem(tree);
534
535     FocusState focusState;
536     focusState << child << tree << c1 << c2;
537     child->setFocus(true);
538     tree->setFocus(true);
539     c1->setFocus(true);
540     c2->setFocus(true);
541     focusState[child].set(true, true);
542     focusState[tree].set(true, false);
543     focusState[c1].set(true, false);
544     focusState[c2].set(true, false);
545     focusState.active(child);
546     FVERIFY();
547
548     tree->setParentItem(canvas.rootItem());
549     focusState[tree].set(false, false);
550     focusState[c1].set(true, false);
551     focusState[c2].set(false, false);
552     FVERIFY();
553
554     tree->setFocus(true);
555     focusState[child].set(false, false);
556     focusState[tree].set(true, true);
557     focusState[c1].set(true, true);
558     focusState.active(c1);
559     FVERIFY();
560     }
561 }
562
563 void tst_qquickitem::changeParent()
564 {
565     // Parent to no parent
566     {
567     QQuickCanvas canvas;
568     ensureFocus(&canvas);
569     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
570     QQuickItem *child = new TestItem(canvas.rootItem());
571
572     FocusState focusState;
573     focusState << child;
574     FVERIFY();
575
576     child->setFocus(true);
577     focusState[child].set(true, true);
578     focusState.active(child);
579     FVERIFY();
580
581     child->setParentItem(0);
582     focusState[child].set(true, false);
583     focusState.active(0);
584     FVERIFY();
585     }
586
587     // Different parent, same focus scope
588     {
589     QQuickCanvas canvas;
590     ensureFocus(&canvas);
591     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
592     QQuickItem *child = new TestItem(canvas.rootItem());
593     QQuickItem *child2 = new TestItem(canvas.rootItem());
594
595     FocusState focusState;
596     focusState << child << child2;
597     FVERIFY();
598
599     child->setFocus(true);
600     focusState[child].set(true, true);
601     focusState.active(child);
602     FVERIFY();
603
604     child->setParentItem(child2);
605     FVERIFY();
606     }
607
608     // Different parent, different focus scope
609     {
610     QQuickCanvas canvas;
611     ensureFocus(&canvas);
612     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
613     QQuickItem *child = new TestItem(canvas.rootItem());
614     QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
615     QQuickItem *item = new TestItem(child);
616
617     FocusState focusState;
618     focusState << child << child2 << item;
619     FVERIFY();
620
621     item->setFocus(true);
622     focusState[item].set(true, true);
623     focusState.active(item);
624     FVERIFY();
625
626     item->setParentItem(child2);
627     focusState[item].set(true, false);
628     focusState.active(0);
629     FVERIFY();
630     }
631     {
632     QQuickCanvas canvas;
633     ensureFocus(&canvas);
634     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
635     QQuickItem *child = new TestItem(canvas.rootItem());
636     QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
637     QQuickItem *item = new TestItem(child2);
638
639     FocusState focusState;
640     focusState << child << child2 << item;
641     FVERIFY();
642
643     item->setFocus(true);
644     focusState[item].set(true, false);
645     focusState.active(0);
646     FVERIFY();
647
648     item->setParentItem(child);
649     focusState[item].set(true, true);
650     focusState.active(item);
651     FVERIFY();
652     }
653     {
654     QQuickCanvas canvas;
655     ensureFocus(&canvas);
656     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
657     QQuickItem *child = new TestItem(canvas.rootItem());
658     QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
659     QQuickItem *item = new TestItem(child2);
660
661     FocusState focusState;
662     focusState << child << child2 << item;
663     FVERIFY();
664
665     child->setFocus(true);
666     item->setFocus(true);
667     focusState[child].set(true, true);
668     focusState[item].set(true, false);
669     focusState.active(child);
670     FVERIFY();
671
672     item->setParentItem(child);
673     focusState[item].set(false, false);
674     FVERIFY();
675     }
676
677 }
678
679 void tst_qquickitem::multipleFocusClears()
680 {
681     //Multiple clears of focus inside a focus scope shouldn't crash. QTBUG-24714
682     QQuickView *view = new QQuickView;
683     view->setSource(testFileUrl("multipleFocusClears.qml"));
684     view->show();
685     ensureFocus(view);
686     QTRY_VERIFY(QGuiApplication::focusWindow() == view);
687 }
688
689 void tst_qquickitem::constructor()
690 {
691     QQuickItem *root = new QQuickItem;
692     QVERIFY(root->parent() == 0);
693     QVERIFY(root->parentItem() == 0);
694
695     QQuickItem *child1 = new QQuickItem(root);
696     QVERIFY(child1->parent() == root);
697     QVERIFY(child1->parentItem() == root);
698     QCOMPARE(root->childItems().count(), 1);
699     QCOMPARE(root->childItems().at(0), child1);
700
701     QQuickItem *child2 = new QQuickItem(root);
702     QVERIFY(child2->parent() == root);
703     QVERIFY(child2->parentItem() == root);
704     QCOMPARE(root->childItems().count(), 2);
705     QCOMPARE(root->childItems().at(0), child1);
706     QCOMPARE(root->childItems().at(1), child2);
707
708     delete root;
709 }
710
711 void tst_qquickitem::setParentItem()
712 {
713     QQuickItem *root = new QQuickItem;
714     QVERIFY(root->parent() == 0);
715     QVERIFY(root->parentItem() == 0);
716
717     QQuickItem *child1 = new QQuickItem;
718     QVERIFY(child1->parent() == 0);
719     QVERIFY(child1->parentItem() == 0);
720
721     child1->setParentItem(root);
722     QVERIFY(child1->parent() == 0);
723     QVERIFY(child1->parentItem() == root);
724     QCOMPARE(root->childItems().count(), 1);
725     QCOMPARE(root->childItems().at(0), child1);
726
727     QQuickItem *child2 = new QQuickItem;
728     QVERIFY(child2->parent() == 0);
729     QVERIFY(child2->parentItem() == 0);
730     child2->setParentItem(root);
731     QVERIFY(child2->parent() == 0);
732     QVERIFY(child2->parentItem() == root);
733     QCOMPARE(root->childItems().count(), 2);
734     QCOMPARE(root->childItems().at(0), child1);
735     QCOMPARE(root->childItems().at(1), child2);
736
737     child1->setParentItem(0);
738     QVERIFY(child1->parent() == 0);
739     QVERIFY(child1->parentItem() == 0);
740     QCOMPARE(root->childItems().count(), 1);
741     QCOMPARE(root->childItems().at(0), child2);
742
743     delete root;
744
745     QVERIFY(child1->parent() == 0);
746     QVERIFY(child1->parentItem() == 0);
747     QVERIFY(child2->parent() == 0);
748     QVERIFY(child2->parentItem() == 0);
749
750     delete child1;
751     delete child2;
752 }
753
754 void tst_qquickitem::visible()
755 {
756     QQuickItem *root = new QQuickItem;
757
758     QQuickItem *child1 = new QQuickItem;
759     child1->setParentItem(root);
760
761     QQuickItem *child2 = new QQuickItem;
762     child2->setParentItem(root);
763
764     QVERIFY(child1->isVisible());
765     QVERIFY(child2->isVisible());
766
767     root->setVisible(false);
768     QVERIFY(!child1->isVisible());
769     QVERIFY(!child2->isVisible());
770
771     root->setVisible(true);
772     QVERIFY(child1->isVisible());
773     QVERIFY(child2->isVisible());
774
775     child1->setVisible(false);
776     QVERIFY(!child1->isVisible());
777     QVERIFY(child2->isVisible());
778
779     child2->setParentItem(child1);
780     QVERIFY(!child1->isVisible());
781     QVERIFY(!child2->isVisible());
782
783     child2->setParentItem(root);
784     QVERIFY(!child1->isVisible());
785     QVERIFY(child2->isVisible());
786
787     delete root;
788     delete child1;
789     delete child2;
790 }
791
792 void tst_qquickitem::enabled()
793 {
794     QQuickItem *root = new QQuickItem;
795
796     QQuickItem *child1 = new QQuickItem;
797     child1->setParentItem(root);
798
799     QQuickItem *child2 = new QQuickItem;
800     child2->setParentItem(root);
801
802     QVERIFY(child1->isEnabled());
803     QVERIFY(child2->isEnabled());
804
805     root->setEnabled(false);
806     QVERIFY(!child1->isEnabled());
807     QVERIFY(!child2->isEnabled());
808
809     root->setEnabled(true);
810     QVERIFY(child1->isEnabled());
811     QVERIFY(child2->isEnabled());
812
813     child1->setEnabled(false);
814     QVERIFY(!child1->isEnabled());
815     QVERIFY(child2->isEnabled());
816
817     child2->setParentItem(child1);
818     QVERIFY(!child1->isEnabled());
819     QVERIFY(!child2->isEnabled());
820
821     child2->setParentItem(root);
822     QVERIFY(!child1->isEnabled());
823     QVERIFY(child2->isEnabled());
824
825     delete root;
826     delete child1;
827     delete child2;
828 }
829
830 void tst_qquickitem::enabledFocus()
831 {
832     QQuickCanvas canvas;
833     ensureFocus(&canvas);
834
835     QQuickFocusScope root;
836
837     root.setFocus(true);
838     root.setEnabled(false);
839
840     QCOMPARE(root.isEnabled(), false);
841     QCOMPARE(root.hasFocus(), true);
842     QCOMPARE(root.hasActiveFocus(), false);
843
844     root.setParentItem(canvas.rootItem());
845
846     QCOMPARE(root.isEnabled(), false);
847     QCOMPARE(root.hasFocus(), true);
848     QCOMPARE(root.hasActiveFocus(), false);
849     QCOMPARE(canvas.activeFocusItem(), canvas.rootItem());
850
851     root.setEnabled(true);
852     QCOMPARE(root.isEnabled(), true);
853     QCOMPARE(root.hasFocus(), true);
854     QCOMPARE(root.hasActiveFocus(), true);
855     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
856
857     QQuickItem child1;
858     child1.setParentItem(&root);
859
860     QCOMPARE(child1.isEnabled(), true);
861     QCOMPARE(child1.hasFocus(), false);
862     QCOMPARE(child1.hasActiveFocus(), false);
863     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
864
865     QQuickItem child2;
866     child2.setFocus(true);
867     child2.setParentItem(&root);
868
869     QCOMPARE(root.isEnabled(), true);
870     QCOMPARE(root.hasFocus(), true);
871     QCOMPARE(root.hasActiveFocus(), true);
872     QCOMPARE(child2.isEnabled(), true);
873     QCOMPARE(child2.hasFocus(), true);
874     QCOMPARE(child2.hasActiveFocus(), true);
875     QCOMPARE(canvas.activeFocusItem(), &child2);
876
877     child2.setEnabled(false);
878
879     QCOMPARE(root.isEnabled(), true);
880     QCOMPARE(root.hasFocus(), true);
881     QCOMPARE(root.hasActiveFocus(), true);
882     QCOMPARE(child1.isEnabled(), true);
883     QCOMPARE(child1.hasFocus(), false);
884     QCOMPARE(child1.hasActiveFocus(), false);
885     QCOMPARE(child2.isEnabled(), false);
886     QCOMPARE(child2.hasFocus(), true);
887     QCOMPARE(child2.hasActiveFocus(), false);
888     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
889
890     child1.setEnabled(false);
891     QCOMPARE(child1.isEnabled(), false);
892     QCOMPARE(child1.hasFocus(), false);
893     QCOMPARE(child1.hasActiveFocus(), false);
894
895     child1.setFocus(true);
896     QCOMPARE(child1.isEnabled(), false);
897     QCOMPARE(child1.hasFocus(), true);
898     QCOMPARE(child1.hasActiveFocus(), false);
899     QCOMPARE(child2.isEnabled(), false);
900     QCOMPARE(child2.hasFocus(), false);
901     QCOMPARE(child2.hasActiveFocus(), false);
902     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
903
904     child1.setEnabled(true);
905     QCOMPARE(child1.isEnabled(), true);
906     QCOMPARE(child1.hasFocus(), true);
907     QCOMPARE(child1.hasActiveFocus(), true);
908     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&child1));
909
910     root.setFocus(false);
911     QCOMPARE(root.isEnabled(), true);
912     QCOMPARE(root.hasFocus(), false);
913     QCOMPARE(root.hasActiveFocus(), false);
914     QCOMPARE(child1.isEnabled(), true);
915     QCOMPARE(child1.hasFocus(), true);
916     QCOMPARE(child1.hasActiveFocus(), false);
917     QCOMPARE(canvas.activeFocusItem(), canvas.rootItem());
918
919     child2.forceActiveFocus();
920     QCOMPARE(root.isEnabled(), true);
921     QCOMPARE(root.hasFocus(), true);
922     QCOMPARE(root.hasActiveFocus(), true);
923     QCOMPARE(child1.isEnabled(), true);
924     QCOMPARE(child1.hasFocus(), false);
925     QCOMPARE(child1.hasActiveFocus(), false);
926     QCOMPARE(child2.isEnabled(), false);
927     QCOMPARE(child2.hasFocus(), true);
928     QCOMPARE(child2.hasActiveFocus(), false);
929     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
930
931     root.setEnabled(false);
932     QCOMPARE(root.isEnabled(), false);
933     QCOMPARE(root.hasFocus(), true);
934     QCOMPARE(root.hasActiveFocus(), false);
935     QCOMPARE(child1.isEnabled(), false);
936     QCOMPARE(child1.hasFocus(), false);
937     QCOMPARE(child1.hasActiveFocus(), false);
938     QCOMPARE(child2.isEnabled(), false);
939     QCOMPARE(child2.hasFocus(), true);
940     QCOMPARE(child2.hasActiveFocus(), false);
941     QCOMPARE(canvas.activeFocusItem(), canvas.rootItem());
942
943     child1.forceActiveFocus();
944     QCOMPARE(root.isEnabled(), false);
945     QCOMPARE(root.hasFocus(), true);
946     QCOMPARE(root.hasActiveFocus(), false);
947     QCOMPARE(child1.isEnabled(), false);
948     QCOMPARE(child1.hasFocus(), true);
949     QCOMPARE(child1.hasActiveFocus(), false);
950     QCOMPARE(child2.isEnabled(), false);
951     QCOMPARE(child2.hasFocus(), false);
952     QCOMPARE(child2.hasActiveFocus(), false);
953     QCOMPARE(canvas.activeFocusItem(), canvas.rootItem());
954
955     root.setEnabled(true);
956     QCOMPARE(root.isEnabled(), true);
957     QCOMPARE(root.hasFocus(), true);
958     QCOMPARE(root.hasActiveFocus(), true);
959     QCOMPARE(child1.isEnabled(), true);
960     QCOMPARE(child1.hasFocus(), true);
961     QCOMPARE(child1.hasActiveFocus(), true);
962     QCOMPARE(child2.isEnabled(), false);
963     QCOMPARE(child2.hasFocus(), false);
964     QCOMPARE(child2.hasActiveFocus(), false);
965     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&child1));
966 }
967
968 void tst_qquickitem::mouseGrab()
969 {
970     QQuickCanvas *canvas = new QQuickCanvas;
971     canvas->resize(200, 200);
972     canvas->show();
973
974     TestItem *child1 = new TestItem;
975     child1->setAcceptedMouseButtons(Qt::LeftButton);
976     child1->setSize(QSizeF(200, 100));
977     child1->setParentItem(canvas->rootItem());
978
979     TestItem *child2 = new TestItem;
980     child2->setAcceptedMouseButtons(Qt::LeftButton);
981     child2->setY(51);
982     child2->setSize(QSizeF(200, 100));
983     child2->setParentItem(canvas->rootItem());
984
985     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
986     QTest::qWait(100);
987     QVERIFY(canvas->mouseGrabberItem() == child1);
988     QTest::qWait(100);
989
990     QCOMPARE(child1->pressCount, 1);
991     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
992     QTest::qWait(50);
993     QVERIFY(canvas->mouseGrabberItem() == 0);
994     QCOMPARE(child1->releaseCount, 1);
995
996     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
997     QTest::qWait(50);
998     QVERIFY(canvas->mouseGrabberItem() == child1);
999     QCOMPARE(child1->pressCount, 2);
1000     child1->setEnabled(false);
1001     QVERIFY(canvas->mouseGrabberItem() == 0);
1002     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
1003     QTest::qWait(50);
1004     QCOMPARE(child1->releaseCount, 1);
1005     child1->setEnabled(true);
1006
1007     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
1008     QTest::qWait(50);
1009     QVERIFY(canvas->mouseGrabberItem() == child1);
1010     QCOMPARE(child1->pressCount, 3);
1011     child1->setVisible(false);
1012     QVERIFY(canvas->mouseGrabberItem() == 0);
1013     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
1014     QCOMPARE(child1->releaseCount, 1);
1015     child1->setVisible(true);
1016
1017     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
1018     QTest::qWait(50);
1019     QVERIFY(canvas->mouseGrabberItem() == child1);
1020     QCOMPARE(child1->pressCount, 4);
1021     child2->grabMouse();
1022     QVERIFY(canvas->mouseGrabberItem() == child2);
1023     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
1024     QTest::qWait(50);
1025     QCOMPARE(child1->releaseCount, 1);
1026     QCOMPARE(child2->releaseCount, 1);
1027
1028     child2->grabMouse();
1029     QVERIFY(canvas->mouseGrabberItem() == child2);
1030     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
1031     QTest::qWait(50);
1032     QCOMPARE(child1->pressCount, 4);
1033     QCOMPARE(child2->pressCount, 1);
1034     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
1035     QTest::qWait(50);
1036     QCOMPARE(child1->releaseCount, 1);
1037     QCOMPARE(child2->releaseCount, 2);
1038
1039     delete child1;
1040     delete child2;
1041     delete canvas;
1042 }
1043
1044 void tst_qquickitem::touchEventAcceptIgnore_data()
1045 {
1046     QTest::addColumn<bool>("itemSupportsTouch");
1047
1048     QTest::newRow("with touch") << true;
1049     QTest::newRow("without touch") << false;
1050 }
1051
1052 void tst_qquickitem::touchEventAcceptIgnore()
1053 {
1054     QFETCH(bool, itemSupportsTouch);
1055
1056     TestCanvas *canvas = new TestCanvas;
1057     canvas->resize(100, 100);
1058     canvas->show();
1059
1060     TestItem *item = new TestItem;
1061     item->setSize(QSizeF(100, 100));
1062     item->setParentItem(canvas->rootItem());
1063     item->acceptIncomingTouchEvents = itemSupportsTouch;
1064
1065     static QTouchDevice* device = 0;
1066     if (!device) {
1067         device =new QTouchDevice;
1068         device->setType(QTouchDevice::TouchScreen);
1069         QWindowSystemInterface::registerTouchDevice(device);
1070     }
1071
1072     // Send Begin, Update & End touch sequence
1073     {
1074         QTouchEvent::TouchPoint point;
1075         point.setId(1);
1076         point.setPos(QPointF(50, 50));
1077         point.setScreenPos(point.pos());
1078         point.setState(Qt::TouchPointPressed);
1079
1080         QTouchEvent event(QEvent::TouchBegin, device,
1081                           Qt::NoModifier,
1082                           Qt::TouchPointPressed,
1083                           QList<QTouchEvent::TouchPoint>() << point);
1084         event.setAccepted(true);
1085
1086         item->touchEventReached = false;
1087
1088         bool accepted = canvas->event(&event);
1089
1090         QVERIFY(item->touchEventReached);
1091         QCOMPARE(accepted && event.isAccepted(), itemSupportsTouch);
1092     }
1093     {
1094         QTouchEvent::TouchPoint point;
1095         point.setId(1);
1096         point.setPos(QPointF(60, 60));
1097         point.setScreenPos(point.pos());
1098         point.setState(Qt::TouchPointMoved);
1099
1100         QTouchEvent event(QEvent::TouchUpdate, device,
1101                           Qt::NoModifier,
1102                           Qt::TouchPointMoved,
1103                           QList<QTouchEvent::TouchPoint>() << point);
1104         event.setAccepted(true);
1105
1106         item->touchEventReached = false;
1107
1108         bool accepted = canvas->event(&event);
1109
1110         QCOMPARE(item->touchEventReached, itemSupportsTouch);
1111         QCOMPARE(accepted && event.isAccepted(), itemSupportsTouch);
1112     }
1113     {
1114         QTouchEvent::TouchPoint point;
1115         point.setId(1);
1116         point.setPos(QPointF(60, 60));
1117         point.setScreenPos(point.pos());
1118         point.setState(Qt::TouchPointReleased);
1119
1120         QTouchEvent event(QEvent::TouchEnd, device,
1121                           Qt::NoModifier,
1122                           Qt::TouchPointReleased,
1123                           QList<QTouchEvent::TouchPoint>() << point);
1124         event.setAccepted(true);
1125
1126         item->touchEventReached = false;
1127
1128         bool accepted = canvas->event(&event);
1129
1130         QCOMPARE(item->touchEventReached, itemSupportsTouch);
1131         QCOMPARE(accepted && event.isAccepted(), itemSupportsTouch);
1132     }
1133
1134     delete item;
1135     delete canvas;
1136 }
1137
1138 void tst_qquickitem::polishOutsideAnimation()
1139 {
1140     QQuickCanvas *canvas = new QQuickCanvas;
1141     canvas->resize(200, 200);
1142     canvas->show();
1143
1144     TestPolishItem *item = new TestPolishItem(canvas->rootItem());
1145     item->setSize(QSizeF(200, 100));
1146     QTest::qWait(50);
1147
1148     QTimer::singleShot(10, item, SLOT(doPolish()));
1149     QTRY_VERIFY(item->wasPolished);
1150
1151     delete item;
1152     delete canvas;
1153 }
1154
1155 void tst_qquickitem::polishOnCompleted()
1156 {
1157     QQuickView *view = new QQuickView;
1158     view->setSource(testFileUrl("polishOnCompleted.qml"));
1159     view->show();
1160
1161     TestPolishItem *item = qobject_cast<TestPolishItem*>(view->rootObject());
1162     QVERIFY(item);
1163
1164 #ifdef Q_OS_MAC
1165     QSKIP("QTBUG-21590 view does not reliably receive polish without a running animation");
1166 #endif
1167
1168     QTRY_VERIFY(item->wasPolished);
1169
1170     delete view;
1171 }
1172
1173 void tst_qquickitem::wheelEvent_data()
1174 {
1175     QTest::addColumn<bool>("visible");
1176     QTest::addColumn<bool>("enabled");
1177
1178     QTest::newRow("visible and enabled") << true << true;
1179     QTest::newRow("visible and disabled") << true << false;
1180     QTest::newRow("invisible and enabled") << false << true;
1181     QTest::newRow("invisible and disabled") << false << false;
1182 }
1183
1184 void tst_qquickitem::wheelEvent()
1185 {
1186     QFETCH(bool, visible);
1187     QFETCH(bool, enabled);
1188
1189     const bool shouldReceiveWheelEvents = visible && enabled;
1190
1191     QQuickCanvas *canvas = new QQuickCanvas;
1192     canvas->resize(200, 200);
1193     canvas->show();
1194
1195     TestItem *item = new TestItem;
1196     item->setSize(QSizeF(200, 100));
1197     item->setParentItem(canvas->rootItem());
1198
1199     item->setEnabled(enabled);
1200     item->setVisible(visible);
1201
1202     QWheelEvent event(QPoint(100, 50), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical);
1203     event.setAccepted(false);
1204     QGuiApplication::sendEvent(canvas, &event);
1205
1206     if (shouldReceiveWheelEvents) {
1207         QVERIFY(event.isAccepted());
1208         QCOMPARE(item->wheelCount, 1);
1209     } else {
1210         QVERIFY(!event.isAccepted());
1211         QCOMPARE(item->wheelCount, 0);
1212     }
1213
1214     delete canvas;
1215 }
1216
1217 class HoverItem : public QQuickItem
1218 {
1219 Q_OBJECT
1220 public:
1221     HoverItem(QQuickItem *parent = 0)
1222         : QQuickItem(parent), hoverEnterCount(0), hoverMoveCount(0), hoverLeaveCount(0)
1223     { }
1224     void resetCounters() {
1225         hoverEnterCount = 0;
1226         hoverMoveCount = 0;
1227         hoverLeaveCount = 0;
1228     }
1229     int hoverEnterCount;
1230     int hoverMoveCount;
1231     int hoverLeaveCount;
1232 protected:
1233     virtual void hoverEnterEvent(QHoverEvent *event) {
1234         event->accept();
1235         ++hoverEnterCount;
1236     }
1237     virtual void hoverMoveEvent(QHoverEvent *event) {
1238         event->accept();
1239         ++hoverMoveCount;
1240     }
1241     virtual void hoverLeaveEvent(QHoverEvent *event) {
1242         event->accept();
1243         ++hoverLeaveCount;
1244     }
1245 };
1246
1247 void tst_qquickitem::hoverEvent_data()
1248 {
1249     QTest::addColumn<bool>("visible");
1250     QTest::addColumn<bool>("enabled");
1251     QTest::addColumn<bool>("acceptHoverEvents");
1252
1253     QTest::newRow("visible, enabled, accept hover") << true << true << true;
1254     QTest::newRow("visible, disabled, accept hover") << true << false << true;
1255     QTest::newRow("invisible, enabled, accept hover") << false << true << true;
1256     QTest::newRow("invisible, disabled, accept hover") << false << false << true;
1257
1258     QTest::newRow("visible, enabled, not accept hover") << true << true << false;
1259     QTest::newRow("visible, disabled, not accept hover") << true << false << false;
1260     QTest::newRow("invisible, enabled, not accept hover") << false << true << false;
1261     QTest::newRow("invisible, disabled, not accept hover") << false << false << false;
1262 }
1263
1264 // ### For some unknown reason QTest::mouseMove() isn't working correctly.
1265 static void sendMouseMove(QObject *object, const QPoint &position)
1266 {
1267     QMouseEvent moveEvent(QEvent::MouseMove, position, Qt::NoButton, Qt::NoButton, 0);
1268     QGuiApplication::sendEvent(object, &moveEvent);
1269 }
1270
1271 void tst_qquickitem::hoverEvent()
1272 {
1273     QFETCH(bool, visible);
1274     QFETCH(bool, enabled);
1275     QFETCH(bool, acceptHoverEvents);
1276
1277     QQuickCanvas *canvas = new QQuickCanvas();
1278     canvas->resize(200, 200);
1279     canvas->show();
1280
1281     HoverItem *item = new HoverItem;
1282     item->setSize(QSizeF(100, 100));
1283     item->setParentItem(canvas->rootItem());
1284
1285     item->setEnabled(enabled);
1286     item->setVisible(visible);
1287     item->setAcceptHoverEvents(acceptHoverEvents);
1288
1289     const QPoint outside(150, 150);
1290     const QPoint inside(50, 50);
1291     const QPoint anotherInside(51, 51);
1292
1293     sendMouseMove(canvas, outside);
1294     item->resetCounters();
1295
1296     // Enter, then move twice inside, then leave.
1297     sendMouseMove(canvas, inside);
1298     sendMouseMove(canvas, anotherInside);
1299     sendMouseMove(canvas, inside);
1300     sendMouseMove(canvas, outside);
1301
1302     const bool shouldReceiveHoverEvents = visible && enabled && acceptHoverEvents;
1303     if (shouldReceiveHoverEvents) {
1304         QCOMPARE(item->hoverEnterCount, 1);
1305         QCOMPARE(item->hoverMoveCount, 2);
1306         QCOMPARE(item->hoverLeaveCount, 1);
1307     } else {
1308         QCOMPARE(item->hoverEnterCount, 0);
1309         QCOMPARE(item->hoverMoveCount, 0);
1310         QCOMPARE(item->hoverLeaveCount, 0);
1311     }
1312
1313     delete canvas;
1314 }
1315
1316 void tst_qquickitem::hoverEventInParent()
1317 {
1318     QQuickCanvas *canvas = new QQuickCanvas();
1319     canvas->resize(200, 200);
1320     canvas->show();
1321
1322     HoverItem *parentItem = new HoverItem(canvas->rootItem());
1323     parentItem->setSize(QSizeF(200, 200));
1324     parentItem->setAcceptHoverEvents(true);
1325
1326     HoverItem *leftItem = new HoverItem(parentItem);
1327     leftItem->setSize(QSizeF(100, 200));
1328     leftItem->setAcceptHoverEvents(true);
1329
1330     HoverItem *rightItem = new HoverItem(parentItem);
1331     rightItem->setSize(QSizeF(100, 200));
1332     rightItem->setPos(QPointF(100, 0));
1333     rightItem->setAcceptHoverEvents(true);
1334
1335     const QPoint insideLeft(50, 100);
1336     const QPoint insideRight(150, 100);
1337
1338     sendMouseMove(canvas, insideLeft);
1339     parentItem->resetCounters();
1340     leftItem->resetCounters();
1341     rightItem->resetCounters();
1342
1343     sendMouseMove(canvas, insideRight);
1344     QCOMPARE(parentItem->hoverEnterCount, 0);
1345     QCOMPARE(parentItem->hoverLeaveCount, 0);
1346     QCOMPARE(leftItem->hoverEnterCount, 0);
1347     QCOMPARE(leftItem->hoverLeaveCount, 1);
1348     QCOMPARE(rightItem->hoverEnterCount, 1);
1349     QCOMPARE(rightItem->hoverLeaveCount, 0);
1350
1351     sendMouseMove(canvas, insideLeft);
1352     QCOMPARE(parentItem->hoverEnterCount, 0);
1353     QCOMPARE(parentItem->hoverLeaveCount, 0);
1354     QCOMPARE(leftItem->hoverEnterCount, 1);
1355     QCOMPARE(leftItem->hoverLeaveCount, 1);
1356     QCOMPARE(rightItem->hoverEnterCount, 1);
1357     QCOMPARE(rightItem->hoverLeaveCount, 1);
1358
1359     delete canvas;
1360 }
1361
1362 void tst_qquickitem::paintOrder_data()
1363 {
1364     const QUrl order1Url = testFileUrl("order.1.qml");
1365     const QUrl order2Url = testFileUrl("order.2.qml");
1366
1367     QTest::addColumn<QUrl>("source");
1368     QTest::addColumn<int>("op");
1369     QTest::addColumn<QVariant>("param1");
1370     QTest::addColumn<QVariant>("param2");
1371     QTest::addColumn<QStringList>("expected");
1372
1373     QTest::newRow("test 1 noop") << order1Url
1374         << int(NoOp) << QVariant() << QVariant()
1375         << (QStringList() << "1" << "2" << "3");
1376     QTest::newRow("test 1 add") << order1Url
1377         << int(Append) << QVariant("new") << QVariant()
1378         << (QStringList() << "1" << "2" << "3" << "new");
1379     QTest::newRow("test 1 remove") << order1Url
1380         << int(Remove) << QVariant(1) << QVariant()
1381         << (QStringList() << "1" << "3");
1382     QTest::newRow("test 1 stack before") << order1Url
1383         << int(StackBefore) << QVariant(2) << QVariant(1)
1384         << (QStringList() << "1" << "3" << "2");
1385     QTest::newRow("test 1 stack after") << order1Url
1386         << int(StackAfter) << QVariant(0) << QVariant(1)
1387         << (QStringList() << "2" << "1" << "3");
1388     QTest::newRow("test 1 set z") << order1Url
1389         << int(SetZ) << QVariant(1) << QVariant(qreal(1.))
1390         << (QStringList() << "1" << "3" << "2");
1391
1392     QTest::newRow("test 2 noop") << order2Url
1393         << int(NoOp) << QVariant() << QVariant()
1394         << (QStringList() << "1" << "3" << "2");
1395     QTest::newRow("test 2 add") << order2Url
1396         << int(Append) << QVariant("new") << QVariant()
1397         << (QStringList() << "1" << "3" << "new" << "2");
1398     QTest::newRow("test 2 remove 1") << order2Url
1399         << int(Remove) << QVariant(1) << QVariant()
1400         << (QStringList() << "1" << "3");
1401     QTest::newRow("test 2 remove 2") << order2Url
1402         << int(Remove) << QVariant(2) << QVariant()
1403         << (QStringList() << "1" << "2");
1404     QTest::newRow("test 2 stack before 1") << order2Url
1405         << int(StackBefore) << QVariant(1) << QVariant(0)
1406         << (QStringList() << "1" << "3" << "2");
1407     QTest::newRow("test 2 stack before 2") << order2Url
1408         << int(StackBefore) << QVariant(2) << QVariant(0)
1409         << (QStringList() << "3" << "1" << "2");
1410     QTest::newRow("test 2 stack after 1") << order2Url
1411         << int(StackAfter) << QVariant(0) << QVariant(1)
1412         << (QStringList() << "1" << "3" << "2");
1413     QTest::newRow("test 2 stack after 2") << order2Url
1414         << int(StackAfter) << QVariant(0) << QVariant(2)
1415         << (QStringList() << "3" << "1" << "2");
1416     QTest::newRow("test 1 set z") << order1Url
1417         << int(SetZ) << QVariant(2) << QVariant(qreal(2.))
1418         << (QStringList() << "1" << "2" << "3");
1419 }
1420
1421 void tst_qquickitem::paintOrder()
1422 {
1423     QFETCH(QUrl, source);
1424     QFETCH(int, op);
1425     QFETCH(QVariant, param1);
1426     QFETCH(QVariant, param2);
1427     QFETCH(QStringList, expected);
1428
1429     QQuickView view;
1430     view.setSource(source);
1431
1432     QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject());
1433     QVERIFY(root);
1434
1435     switch (op) {
1436         case Append: {
1437                 QQuickItem *item = new QQuickItem(root);
1438                 item->setObjectName(param1.toString());
1439             }
1440             break;
1441         case Remove: {
1442                 QQuickItem *item = root->childItems().at(param1.toInt());
1443                 delete item;
1444             }
1445             break;
1446         case StackBefore: {
1447                 QQuickItem *item1 = root->childItems().at(param1.toInt());
1448                 QQuickItem *item2 = root->childItems().at(param2.toInt());
1449                 item1->stackBefore(item2);
1450             }
1451             break;
1452         case StackAfter: {
1453                 QQuickItem *item1 = root->childItems().at(param1.toInt());
1454                 QQuickItem *item2 = root->childItems().at(param2.toInt());
1455                 item1->stackAfter(item2);
1456             }
1457             break;
1458         case SetZ: {
1459                 QQuickItem *item = root->childItems().at(param1.toInt());
1460                 item->setZ(param2.toReal());
1461             }
1462             break;
1463         default:
1464             break;
1465     }
1466
1467     QList<QQuickItem*> list = QQuickItemPrivate::get(root)->paintOrderChildItems();
1468
1469     QStringList items;
1470     for (int i = 0; i < list.count(); ++i)
1471         items << list.at(i)->objectName();
1472
1473     QCOMPARE(items, expected);
1474 }
1475
1476
1477 QTEST_MAIN(tst_qquickitem)
1478
1479 #include "tst_qquickitem.moc"