dccf055ae8b3e8e0e5e9790edbe68dc3cdea46b2
[profile/ivi/qtdeclarative.git] / tests / auto / qtquick2 / qquickitem / tst_qquickitem.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
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) : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0), wheelCount(0) {}
59
60     bool focused;
61     int pressCount;
62     int releaseCount;
63     int wheelCount;
64 protected:
65     virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
66     virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
67     virtual void mousePressEvent(QMouseEvent *event) { event->accept(); ++pressCount; }
68     virtual void mouseReleaseEvent(QMouseEvent *event) { event->accept(); ++releaseCount; }
69     virtual void touchEvent(QTouchEvent *event) { event->accept(); }
70     virtual void wheelEvent(QWheelEvent *event) { event->accept(); ++wheelCount; }
71 };
72
73 class TestCanvas: public QQuickCanvas
74 {
75 public:
76     TestCanvas()
77         : QQuickCanvas()
78     {}
79
80     virtual bool event(QEvent *event)
81     {
82         return QQuickCanvas::event(event);
83     }
84 };
85
86 class TestPolishItem : public QQuickItem
87 {
88 Q_OBJECT
89 public:
90     TestPolishItem(QQuickItem *parent = 0)
91     : QQuickItem(parent), wasPolished(false) {
92
93     }
94
95     bool wasPolished;
96
97 protected:
98     virtual void updatePolish() {
99         wasPolished = true;
100     }
101
102 public slots:
103     void doPolish() {
104         polish();
105     }
106 };
107
108 class TestFocusScope : public QQuickFocusScope
109 {
110 Q_OBJECT
111 public:
112     TestFocusScope(QQuickItem *parent = 0) : QQuickFocusScope(parent), focused(false) {}
113
114     bool focused;
115 protected:
116     virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
117     virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
118 };
119
120 class tst_qquickitem : public QDeclarativeDataTest
121 {
122     Q_OBJECT
123 public:
124
125 private slots:
126     void initTestCase();
127
128     void noCanvas();
129     void simpleFocus();
130     void scopedFocus();
131     void addedToCanvas();
132     void changeParent();
133
134     void constructor();
135     void setParentItem();
136
137     void visible();
138     void enabled();
139
140     void mouseGrab();
141     void touchEventAccept();
142     void polishOutsideAnimation();
143     void polishOnCompleted();
144
145     void wheelEvent_data();
146     void wheelEvent();
147     void hoverEvent_data();
148     void hoverEvent();
149     void hoverEventInParent();
150
151     void paintOrder_data();
152     void paintOrder();
153
154 private:
155
156     enum PaintOrderOp {
157         NoOp, Append, Remove, StackBefore, StackAfter, SetZ
158     };
159
160     void ensureFocus(QWindow *w) {
161         w->show();
162         w->requestActivateWindow();
163         qApp->processEvents();
164     }
165 };
166
167 void tst_qquickitem::initTestCase()
168 {
169     QDeclarativeDataTest::initTestCase();
170     qmlRegisterType<TestPolishItem>("Qt.test", 1, 0, "TestPolishItem");
171 }
172
173 // Focus has no effect when outside a canvas
174 void tst_qquickitem::noCanvas()
175 {
176     QQuickItem *root = new TestItem;
177     QQuickItem *child = new TestItem(root);
178     QQuickItem *scope = new TestItem(root);
179     QQuickFocusScope *scopedChild = new TestFocusScope(scope);
180     QQuickFocusScope *scopedChild2 = new TestFocusScope(scope);
181
182     QCOMPARE(root->hasFocus(), false);
183     QCOMPARE(child->hasFocus(), false);
184     QCOMPARE(scope->hasFocus(), false);
185     QCOMPARE(scopedChild->hasFocus(), false);
186     QCOMPARE(scopedChild2->hasFocus(), false);
187
188     root->setFocus(true);
189     scope->setFocus(true);
190     scopedChild2->setFocus(true);
191     QCOMPARE(root->hasFocus(), true);
192     QCOMPARE(child->hasFocus(), false);
193     QCOMPARE(scope->hasFocus(), true);
194     QCOMPARE(scopedChild->hasFocus(), false);
195     QCOMPARE(scopedChild2->hasFocus(), true);
196
197     root->setFocus(false);
198     child->setFocus(true);
199     scopedChild->setFocus(true);
200     scope->setFocus(false);
201     QCOMPARE(root->hasFocus(), false);
202     QCOMPARE(child->hasFocus(), true);
203     QCOMPARE(scope->hasFocus(), false);
204     QCOMPARE(scopedChild->hasFocus(), true);
205     QCOMPARE(scopedChild2->hasFocus(), true);
206
207     delete root;
208 }
209
210 struct FocusData {
211     FocusData() : focus(false), activeFocus(false) {}
212
213     void set(bool f, bool af) { focus = f; activeFocus = af; }
214     bool focus;
215     bool activeFocus;
216 };
217 struct FocusState : public QHash<QQuickItem *, FocusData>
218 {
219     FocusState() : activeFocusItem(0) {}
220     FocusState &operator<<(QQuickItem *item) {
221         insert(item, FocusData());
222         return *this;
223     }
224
225     void active(QQuickItem *i) {
226         activeFocusItem = i;
227     }
228     QQuickItem *activeFocusItem;
229 };
230
231 #define FVERIFY() \
232     do { \
233         if (focusState.activeFocusItem) { \
234             QCOMPARE(canvas.activeFocusItem(), focusState.activeFocusItem); \
235             if (qobject_cast<TestItem *>(canvas.activeFocusItem())) \
236                 QCOMPARE(qobject_cast<TestItem *>(canvas.activeFocusItem())->focused, true); \
237             else if (qobject_cast<TestFocusScope *>(canvas.activeFocusItem())) \
238                 QCOMPARE(qobject_cast<TestFocusScope *>(canvas.activeFocusItem())->focused, true); \
239         } else { \
240             QCOMPARE(canvas.activeFocusItem(), canvas.rootItem()); \
241         } \
242         for (QHash<QQuickItem *, FocusData>::Iterator iter = focusState.begin(); \
243             iter != focusState.end(); \
244             iter++) { \
245             QCOMPARE(iter.key()->hasFocus(), iter.value().focus); \
246             QCOMPARE(iter.key()->hasActiveFocus(), iter.value().activeFocus); \
247         } \
248     } while (false)
249
250 // Tests a simple set of top-level scoped items
251 void tst_qquickitem::simpleFocus()
252 {
253     QQuickCanvas canvas;
254     ensureFocus(&canvas);
255     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
256
257     QQuickItem *l1c1 = new TestItem(canvas.rootItem());
258     QQuickItem *l1c2 = new TestItem(canvas.rootItem());
259     QQuickItem *l1c3 = new TestItem(canvas.rootItem());
260
261     QQuickItem *l2c1 = new TestItem(l1c1);
262     QQuickItem *l2c2 = new TestItem(l1c1);
263     QQuickItem *l2c3 = new TestItem(l1c3);
264
265     FocusState focusState;
266     focusState << l1c1 << l1c2 << l1c3
267                << l2c1 << l2c2 << l2c3;
268     FVERIFY();
269
270     l1c1->setFocus(true);
271     focusState[l1c1].set(true, true);
272     focusState.active(l1c1);
273     FVERIFY();
274
275     l2c3->setFocus(true);
276     focusState[l1c1].set(false, false);
277     focusState[l2c3].set(true, true);
278     focusState.active(l2c3);
279     FVERIFY();
280
281     l1c3->setFocus(true);
282     focusState[l2c3].set(false, false);
283     focusState[l1c3].set(true, true);
284     focusState.active(l1c3);
285     FVERIFY();
286
287     l1c2->setFocus(false);
288     FVERIFY();
289
290     l1c3->setFocus(false);
291     focusState[l1c3].set(false, false);
292     focusState.active(0);
293     FVERIFY();
294
295     l2c1->setFocus(true);
296     focusState[l2c1].set(true, true);
297     focusState.active(l2c1);
298     FVERIFY();
299 }
300
301 // Items with a focus scope
302 void tst_qquickitem::scopedFocus()
303 {
304     QQuickCanvas canvas;
305     ensureFocus(&canvas);
306     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
307
308     QQuickItem *l1c1 = new TestItem(canvas.rootItem());
309     QQuickItem *l1c2 = new TestItem(canvas.rootItem());
310     QQuickItem *l1c3 = new TestItem(canvas.rootItem());
311
312     QQuickItem *l2c1 = new TestItem(l1c1);
313     QQuickItem *l2c2 = new TestItem(l1c1);
314     QQuickItem *l2c3 = new TestFocusScope(l1c3);
315
316     QQuickItem *l3c1 = new TestItem(l2c3);
317     QQuickItem *l3c2 = new TestFocusScope(l2c3);
318
319     QQuickItem *l4c1 = new TestItem(l3c2);
320     QQuickItem *l4c2 = new TestItem(l3c2);
321
322     FocusState focusState;
323     focusState << l1c1 << l1c2 << l1c3
324                << l2c1 << l2c2 << l2c3
325                << l3c1 << l3c2
326                << l4c1 << l4c2;
327     FVERIFY();
328
329     l4c2->setFocus(true);
330     focusState[l4c2].set(true, false);
331     FVERIFY();
332
333     l4c1->setFocus(true);
334     focusState[l4c2].set(false, false);
335     focusState[l4c1].set(true, false);
336     FVERIFY();
337
338     l1c1->setFocus(true);
339     focusState[l1c1].set(true, true);
340     focusState.active(l1c1);
341     FVERIFY();
342
343     l3c2->setFocus(true);
344     focusState[l3c2].set(true, false);
345     FVERIFY();
346
347     l2c3->setFocus(true);
348     focusState[l1c1].set(false, false);
349     focusState[l2c3].set(true, true);
350     focusState[l3c2].set(true, true);
351     focusState[l4c1].set(true, true);
352     focusState.active(l4c1);
353     FVERIFY();
354
355     l3c2->setFocus(false);
356     focusState[l3c2].set(false, false);
357     focusState[l4c1].set(true, false);
358     focusState.active(l2c3);
359     FVERIFY();
360
361     l3c2->setFocus(true);
362     focusState[l3c2].set(true, true);
363     focusState[l4c1].set(true, true);
364     focusState.active(l4c1);
365     FVERIFY();
366
367     l4c1->setFocus(false);
368     focusState[l4c1].set(false, false);
369     focusState.active(l3c2);
370     FVERIFY();
371
372     l1c3->setFocus(true);
373     focusState[l1c3].set(true, true);
374     focusState[l2c3].set(false, false);
375     focusState[l3c2].set(true, false);
376     focusState.active(l1c3);
377     FVERIFY();
378 }
379
380 // Tests focus corrects itself when a tree is added to a canvas for the first time
381 void tst_qquickitem::addedToCanvas()
382 {
383     {
384     QQuickCanvas canvas;
385     ensureFocus(&canvas);
386     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
387
388     QQuickItem *item = new TestItem;
389
390     FocusState focusState;
391     focusState << item;
392
393     item->setFocus(true);
394     focusState[item].set(true, false);
395     FVERIFY();
396
397     item->setParentItem(canvas.rootItem());
398     focusState[item].set(true, true);
399     focusState.active(item);
400     FVERIFY();
401     }
402
403     {
404     QQuickCanvas canvas;
405     ensureFocus(&canvas);
406     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
407
408     QQuickItem *item = new TestItem(canvas.rootItem());
409
410     QQuickItem *tree = new TestItem;
411     QQuickItem *c1 = new TestItem(tree);
412     QQuickItem *c2 = new TestItem(tree);
413
414     FocusState focusState;
415     focusState << item << tree << c1 << c2;
416
417     item->setFocus(true);
418     c1->setFocus(true);
419     c2->setFocus(true);
420     focusState[item].set(true, true);
421     focusState[c1].set(true, false);
422     focusState[c2].set(true, false);
423     focusState.active(item);
424     FVERIFY();
425
426     tree->setParentItem(item);
427     focusState[c1].set(false, false);
428     focusState[c2].set(false, false);
429     FVERIFY();
430     }
431
432     {
433     QQuickCanvas canvas;
434     ensureFocus(&canvas);
435     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
436
437     QQuickItem *tree = new TestItem;
438     QQuickItem *c1 = new TestItem(tree);
439     QQuickItem *c2 = new TestItem(tree);
440
441     FocusState focusState;
442     focusState << tree << c1 << c2;
443     c1->setFocus(true);
444     c2->setFocus(true);
445     focusState[c1].set(true, false);
446     focusState[c2].set(true, false);
447     FVERIFY();
448
449     tree->setParentItem(canvas.rootItem());
450     focusState[c1].set(true, true);
451     focusState[c2].set(false, false);
452     focusState.active(c1);
453     FVERIFY();
454     }
455
456     {
457     QQuickCanvas canvas;
458     ensureFocus(&canvas);
459     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
460     QQuickItem *tree = new TestFocusScope;
461     QQuickItem *c1 = new TestItem(tree);
462     QQuickItem *c2 = new TestItem(tree);
463
464     FocusState focusState;
465     focusState << tree << c1 << c2;
466     c1->setFocus(true);
467     c2->setFocus(true);
468     focusState[c1].set(true, false);
469     focusState[c2].set(true, false);
470     FVERIFY();
471
472     tree->setParentItem(canvas.rootItem());
473     focusState[c1].set(true, false);
474     focusState[c2].set(false, false);
475     FVERIFY();
476
477     tree->setFocus(true);
478     focusState[tree].set(true, true);
479     focusState[c1].set(true, true);
480     focusState.active(c1);
481     FVERIFY();
482     }
483
484     {
485     QQuickCanvas canvas;
486     ensureFocus(&canvas);
487     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
488     QQuickItem *tree = new TestFocusScope;
489     QQuickItem *c1 = new TestItem(tree);
490     QQuickItem *c2 = new TestItem(tree);
491
492     FocusState focusState;
493     focusState << tree << c1 << c2;
494     tree->setFocus(true);
495     c1->setFocus(true);
496     c2->setFocus(true);
497     focusState[tree].set(true, false);
498     focusState[c1].set(true, false);
499     focusState[c2].set(true, false);
500     FVERIFY();
501
502     tree->setParentItem(canvas.rootItem());
503     focusState[tree].set(true, true);
504     focusState[c1].set(true, true);
505     focusState[c2].set(false, false);
506     focusState.active(c1);
507     FVERIFY();
508     }
509
510     {
511     QQuickCanvas canvas;
512     ensureFocus(&canvas);
513     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
514     QQuickItem *child = new TestItem(canvas.rootItem());
515     QQuickItem *tree = new TestFocusScope;
516     QQuickItem *c1 = new TestItem(tree);
517     QQuickItem *c2 = new TestItem(tree);
518
519     FocusState focusState;
520     focusState << child << tree << c1 << c2;
521     child->setFocus(true);
522     tree->setFocus(true);
523     c1->setFocus(true);
524     c2->setFocus(true);
525     focusState[child].set(true, true);
526     focusState[tree].set(true, false);
527     focusState[c1].set(true, false);
528     focusState[c2].set(true, false);
529     focusState.active(child);
530     FVERIFY();
531
532     tree->setParentItem(canvas.rootItem());
533     focusState[tree].set(false, false);
534     focusState[c1].set(true, false);
535     focusState[c2].set(false, false);
536     FVERIFY();
537
538     tree->setFocus(true);
539     focusState[child].set(false, false);
540     focusState[tree].set(true, true);
541     focusState[c1].set(true, true);
542     focusState.active(c1);
543     FVERIFY();
544     }
545 }
546
547 void tst_qquickitem::changeParent()
548 {
549     // Parent to no parent
550     {
551     QQuickCanvas canvas;
552     ensureFocus(&canvas);
553     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
554     QQuickItem *child = new TestItem(canvas.rootItem());
555
556     FocusState focusState;
557     focusState << child;
558     FVERIFY();
559
560     child->setFocus(true);
561     focusState[child].set(true, true);
562     focusState.active(child);
563     FVERIFY();
564
565     child->setParentItem(0);
566     focusState[child].set(true, false);
567     focusState.active(0);
568     FVERIFY();
569     }
570
571     // Different parent, same focus scope
572     {
573     QQuickCanvas canvas;
574     ensureFocus(&canvas);
575     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
576     QQuickItem *child = new TestItem(canvas.rootItem());
577     QQuickItem *child2 = new TestItem(canvas.rootItem());
578
579     FocusState focusState;
580     focusState << child << child2;
581     FVERIFY();
582
583     child->setFocus(true);
584     focusState[child].set(true, true);
585     focusState.active(child);
586     FVERIFY();
587
588     child->setParentItem(child2);
589     FVERIFY();
590     }
591
592     // Different parent, different focus scope
593     {
594     QQuickCanvas canvas;
595     ensureFocus(&canvas);
596     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
597     QQuickItem *child = new TestItem(canvas.rootItem());
598     QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
599     QQuickItem *item = new TestItem(child);
600
601     FocusState focusState;
602     focusState << child << child2 << item;
603     FVERIFY();
604
605     item->setFocus(true);
606     focusState[item].set(true, true);
607     focusState.active(item);
608     FVERIFY();
609
610     item->setParentItem(child2);
611     focusState[item].set(true, false);
612     focusState.active(0);
613     FVERIFY();
614     }
615     {
616     QQuickCanvas canvas;
617     ensureFocus(&canvas);
618     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
619     QQuickItem *child = new TestItem(canvas.rootItem());
620     QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
621     QQuickItem *item = new TestItem(child2);
622
623     FocusState focusState;
624     focusState << child << child2 << item;
625     FVERIFY();
626
627     item->setFocus(true);
628     focusState[item].set(true, false);
629     focusState.active(0);
630     FVERIFY();
631
632     item->setParentItem(child);
633     focusState[item].set(true, true);
634     focusState.active(item);
635     FVERIFY();
636     }
637     {
638     QQuickCanvas canvas;
639     ensureFocus(&canvas);
640     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
641     QQuickItem *child = new TestItem(canvas.rootItem());
642     QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
643     QQuickItem *item = new TestItem(child2);
644
645     FocusState focusState;
646     focusState << child << child2 << item;
647     FVERIFY();
648
649     child->setFocus(true);
650     item->setFocus(true);
651     focusState[child].set(true, true);
652     focusState[item].set(true, false);
653     focusState.active(child);
654     FVERIFY();
655
656     item->setParentItem(child);
657     focusState[item].set(false, false);
658     FVERIFY();
659     }
660
661 }
662
663 void tst_qquickitem::constructor()
664 {
665     QQuickItem *root = new QQuickItem;
666     QVERIFY(root->parent() == 0);
667     QVERIFY(root->parentItem() == 0);
668
669     QQuickItem *child1 = new QQuickItem(root);
670     QVERIFY(child1->parent() == root);
671     QVERIFY(child1->parentItem() == root);
672     QCOMPARE(root->childItems().count(), 1);
673     QCOMPARE(root->childItems().at(0), child1);
674
675     QQuickItem *child2 = new QQuickItem(root);
676     QVERIFY(child2->parent() == root);
677     QVERIFY(child2->parentItem() == root);
678     QCOMPARE(root->childItems().count(), 2);
679     QCOMPARE(root->childItems().at(0), child1);
680     QCOMPARE(root->childItems().at(1), child2);
681
682     delete root;
683 }
684
685 void tst_qquickitem::setParentItem()
686 {
687     QQuickItem *root = new QQuickItem;
688     QVERIFY(root->parent() == 0);
689     QVERIFY(root->parentItem() == 0);
690
691     QQuickItem *child1 = new QQuickItem;
692     QVERIFY(child1->parent() == 0);
693     QVERIFY(child1->parentItem() == 0);
694
695     child1->setParentItem(root);
696     QVERIFY(child1->parent() == 0);
697     QVERIFY(child1->parentItem() == root);
698     QCOMPARE(root->childItems().count(), 1);
699     QCOMPARE(root->childItems().at(0), child1);
700
701     QQuickItem *child2 = new QQuickItem;
702     QVERIFY(child2->parent() == 0);
703     QVERIFY(child2->parentItem() == 0);
704     child2->setParentItem(root);
705     QVERIFY(child2->parent() == 0);
706     QVERIFY(child2->parentItem() == root);
707     QCOMPARE(root->childItems().count(), 2);
708     QCOMPARE(root->childItems().at(0), child1);
709     QCOMPARE(root->childItems().at(1), child2);
710
711     child1->setParentItem(0);
712     QVERIFY(child1->parent() == 0);
713     QVERIFY(child1->parentItem() == 0);
714     QCOMPARE(root->childItems().count(), 1);
715     QCOMPARE(root->childItems().at(0), child2);
716
717     delete root;
718
719     QVERIFY(child1->parent() == 0);
720     QVERIFY(child1->parentItem() == 0);
721     QVERIFY(child2->parent() == 0);
722     QVERIFY(child2->parentItem() == 0);
723
724     delete child1;
725     delete child2;
726 }
727
728 void tst_qquickitem::visible()
729 {
730     QQuickItem *root = new QQuickItem;
731
732     QQuickItem *child1 = new QQuickItem;
733     child1->setParentItem(root);
734
735     QQuickItem *child2 = new QQuickItem;
736     child2->setParentItem(root);
737
738     QVERIFY(child1->isVisible());
739     QVERIFY(child2->isVisible());
740
741     root->setVisible(false);
742     QVERIFY(!child1->isVisible());
743     QVERIFY(!child2->isVisible());
744
745     root->setVisible(true);
746     QVERIFY(child1->isVisible());
747     QVERIFY(child2->isVisible());
748
749     child1->setVisible(false);
750     QVERIFY(!child1->isVisible());
751     QVERIFY(child2->isVisible());
752
753     child2->setParentItem(child1);
754     QVERIFY(!child1->isVisible());
755     QVERIFY(!child2->isVisible());
756
757     child2->setParentItem(root);
758     QVERIFY(!child1->isVisible());
759     QVERIFY(child2->isVisible());
760
761     delete root;
762     delete child1;
763     delete child2;
764 }
765
766 void tst_qquickitem::enabled()
767 {
768     QQuickItem *root = new QQuickItem;
769
770     QQuickItem *child1 = new QQuickItem;
771     child1->setParentItem(root);
772
773     QQuickItem *child2 = new QQuickItem;
774     child2->setParentItem(root);
775
776     QVERIFY(child1->isEnabled());
777     QVERIFY(child2->isEnabled());
778
779     root->setEnabled(false);
780     QVERIFY(!child1->isEnabled());
781     QVERIFY(!child2->isEnabled());
782
783     root->setEnabled(true);
784     QVERIFY(child1->isEnabled());
785     QVERIFY(child2->isEnabled());
786
787     child1->setEnabled(false);
788     QVERIFY(!child1->isEnabled());
789     QVERIFY(child2->isEnabled());
790
791     child2->setParentItem(child1);
792     QVERIFY(!child1->isEnabled());
793     QVERIFY(!child2->isEnabled());
794
795     child2->setParentItem(root);
796     QVERIFY(!child1->isEnabled());
797     QVERIFY(child2->isEnabled());
798
799     delete root;
800     delete child1;
801     delete child2;
802 }
803
804 void tst_qquickitem::mouseGrab()
805 {
806     QQuickCanvas *canvas = new QQuickCanvas;
807     canvas->resize(200, 200);
808     canvas->show();
809
810     TestItem *child1 = new TestItem;
811     child1->setAcceptedMouseButtons(Qt::LeftButton);
812     child1->setSize(QSizeF(200, 100));
813     child1->setParentItem(canvas->rootItem());
814
815     TestItem *child2 = new TestItem;
816     child2->setAcceptedMouseButtons(Qt::LeftButton);
817     child2->setY(51);
818     child2->setSize(QSizeF(200, 100));
819     child2->setParentItem(canvas->rootItem());
820
821     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
822     QTest::qWait(100);
823     QVERIFY(canvas->mouseGrabberItem() == child1);
824     QTest::qWait(100);
825
826     QCOMPARE(child1->pressCount, 1);
827     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
828     QTest::qWait(50);
829     QVERIFY(canvas->mouseGrabberItem() == 0);
830     QCOMPARE(child1->releaseCount, 1);
831
832     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
833     QTest::qWait(50);
834     QVERIFY(canvas->mouseGrabberItem() == child1);
835     QCOMPARE(child1->pressCount, 2);
836     child1->setEnabled(false);
837     QVERIFY(canvas->mouseGrabberItem() == 0);
838     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
839     QTest::qWait(50);
840     QCOMPARE(child1->releaseCount, 1);
841     child1->setEnabled(true);
842
843     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
844     QTest::qWait(50);
845     QVERIFY(canvas->mouseGrabberItem() == child1);
846     QCOMPARE(child1->pressCount, 3);
847     child1->setVisible(false);
848     QVERIFY(canvas->mouseGrabberItem() == 0);
849     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
850     QCOMPARE(child1->releaseCount, 1);
851     child1->setVisible(true);
852
853     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
854     QTest::qWait(50);
855     QVERIFY(canvas->mouseGrabberItem() == child1);
856     QCOMPARE(child1->pressCount, 4);
857     child2->grabMouse();
858     QVERIFY(canvas->mouseGrabberItem() == child2);
859     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
860     QTest::qWait(50);
861     QCOMPARE(child1->releaseCount, 1);
862     QCOMPARE(child2->releaseCount, 1);
863
864     child2->grabMouse();
865     QVERIFY(canvas->mouseGrabberItem() == child2);
866     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
867     QTest::qWait(50);
868     QCOMPARE(child1->pressCount, 4);
869     QCOMPARE(child2->pressCount, 1);
870     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
871     QTest::qWait(50);
872     QCOMPARE(child1->releaseCount, 1);
873     QCOMPARE(child2->releaseCount, 2);
874
875     delete child1;
876     delete child2;
877     delete canvas;
878 }
879
880 void tst_qquickitem::touchEventAccept()
881 {
882     TestCanvas *canvas = new TestCanvas;
883     canvas->resize(100, 100);
884     canvas->show();
885
886     TestItem *item = new TestItem;
887     item->setSize(QSizeF(100, 100));
888     item->setParentItem(canvas->rootItem());
889
890     static QTouchDevice* device = new QTouchDevice;
891     device->setType(QTouchDevice::TouchScreen);
892     QWindowSystemInterface::registerTouchDevice(device);
893
894     QTouchEvent *event = new QTouchEvent(QEvent::TouchBegin, device);
895
896     bool accepted = canvas->event(event);
897
898     QVERIFY(accepted && event->isAccepted());
899
900     delete event;
901     delete item;
902     delete canvas;
903 }
904
905 void tst_qquickitem::polishOutsideAnimation()
906 {
907     QQuickCanvas *canvas = new QQuickCanvas;
908     canvas->resize(200, 200);
909     canvas->show();
910
911     TestPolishItem *item = new TestPolishItem(canvas->rootItem());
912     item->setSize(QSizeF(200, 100));
913     QTest::qWait(50);
914
915     QTimer::singleShot(10, item, SLOT(doPolish()));
916     QTRY_VERIFY(item->wasPolished);
917
918     delete item;
919     delete canvas;
920 }
921
922 void tst_qquickitem::polishOnCompleted()
923 {
924     QQuickView *view = new QQuickView;
925     view->setSource(testFileUrl("polishOnCompleted.qml"));
926     view->show();
927
928     TestPolishItem *item = qobject_cast<TestPolishItem*>(view->rootObject());
929     QVERIFY(item);
930
931 #ifdef Q_OS_MAC
932     QSKIP("QTBUG-21590 view does not reliably receive polish without a running animation");
933 #endif
934
935     QTRY_VERIFY(item->wasPolished);
936
937     delete view;
938 }
939
940 void tst_qquickitem::wheelEvent_data()
941 {
942     QTest::addColumn<bool>("visible");
943     QTest::addColumn<bool>("enabled");
944
945     QTest::newRow("visible and enabled") << true << true;
946     QTest::newRow("visible and disabled") << true << false;
947     QTest::newRow("invisible and enabled") << false << true;
948     QTest::newRow("invisible and disabled") << false << false;
949 }
950
951 void tst_qquickitem::wheelEvent()
952 {
953     QFETCH(bool, visible);
954     QFETCH(bool, enabled);
955
956     const bool shouldReceiveWheelEvents = visible && enabled;
957
958     QQuickCanvas *canvas = new QQuickCanvas;
959     canvas->resize(200, 200);
960     canvas->show();
961
962     TestItem *item = new TestItem;
963     item->setSize(QSizeF(200, 100));
964     item->setParentItem(canvas->rootItem());
965
966     item->setEnabled(enabled);
967     item->setVisible(visible);
968
969     QWheelEvent event(QPoint(100, 50), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical);
970     event.setAccepted(false);
971     QGuiApplication::sendEvent(canvas, &event);
972
973     if (shouldReceiveWheelEvents) {
974         QVERIFY(event.isAccepted());
975         QCOMPARE(item->wheelCount, 1);
976     } else {
977         QVERIFY(!event.isAccepted());
978         QCOMPARE(item->wheelCount, 0);
979     }
980
981     delete canvas;
982 }
983
984 class HoverItem : public QQuickItem
985 {
986 Q_OBJECT
987 public:
988     HoverItem(QQuickItem *parent = 0)
989         : QQuickItem(parent), hoverEnterCount(0), hoverMoveCount(0), hoverLeaveCount(0)
990     { }
991     void resetCounters() {
992         hoverEnterCount = 0;
993         hoverMoveCount = 0;
994         hoverLeaveCount = 0;
995     }
996     int hoverEnterCount;
997     int hoverMoveCount;
998     int hoverLeaveCount;
999 protected:
1000     virtual void hoverEnterEvent(QHoverEvent *event) {
1001         event->accept();
1002         ++hoverEnterCount;
1003     }
1004     virtual void hoverMoveEvent(QHoverEvent *event) {
1005         event->accept();
1006         ++hoverMoveCount;
1007     }
1008     virtual void hoverLeaveEvent(QHoverEvent *event) {
1009         event->accept();
1010         ++hoverLeaveCount;
1011     }
1012 };
1013
1014 void tst_qquickitem::hoverEvent_data()
1015 {
1016     QTest::addColumn<bool>("visible");
1017     QTest::addColumn<bool>("enabled");
1018     QTest::addColumn<bool>("acceptHoverEvents");
1019
1020     QTest::newRow("visible, enabled, accept hover") << true << true << true;
1021     QTest::newRow("visible, disabled, accept hover") << true << false << true;
1022     QTest::newRow("invisible, enabled, accept hover") << false << true << true;
1023     QTest::newRow("invisible, disabled, accept hover") << false << false << true;
1024
1025     QTest::newRow("visible, enabled, not accept hover") << true << true << false;
1026     QTest::newRow("visible, disabled, not accept hover") << true << false << false;
1027     QTest::newRow("invisible, enabled, not accept hover") << false << true << false;
1028     QTest::newRow("invisible, disabled, not accept hover") << false << false << false;
1029 }
1030
1031 // ### For some unknown reason QTest::mouseMove() isn't working correctly.
1032 static void sendMouseMove(QObject *object, const QPoint &position)
1033 {
1034     QMouseEvent moveEvent(QEvent::MouseMove, position, Qt::NoButton, Qt::NoButton, 0);
1035     QGuiApplication::sendEvent(object, &moveEvent);
1036 }
1037
1038 void tst_qquickitem::hoverEvent()
1039 {
1040     QFETCH(bool, visible);
1041     QFETCH(bool, enabled);
1042     QFETCH(bool, acceptHoverEvents);
1043
1044     QQuickCanvas *canvas = new QQuickCanvas();
1045     canvas->resize(200, 200);
1046     canvas->show();
1047
1048     HoverItem *item = new HoverItem;
1049     item->setSize(QSizeF(100, 100));
1050     item->setParentItem(canvas->rootItem());
1051
1052     item->setEnabled(enabled);
1053     item->setVisible(visible);
1054     item->setAcceptHoverEvents(acceptHoverEvents);
1055
1056     const QPoint outside(150, 150);
1057     const QPoint inside(50, 50);
1058     const QPoint anotherInside(51, 51);
1059
1060     sendMouseMove(canvas, outside);
1061     item->resetCounters();
1062
1063     // Enter, then move twice inside, then leave.
1064     sendMouseMove(canvas, inside);
1065     sendMouseMove(canvas, anotherInside);
1066     sendMouseMove(canvas, inside);
1067     sendMouseMove(canvas, outside);
1068
1069     const bool shouldReceiveHoverEvents = visible && enabled && acceptHoverEvents;
1070     if (shouldReceiveHoverEvents) {
1071         QCOMPARE(item->hoverEnterCount, 1);
1072         QCOMPARE(item->hoverMoveCount, 2);
1073         QCOMPARE(item->hoverLeaveCount, 1);
1074     } else {
1075         QCOMPARE(item->hoverEnterCount, 0);
1076         QCOMPARE(item->hoverMoveCount, 0);
1077         QCOMPARE(item->hoverLeaveCount, 0);
1078     }
1079
1080     delete canvas;
1081 }
1082
1083 void tst_qquickitem::hoverEventInParent()
1084 {
1085     QQuickCanvas *canvas = new QQuickCanvas();
1086     canvas->resize(200, 200);
1087     canvas->show();
1088
1089     HoverItem *parentItem = new HoverItem(canvas->rootItem());
1090     parentItem->setSize(QSizeF(200, 200));
1091     parentItem->setAcceptHoverEvents(true);
1092
1093     HoverItem *leftItem = new HoverItem(parentItem);
1094     leftItem->setSize(QSizeF(100, 200));
1095     leftItem->setAcceptHoverEvents(true);
1096
1097     HoverItem *rightItem = new HoverItem(parentItem);
1098     rightItem->setSize(QSizeF(100, 200));
1099     rightItem->setPos(QPointF(100, 0));
1100     rightItem->setAcceptHoverEvents(true);
1101
1102     const QPoint insideLeft(50, 100);
1103     const QPoint insideRight(150, 100);
1104
1105     sendMouseMove(canvas, insideLeft);
1106     parentItem->resetCounters();
1107     leftItem->resetCounters();
1108     rightItem->resetCounters();
1109
1110     sendMouseMove(canvas, insideRight);
1111     QCOMPARE(parentItem->hoverEnterCount, 0);
1112     QCOMPARE(parentItem->hoverLeaveCount, 0);
1113     QCOMPARE(leftItem->hoverEnterCount, 0);
1114     QCOMPARE(leftItem->hoverLeaveCount, 1);
1115     QCOMPARE(rightItem->hoverEnterCount, 1);
1116     QCOMPARE(rightItem->hoverLeaveCount, 0);
1117
1118     sendMouseMove(canvas, insideLeft);
1119     QCOMPARE(parentItem->hoverEnterCount, 0);
1120     QCOMPARE(parentItem->hoverLeaveCount, 0);
1121     QCOMPARE(leftItem->hoverEnterCount, 1);
1122     QCOMPARE(leftItem->hoverLeaveCount, 1);
1123     QCOMPARE(rightItem->hoverEnterCount, 1);
1124     QCOMPARE(rightItem->hoverLeaveCount, 1);
1125
1126     delete canvas;
1127 }
1128
1129 void tst_qquickitem::paintOrder_data()
1130 {
1131     const QUrl order1Url = testFileUrl("order.1.qml");
1132     const QUrl order2Url = testFileUrl("order.2.qml");
1133
1134     QTest::addColumn<QUrl>("source");
1135     QTest::addColumn<int>("op");
1136     QTest::addColumn<QVariant>("param1");
1137     QTest::addColumn<QVariant>("param2");
1138     QTest::addColumn<QStringList>("expected");
1139
1140     QTest::newRow("test 1 noop") << order1Url
1141         << int(NoOp) << QVariant() << QVariant()
1142         << (QStringList() << "1" << "2" << "3");
1143     QTest::newRow("test 1 add") << order1Url
1144         << int(Append) << QVariant("new") << QVariant()
1145         << (QStringList() << "1" << "2" << "3" << "new");
1146     QTest::newRow("test 1 remove") << order1Url
1147         << int(Remove) << QVariant(1) << QVariant()
1148         << (QStringList() << "1" << "3");
1149     QTest::newRow("test 1 stack before") << order1Url
1150         << int(StackBefore) << QVariant(2) << QVariant(1)
1151         << (QStringList() << "1" << "3" << "2");
1152     QTest::newRow("test 1 stack after") << order1Url
1153         << int(StackAfter) << QVariant(0) << QVariant(1)
1154         << (QStringList() << "2" << "1" << "3");
1155     QTest::newRow("test 1 set z") << order1Url
1156         << int(SetZ) << QVariant(1) << QVariant(qreal(1.))
1157         << (QStringList() << "1" << "3" << "2");
1158
1159     QTest::newRow("test 2 noop") << order2Url
1160         << int(NoOp) << QVariant() << QVariant()
1161         << (QStringList() << "1" << "3" << "2");
1162     QTest::newRow("test 2 add") << order2Url
1163         << int(Append) << QVariant("new") << QVariant()
1164         << (QStringList() << "1" << "3" << "new" << "2");
1165     QTest::newRow("test 2 remove 1") << order2Url
1166         << int(Remove) << QVariant(1) << QVariant()
1167         << (QStringList() << "1" << "3");
1168     QTest::newRow("test 2 remove 2") << order2Url
1169         << int(Remove) << QVariant(2) << QVariant()
1170         << (QStringList() << "1" << "2");
1171     QTest::newRow("test 2 stack before 1") << order2Url
1172         << int(StackBefore) << QVariant(1) << QVariant(0)
1173         << (QStringList() << "1" << "3" << "2");
1174     QTest::newRow("test 2 stack before 2") << order2Url
1175         << int(StackBefore) << QVariant(2) << QVariant(0)
1176         << (QStringList() << "3" << "1" << "2");
1177     QTest::newRow("test 2 stack after 1") << order2Url
1178         << int(StackAfter) << QVariant(0) << QVariant(1)
1179         << (QStringList() << "1" << "3" << "2");
1180     QTest::newRow("test 2 stack after 2") << order2Url
1181         << int(StackAfter) << QVariant(0) << QVariant(2)
1182         << (QStringList() << "3" << "1" << "2");
1183     QTest::newRow("test 1 set z") << order1Url
1184         << int(SetZ) << QVariant(2) << QVariant(qreal(2.))
1185         << (QStringList() << "1" << "2" << "3");
1186 }
1187
1188 void tst_qquickitem::paintOrder()
1189 {
1190     QFETCH(QUrl, source);
1191     QFETCH(int, op);
1192     QFETCH(QVariant, param1);
1193     QFETCH(QVariant, param2);
1194     QFETCH(QStringList, expected);
1195
1196     QQuickView view;
1197     view.setSource(source);
1198
1199     QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject());
1200     QVERIFY(root);
1201
1202     switch (op) {
1203         case Append: {
1204                 QQuickItem *item = new QQuickItem(root);
1205                 item->setObjectName(param1.toString());
1206             }
1207             break;
1208         case Remove: {
1209                 QQuickItem *item = root->childItems().at(param1.toInt());
1210                 delete item;
1211             }
1212             break;
1213         case StackBefore: {
1214                 QQuickItem *item1 = root->childItems().at(param1.toInt());
1215                 QQuickItem *item2 = root->childItems().at(param2.toInt());
1216                 item1->stackBefore(item2);
1217             }
1218             break;
1219         case StackAfter: {
1220                 QQuickItem *item1 = root->childItems().at(param1.toInt());
1221                 QQuickItem *item2 = root->childItems().at(param2.toInt());
1222                 item1->stackAfter(item2);
1223             }
1224             break;
1225         case SetZ: {
1226                 QQuickItem *item = root->childItems().at(param1.toInt());
1227                 item->setZ(param2.toReal());
1228             }
1229             break;
1230         default:
1231             break;
1232     }
1233
1234     QList<QQuickItem*> list = QQuickItemPrivate::get(root)->paintOrderChildItems();
1235
1236     QStringList items;
1237     for (int i = 0; i < list.count(); ++i)
1238         items << list.at(i)->objectName();
1239
1240     QCOMPARE(items, expected);
1241 }
1242
1243
1244 QTEST_MAIN(tst_qquickitem)
1245
1246 #include "tst_qquickitem.moc"