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