35346c823677009641e10e64bb512b044763d4cb
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qquickitem / tst_qquickitem.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
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 "qquickitem.h"
45 #include "qquickcanvas.h"
46 #include <QtWidgets/QGraphicsSceneMouseEvent>
47 #include "private/qquickfocusscope_p.h"
48 #include <QDebug>
49 #include <QTimer>
50
51 class TestItem : public QQuickItem
52 {
53 Q_OBJECT
54 public:
55     TestItem(QQuickItem *parent = 0) : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0), wheelCount(0) {}
56
57     bool focused;
58     int pressCount;
59     int releaseCount;
60     int wheelCount;
61 protected:
62     virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
63     virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
64     virtual void mousePressEvent(QMouseEvent *event) { event->accept(); ++pressCount; }
65     virtual void mouseReleaseEvent(QMouseEvent *event) { event->accept(); ++releaseCount; }
66     virtual void wheelEvent(QWheelEvent *event) { event->accept(); ++wheelCount; }
67 };
68
69 class TestPolishItem : public QQuickItem
70 {
71 Q_OBJECT
72 public:
73     TestPolishItem(QQuickItem *parent)
74     : QQuickItem(parent), wasPolished(false) {
75         QTimer::singleShot(10, this, SLOT(doPolish()));
76     }
77
78     bool wasPolished;
79
80 protected:
81     virtual void updatePolish() {
82         wasPolished = true;
83     }
84
85 public slots:
86     void doPolish() {
87         polish();
88     }
89 };
90
91 class TestFocusScope : public QQuickFocusScope
92 {
93 Q_OBJECT
94 public:
95     TestFocusScope(QQuickItem *parent = 0) : QQuickFocusScope(parent), focused(false) {}
96
97     bool focused;
98 protected:
99     virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
100     virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
101 };
102
103 class tst_qquickitem : public QObject
104 {
105     Q_OBJECT
106 public:
107     tst_qquickitem();
108
109 private slots:
110     void initTestCase();
111     void cleanupTestCase();
112
113     void noCanvas();
114     void simpleFocus();
115     void scopedFocus();
116     void addedToCanvas();
117     void changeParent();
118
119     void constructor();
120     void setParentItem();
121
122     void visible();
123     void enabled();
124
125     void mouseGrab();
126     void polishOutsideAnimation();
127
128     void wheelEvent_data();
129     void wheelEvent();
130     void hoverEvent_data();
131     void hoverEvent();
132     void hoverEventInParent();
133
134 private:
135
136     void ensureFocus(QWindow *w) {
137         w->show();
138         w->requestActivateWindow();
139         qApp->processEvents();
140
141 #ifdef Q_WS_X11
142         // to be safe and avoid failing setFocus with window managers
143         qt_x11_wait_for_window_manager(w);
144 #endif
145     }
146 };
147
148 tst_qquickitem::tst_qquickitem()
149 {
150 }
151
152 void tst_qquickitem::initTestCase()
153 {
154 }
155
156 void tst_qquickitem::cleanupTestCase()
157 {
158 }
159
160 // Focus has no effect when outside a canvas
161 void tst_qquickitem::noCanvas()
162 {
163     QQuickItem *root = new TestItem;
164     QQuickItem *child = new TestItem(root);
165     QQuickItem *scope = new TestItem(root);
166     QQuickFocusScope *scopedChild = new TestFocusScope(scope);
167     QQuickFocusScope *scopedChild2 = new TestFocusScope(scope);
168
169     QCOMPARE(root->hasFocus(), false);
170     QCOMPARE(child->hasFocus(), false);
171     QCOMPARE(scope->hasFocus(), false);
172     QCOMPARE(scopedChild->hasFocus(), false);
173     QCOMPARE(scopedChild2->hasFocus(), false);
174
175     root->setFocus(true);
176     scope->setFocus(true);
177     scopedChild2->setFocus(true);
178     QCOMPARE(root->hasFocus(), true);
179     QCOMPARE(child->hasFocus(), false);
180     QCOMPARE(scope->hasFocus(), true);
181     QCOMPARE(scopedChild->hasFocus(), false);
182     QCOMPARE(scopedChild2->hasFocus(), true);
183
184     root->setFocus(false);
185     child->setFocus(true);
186     scopedChild->setFocus(true);
187     scope->setFocus(false);
188     QCOMPARE(root->hasFocus(), false);
189     QCOMPARE(child->hasFocus(), true);
190     QCOMPARE(scope->hasFocus(), false);
191     QCOMPARE(scopedChild->hasFocus(), true);
192     QCOMPARE(scopedChild2->hasFocus(), true);
193
194     delete root;
195 }
196
197 struct FocusData {
198     FocusData() : focus(false), activeFocus(false) {}
199
200     void set(bool f, bool af) { focus = f; activeFocus = af; }
201     bool focus;
202     bool activeFocus;
203 };
204 struct FocusState : public QHash<QQuickItem *, FocusData>
205 {
206     FocusState() : activeFocusItem(0) {}
207     FocusState &operator<<(QQuickItem *item) {
208         insert(item, FocusData());
209         return *this;
210     }
211
212     void active(QQuickItem *i) {
213         activeFocusItem = i;
214     }
215     QQuickItem *activeFocusItem;
216 };
217
218 #define FVERIFY() \
219     do { \
220         if (focusState.activeFocusItem) { \
221             QCOMPARE(canvas.activeFocusItem(), focusState.activeFocusItem); \
222             if (qobject_cast<TestItem *>(canvas.activeFocusItem())) \
223                 QCOMPARE(qobject_cast<TestItem *>(canvas.activeFocusItem())->focused, true); \
224             else if (qobject_cast<TestFocusScope *>(canvas.activeFocusItem())) \
225                 QCOMPARE(qobject_cast<TestFocusScope *>(canvas.activeFocusItem())->focused, true); \
226         } else { \
227             QCOMPARE(canvas.activeFocusItem(), canvas.rootItem()); \
228         } \
229         for (QHash<QQuickItem *, FocusData>::Iterator iter = focusState.begin(); \
230             iter != focusState.end(); \
231             iter++) { \
232             QCOMPARE(iter.key()->hasFocus(), iter.value().focus); \
233             QCOMPARE(iter.key()->hasActiveFocus(), iter.value().activeFocus); \
234         } \
235     } while (false)
236
237 // Tests a simple set of top-level scoped items
238 void tst_qquickitem::simpleFocus()
239 {
240     QQuickCanvas canvas;
241     ensureFocus(&canvas);
242     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
243
244     QQuickItem *l1c1 = new TestItem(canvas.rootItem());
245     QQuickItem *l1c2 = new TestItem(canvas.rootItem());
246     QQuickItem *l1c3 = new TestItem(canvas.rootItem());
247
248     QQuickItem *l2c1 = new TestItem(l1c1);
249     QQuickItem *l2c2 = new TestItem(l1c1);
250     QQuickItem *l2c3 = new TestItem(l1c3);
251
252     FocusState focusState;
253     focusState << l1c1 << l1c2 << l1c3
254                << l2c1 << l2c2 << l2c3;
255     FVERIFY();
256
257     l1c1->setFocus(true);
258     focusState[l1c1].set(true, true);
259     focusState.active(l1c1);
260     FVERIFY();
261
262     l2c3->setFocus(true);
263     focusState[l1c1].set(false, false);
264     focusState[l2c3].set(true, true);
265     focusState.active(l2c3);
266     FVERIFY();
267
268     l1c3->setFocus(true);
269     focusState[l2c3].set(false, false);
270     focusState[l1c3].set(true, true);
271     focusState.active(l1c3);
272     FVERIFY();
273
274     l1c2->setFocus(false);
275     FVERIFY();
276
277     l1c3->setFocus(false);
278     focusState[l1c3].set(false, false);
279     focusState.active(0);
280     FVERIFY();
281
282     l2c1->setFocus(true);
283     focusState[l2c1].set(true, true);
284     focusState.active(l2c1);
285     FVERIFY();
286 }
287
288 // Items with a focus scope
289 void tst_qquickitem::scopedFocus()
290 {
291     QQuickCanvas canvas;
292     ensureFocus(&canvas);
293     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
294
295     QQuickItem *l1c1 = new TestItem(canvas.rootItem());
296     QQuickItem *l1c2 = new TestItem(canvas.rootItem());
297     QQuickItem *l1c3 = new TestItem(canvas.rootItem());
298
299     QQuickItem *l2c1 = new TestItem(l1c1);
300     QQuickItem *l2c2 = new TestItem(l1c1);
301     QQuickItem *l2c3 = new TestFocusScope(l1c3);
302
303     QQuickItem *l3c1 = new TestItem(l2c3);
304     QQuickItem *l3c2 = new TestFocusScope(l2c3);
305
306     QQuickItem *l4c1 = new TestItem(l3c2);
307     QQuickItem *l4c2 = new TestItem(l3c2);
308
309     FocusState focusState;
310     focusState << l1c1 << l1c2 << l1c3
311                << l2c1 << l2c2 << l2c3
312                << l3c1 << l3c2
313                << l4c1 << l4c2;
314     FVERIFY();
315
316     l4c2->setFocus(true);
317     focusState[l4c2].set(true, false);
318     FVERIFY();
319
320     l4c1->setFocus(true);
321     focusState[l4c2].set(false, false);
322     focusState[l4c1].set(true, false);
323     FVERIFY();
324
325     l1c1->setFocus(true);
326     focusState[l1c1].set(true, true);
327     focusState.active(l1c1);
328     FVERIFY();
329
330     l3c2->setFocus(true);
331     focusState[l3c2].set(true, false);
332     FVERIFY();
333
334     l2c3->setFocus(true);
335     focusState[l1c1].set(false, false);
336     focusState[l2c3].set(true, true);
337     focusState[l3c2].set(true, true);
338     focusState[l4c1].set(true, true);
339     focusState.active(l4c1);
340     FVERIFY();
341
342     l3c2->setFocus(false);
343     focusState[l3c2].set(false, false);
344     focusState[l4c1].set(true, false);
345     focusState.active(l2c3);
346     FVERIFY();
347
348     l3c2->setFocus(true);
349     focusState[l3c2].set(true, true);
350     focusState[l4c1].set(true, true);
351     focusState.active(l4c1);
352     FVERIFY();
353
354     l4c1->setFocus(false);
355     focusState[l4c1].set(false, false);
356     focusState.active(l3c2);
357     FVERIFY();
358
359     l1c3->setFocus(true);
360     focusState[l1c3].set(true, true);
361     focusState[l2c3].set(false, false);
362     focusState[l3c2].set(true, false);
363     focusState.active(l1c3);
364     FVERIFY();
365 }
366
367 // Tests focus corrects itself when a tree is added to a canvas for the first time
368 void tst_qquickitem::addedToCanvas()
369 {
370     {
371     QQuickCanvas canvas;
372     ensureFocus(&canvas);
373     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
374
375     QQuickItem *item = new TestItem;
376
377     FocusState focusState;
378     focusState << item;
379
380     item->setFocus(true);
381     focusState[item].set(true, false);
382     FVERIFY();
383
384     item->setParentItem(canvas.rootItem());
385     focusState[item].set(true, true);
386     focusState.active(item);
387     FVERIFY();
388     }
389
390     {
391     QQuickCanvas canvas;
392     ensureFocus(&canvas);
393     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
394
395     QQuickItem *item = new TestItem(canvas.rootItem());
396
397     QQuickItem *tree = new TestItem;
398     QQuickItem *c1 = new TestItem(tree);
399     QQuickItem *c2 = new TestItem(tree);
400
401     FocusState focusState;
402     focusState << item << tree << c1 << c2;
403
404     item->setFocus(true);
405     c1->setFocus(true);
406     c2->setFocus(true);
407     focusState[item].set(true, true);
408     focusState[c1].set(true, false);
409     focusState[c2].set(true, false);
410     focusState.active(item);
411     FVERIFY();
412
413     tree->setParentItem(item);
414     focusState[c1].set(false, false);
415     focusState[c2].set(false, false);
416     FVERIFY();
417     }
418
419     {
420     QQuickCanvas canvas;
421     ensureFocus(&canvas);
422     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
423
424     QQuickItem *tree = new TestItem;
425     QQuickItem *c1 = new TestItem(tree);
426     QQuickItem *c2 = new TestItem(tree);
427
428     FocusState focusState;
429     focusState << tree << c1 << c2;
430     c1->setFocus(true);
431     c2->setFocus(true);
432     focusState[c1].set(true, false);
433     focusState[c2].set(true, false);
434     FVERIFY();
435
436     tree->setParentItem(canvas.rootItem());
437     focusState[c1].set(true, true);
438     focusState[c2].set(false, false);
439     focusState.active(c1);
440     FVERIFY();
441     }
442
443     {
444     QQuickCanvas canvas;
445     ensureFocus(&canvas);
446     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
447     QQuickItem *tree = new TestFocusScope;
448     QQuickItem *c1 = new TestItem(tree);
449     QQuickItem *c2 = new TestItem(tree);
450
451     FocusState focusState;
452     focusState << tree << c1 << c2;
453     c1->setFocus(true);
454     c2->setFocus(true);
455     focusState[c1].set(true, false);
456     focusState[c2].set(true, false);
457     FVERIFY();
458
459     tree->setParentItem(canvas.rootItem());
460     focusState[c1].set(true, false);
461     focusState[c2].set(false, false);
462     FVERIFY();
463
464     tree->setFocus(true);
465     focusState[tree].set(true, true);
466     focusState[c1].set(true, true);
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     tree->setFocus(true);
482     c1->setFocus(true);
483     c2->setFocus(true);
484     focusState[tree].set(true, false);
485     focusState[c1].set(true, false);
486     focusState[c2].set(true, false);
487     FVERIFY();
488
489     tree->setParentItem(canvas.rootItem());
490     focusState[tree].set(true, true);
491     focusState[c1].set(true, true);
492     focusState[c2].set(false, false);
493     focusState.active(c1);
494     FVERIFY();
495     }
496
497     {
498     QQuickCanvas canvas;
499     ensureFocus(&canvas);
500     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
501     QQuickItem *child = new TestItem(canvas.rootItem());
502     QQuickItem *tree = new TestFocusScope;
503     QQuickItem *c1 = new TestItem(tree);
504     QQuickItem *c2 = new TestItem(tree);
505
506     FocusState focusState;
507     focusState << child << tree << c1 << c2;
508     child->setFocus(true);
509     tree->setFocus(true);
510     c1->setFocus(true);
511     c2->setFocus(true);
512     focusState[child].set(true, true);
513     focusState[tree].set(true, false);
514     focusState[c1].set(true, false);
515     focusState[c2].set(true, false);
516     focusState.active(child);
517     FVERIFY();
518
519     tree->setParentItem(canvas.rootItem());
520     focusState[tree].set(false, false);
521     focusState[c1].set(true, false);
522     focusState[c2].set(false, false);
523     FVERIFY();
524
525     tree->setFocus(true);
526     focusState[child].set(false, false);
527     focusState[tree].set(true, true);
528     focusState[c1].set(true, true);
529     focusState.active(c1);
530     FVERIFY();
531     }
532 }
533
534 void tst_qquickitem::changeParent()
535 {
536     // Parent to no parent
537     {
538     QQuickCanvas canvas;
539     ensureFocus(&canvas);
540     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
541     QQuickItem *child = new TestItem(canvas.rootItem());
542
543     FocusState focusState;
544     focusState << child;
545     FVERIFY();
546
547     child->setFocus(true);
548     focusState[child].set(true, true);
549     focusState.active(child);
550     FVERIFY();
551
552     child->setParentItem(0);
553     focusState[child].set(true, false);
554     focusState.active(0);
555     FVERIFY();
556     }
557
558     // Different parent, same focus scope
559     {
560     QQuickCanvas canvas;
561     ensureFocus(&canvas);
562     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
563     QQuickItem *child = new TestItem(canvas.rootItem());
564     QQuickItem *child2 = new TestItem(canvas.rootItem());
565
566     FocusState focusState;
567     focusState << child << child2;
568     FVERIFY();
569
570     child->setFocus(true);
571     focusState[child].set(true, true);
572     focusState.active(child);
573     FVERIFY();
574
575     child->setParentItem(child2);
576     FVERIFY();
577     }
578
579     // Different parent, different focus scope
580     {
581     QQuickCanvas canvas;
582     ensureFocus(&canvas);
583     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
584     QQuickItem *child = new TestItem(canvas.rootItem());
585     QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
586     QQuickItem *item = new TestItem(child);
587
588     FocusState focusState;
589     focusState << child << child2 << item;
590     FVERIFY();
591
592     item->setFocus(true);
593     focusState[item].set(true, true);
594     focusState.active(item);
595     FVERIFY();
596
597     item->setParentItem(child2);
598     focusState[item].set(true, false);
599     focusState.active(0);
600     FVERIFY();
601     }
602     {
603     QQuickCanvas canvas;
604     ensureFocus(&canvas);
605     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
606     QQuickItem *child = new TestItem(canvas.rootItem());
607     QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
608     QQuickItem *item = new TestItem(child2);
609
610     FocusState focusState;
611     focusState << child << child2 << item;
612     FVERIFY();
613
614     item->setFocus(true);
615     focusState[item].set(true, false);
616     focusState.active(0);
617     FVERIFY();
618
619     item->setParentItem(child);
620     focusState[item].set(true, true);
621     focusState.active(item);
622     FVERIFY();
623     }
624     {
625     QQuickCanvas canvas;
626     ensureFocus(&canvas);
627     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
628     QQuickItem *child = new TestItem(canvas.rootItem());
629     QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
630     QQuickItem *item = new TestItem(child2);
631
632     FocusState focusState;
633     focusState << child << child2 << item;
634     FVERIFY();
635
636     child->setFocus(true);
637     item->setFocus(true);
638     focusState[child].set(true, true);
639     focusState[item].set(true, false);
640     focusState.active(child);
641     FVERIFY();
642
643     item->setParentItem(child);
644     focusState[item].set(false, false);
645     FVERIFY();
646     }
647
648 }
649
650 void tst_qquickitem::constructor()
651 {
652     QQuickItem *root = new QQuickItem;
653     QVERIFY(root->parent() == 0);
654     QVERIFY(root->parentItem() == 0);
655
656     QQuickItem *child1 = new QQuickItem(root);
657     QVERIFY(child1->parent() == root);
658     QVERIFY(child1->parentItem() == root);
659     QCOMPARE(root->childItems().count(), 1);
660     QCOMPARE(root->childItems().at(0), child1);
661
662     QQuickItem *child2 = new QQuickItem(root);
663     QVERIFY(child2->parent() == root);
664     QVERIFY(child2->parentItem() == root);
665     QCOMPARE(root->childItems().count(), 2);
666     QCOMPARE(root->childItems().at(0), child1);
667     QCOMPARE(root->childItems().at(1), child2);
668
669     delete root;
670 }
671
672 void tst_qquickitem::setParentItem()
673 {
674     QQuickItem *root = new QQuickItem;
675     QVERIFY(root->parent() == 0);
676     QVERIFY(root->parentItem() == 0);
677
678     QQuickItem *child1 = new QQuickItem;
679     QVERIFY(child1->parent() == 0);
680     QVERIFY(child1->parentItem() == 0);
681
682     child1->setParentItem(root);
683     QVERIFY(child1->parent() == 0);
684     QVERIFY(child1->parentItem() == root);
685     QCOMPARE(root->childItems().count(), 1);
686     QCOMPARE(root->childItems().at(0), child1);
687
688     QQuickItem *child2 = new QQuickItem;
689     QVERIFY(child2->parent() == 0);
690     QVERIFY(child2->parentItem() == 0);
691     child2->setParentItem(root);
692     QVERIFY(child2->parent() == 0);
693     QVERIFY(child2->parentItem() == root);
694     QCOMPARE(root->childItems().count(), 2);
695     QCOMPARE(root->childItems().at(0), child1);
696     QCOMPARE(root->childItems().at(1), child2);
697
698     child1->setParentItem(0);
699     QVERIFY(child1->parent() == 0);
700     QVERIFY(child1->parentItem() == 0);
701     QCOMPARE(root->childItems().count(), 1);
702     QCOMPARE(root->childItems().at(0), child2);
703
704     delete root;
705
706     QVERIFY(child1->parent() == 0);
707     QVERIFY(child1->parentItem() == 0);
708     QVERIFY(child2->parent() == 0);
709     QVERIFY(child2->parentItem() == 0);
710
711     delete child1;
712     delete child2;
713 }
714
715 void tst_qquickitem::visible()
716 {
717     QQuickItem *root = new QQuickItem;
718
719     QQuickItem *child1 = new QQuickItem;
720     child1->setParentItem(root);
721
722     QQuickItem *child2 = new QQuickItem;
723     child2->setParentItem(root);
724
725     QVERIFY(child1->isVisible());
726     QVERIFY(child2->isVisible());
727
728     root->setVisible(false);
729     QVERIFY(!child1->isVisible());
730     QVERIFY(!child2->isVisible());
731
732     root->setVisible(true);
733     QVERIFY(child1->isVisible());
734     QVERIFY(child2->isVisible());
735
736     child1->setVisible(false);
737     QVERIFY(!child1->isVisible());
738     QVERIFY(child2->isVisible());
739
740     child2->setParentItem(child1);
741     QVERIFY(!child1->isVisible());
742     QVERIFY(!child2->isVisible());
743
744     child2->setParentItem(root);
745     QVERIFY(!child1->isVisible());
746     QVERIFY(child2->isVisible());
747
748     delete root;
749     delete child1;
750     delete child2;
751 }
752
753 void tst_qquickitem::enabled()
754 {
755     QQuickItem *root = new QQuickItem;
756
757     QQuickItem *child1 = new QQuickItem;
758     child1->setParentItem(root);
759
760     QQuickItem *child2 = new QQuickItem;
761     child2->setParentItem(root);
762
763     QVERIFY(child1->isEnabled());
764     QVERIFY(child2->isEnabled());
765
766     root->setEnabled(false);
767     QVERIFY(!child1->isEnabled());
768     QVERIFY(!child2->isEnabled());
769
770     root->setEnabled(true);
771     QVERIFY(child1->isEnabled());
772     QVERIFY(child2->isEnabled());
773
774     child1->setEnabled(false);
775     QVERIFY(!child1->isEnabled());
776     QVERIFY(child2->isEnabled());
777
778     child2->setParentItem(child1);
779     QVERIFY(!child1->isEnabled());
780     QVERIFY(!child2->isEnabled());
781
782     child2->setParentItem(root);
783     QVERIFY(!child1->isEnabled());
784     QVERIFY(child2->isEnabled());
785
786     delete root;
787     delete child1;
788     delete child2;
789 }
790
791 void tst_qquickitem::mouseGrab()
792 {
793     QQuickCanvas *canvas = new QQuickCanvas;
794     canvas->resize(200, 200);
795     canvas->show();
796
797     TestItem *child1 = new TestItem;
798     child1->setAcceptedMouseButtons(Qt::LeftButton);
799     child1->setSize(QSizeF(200, 100));
800     child1->setParentItem(canvas->rootItem());
801
802     TestItem *child2 = new TestItem;
803     child2->setAcceptedMouseButtons(Qt::LeftButton);
804     child2->setY(51);
805     child2->setSize(QSizeF(200, 100));
806     child2->setParentItem(canvas->rootItem());
807
808     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
809     QTest::qWait(100);
810     qDebug() << canvas->mouseGrabberItem();
811     QVERIFY(canvas->mouseGrabberItem() == child1);
812     QTest::qWait(100);
813
814     QCOMPARE(child1->pressCount, 1);
815     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
816     QTest::qWait(50);
817     QVERIFY(canvas->mouseGrabberItem() == 0);
818     QCOMPARE(child1->releaseCount, 1);
819
820     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
821     QTest::qWait(50);
822     QVERIFY(canvas->mouseGrabberItem() == child1);
823     QCOMPARE(child1->pressCount, 2);
824     child1->setEnabled(false);
825     QVERIFY(canvas->mouseGrabberItem() == 0);
826     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
827     QTest::qWait(50);
828     QCOMPARE(child1->releaseCount, 1);
829     child1->setEnabled(true);
830
831     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
832     QTest::qWait(50);
833     QVERIFY(canvas->mouseGrabberItem() == child1);
834     QCOMPARE(child1->pressCount, 3);
835     child1->setVisible(false);
836     QVERIFY(canvas->mouseGrabberItem() == 0);
837     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
838     QCOMPARE(child1->releaseCount, 1);
839     child1->setVisible(true);
840
841     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
842     QTest::qWait(50);
843     QVERIFY(canvas->mouseGrabberItem() == child1);
844     QCOMPARE(child1->pressCount, 4);
845     child2->grabMouse();
846     QVERIFY(canvas->mouseGrabberItem() == child2);
847     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
848     QTest::qWait(50);
849     QCOMPARE(child1->releaseCount, 1);
850     QCOMPARE(child2->releaseCount, 1);
851
852     child2->grabMouse();
853     QVERIFY(canvas->mouseGrabberItem() == child2);
854     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
855     QTest::qWait(50);
856     QCOMPARE(child1->pressCount, 4);
857     QCOMPARE(child2->pressCount, 1);
858     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
859     QTest::qWait(50);
860     QCOMPARE(child1->releaseCount, 1);
861     QCOMPARE(child2->releaseCount, 2);
862
863     delete child1;
864     delete child2;
865     delete canvas;
866 }
867
868 void tst_qquickitem::polishOutsideAnimation()
869 {
870     QQuickCanvas *canvas = new QQuickCanvas;
871     canvas->resize(200, 200);
872     canvas->show();
873
874     TestPolishItem *item = new TestPolishItem(canvas->rootItem());
875     item->setSize(QSizeF(200, 100));
876     QTest::qWait(50);
877     QTRY_VERIFY(item->wasPolished);
878
879     delete item;
880     delete canvas;
881 }
882
883 void tst_qquickitem::wheelEvent_data()
884 {
885     QTest::addColumn<bool>("visible");
886     QTest::addColumn<bool>("enabled");
887
888     QTest::newRow("visible and enabled") << true << true;
889     QTest::newRow("visible and disabled") << true << false;
890     QTest::newRow("invisible and enabled") << false << true;
891     QTest::newRow("invisible and disabled") << false << false;
892 }
893
894 void tst_qquickitem::wheelEvent()
895 {
896     QFETCH(bool, visible);
897     QFETCH(bool, enabled);
898
899     const bool shouldReceiveWheelEvents = visible && enabled;
900
901     QQuickCanvas *canvas = new QQuickCanvas;
902     canvas->resize(200, 200);
903     canvas->show();
904
905     TestItem *item = new TestItem;
906     item->setSize(QSizeF(200, 100));
907     item->setParentItem(canvas->rootItem());
908
909     item->setEnabled(enabled);
910     item->setVisible(visible);
911
912     QWheelEvent event(QPoint(100, 50), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical);
913     event.setAccepted(false);
914     QApplication::sendEvent(canvas, &event);
915
916     if (shouldReceiveWheelEvents) {
917         QVERIFY(event.isAccepted());
918         QCOMPARE(item->wheelCount, 1);
919     } else {
920         QVERIFY(!event.isAccepted());
921         QCOMPARE(item->wheelCount, 0);
922     }
923
924     delete canvas;
925 }
926
927 class HoverItem : public QQuickItem
928 {
929 Q_OBJECT
930 public:
931     HoverItem(QQuickItem *parent = 0)
932         : QQuickItem(parent), hoverEnterCount(0), hoverMoveCount(0), hoverLeaveCount(0)
933     { }
934     void resetCounters() {
935         hoverEnterCount = 0;
936         hoverMoveCount = 0;
937         hoverLeaveCount = 0;
938     }
939     int hoverEnterCount;
940     int hoverMoveCount;
941     int hoverLeaveCount;
942 protected:
943     virtual void hoverEnterEvent(QHoverEvent *event) {
944         event->accept();
945         ++hoverEnterCount;
946     }
947     virtual void hoverMoveEvent(QHoverEvent *event) {
948         event->accept();
949         ++hoverMoveCount;
950     }
951     virtual void hoverLeaveEvent(QHoverEvent *event) {
952         event->accept();
953         ++hoverLeaveCount;
954     }
955 };
956
957 void tst_qquickitem::hoverEvent_data()
958 {
959     QTest::addColumn<bool>("visible");
960     QTest::addColumn<bool>("enabled");
961     QTest::addColumn<bool>("acceptHoverEvents");
962
963     QTest::newRow("visible, enabled, accept hover") << true << true << true;
964     QTest::newRow("visible, disabled, accept hover") << true << false << true;
965     QTest::newRow("invisible, enabled, accept hover") << false << true << true;
966     QTest::newRow("invisible, disabled, accept hover") << false << false << true;
967
968     QTest::newRow("visible, enabled, not accept hover") << true << true << false;
969     QTest::newRow("visible, disabled, not accept hover") << true << false << false;
970     QTest::newRow("invisible, enabled, not accept hover") << false << true << false;
971     QTest::newRow("invisible, disabled, not accept hover") << false << false << false;
972 }
973
974 // ### For some unknown reason QTest::mouseMove() isn't working correctly.
975 static void sendMouseMove(QObject *object, const QPoint &position)
976 {
977     QMouseEvent moveEvent(QEvent::MouseMove, position, Qt::NoButton, Qt::NoButton, 0);
978     QApplication::sendEvent(object, &moveEvent);
979 }
980
981 void tst_qquickitem::hoverEvent()
982 {
983     QFETCH(bool, visible);
984     QFETCH(bool, enabled);
985     QFETCH(bool, acceptHoverEvents);
986
987     QQuickCanvas *canvas = new QQuickCanvas();
988     canvas->resize(200, 200);
989     canvas->show();
990
991     HoverItem *item = new HoverItem;
992     item->setSize(QSizeF(100, 100));
993     item->setParentItem(canvas->rootItem());
994
995     item->setEnabled(enabled);
996     item->setVisible(visible);
997     item->setAcceptHoverEvents(acceptHoverEvents);
998
999     const QPoint outside(150, 150);
1000     const QPoint inside(50, 50);
1001     const QPoint anotherInside(51, 51);
1002
1003     sendMouseMove(canvas, outside);
1004     item->resetCounters();
1005
1006     // Enter, then move twice inside, then leave.
1007     sendMouseMove(canvas, inside);
1008     sendMouseMove(canvas, anotherInside);
1009     sendMouseMove(canvas, inside);
1010     sendMouseMove(canvas, outside);
1011
1012     const bool shouldReceiveHoverEvents = visible && enabled && acceptHoverEvents;
1013     if (shouldReceiveHoverEvents) {
1014         QCOMPARE(item->hoverEnterCount, 1);
1015         QCOMPARE(item->hoverMoveCount, 2);
1016         QCOMPARE(item->hoverLeaveCount, 1);
1017     } else {
1018         QCOMPARE(item->hoverEnterCount, 0);
1019         QCOMPARE(item->hoverMoveCount, 0);
1020         QCOMPARE(item->hoverLeaveCount, 0);
1021     }
1022
1023     delete canvas;
1024 }
1025
1026 void tst_qquickitem::hoverEventInParent()
1027 {
1028     QQuickCanvas *canvas = new QQuickCanvas();
1029     canvas->resize(200, 200);
1030     canvas->show();
1031
1032     HoverItem *parentItem = new HoverItem(canvas->rootItem());
1033     parentItem->setSize(QSizeF(200, 200));
1034     parentItem->setAcceptHoverEvents(true);
1035
1036     HoverItem *leftItem = new HoverItem(parentItem);
1037     leftItem->setSize(QSizeF(100, 200));
1038     leftItem->setAcceptHoverEvents(true);
1039
1040     HoverItem *rightItem = new HoverItem(parentItem);
1041     rightItem->setSize(QSizeF(100, 200));
1042     rightItem->setPos(QPointF(100, 0));
1043     rightItem->setAcceptHoverEvents(true);
1044
1045     const QPoint insideLeft(50, 100);
1046     const QPoint insideRight(150, 100);
1047
1048     sendMouseMove(canvas, insideLeft);
1049     parentItem->resetCounters();
1050     leftItem->resetCounters();
1051     rightItem->resetCounters();
1052
1053     sendMouseMove(canvas, insideRight);
1054     QCOMPARE(parentItem->hoverEnterCount, 0);
1055     QCOMPARE(parentItem->hoverLeaveCount, 0);
1056     QCOMPARE(leftItem->hoverEnterCount, 0);
1057     QCOMPARE(leftItem->hoverLeaveCount, 1);
1058     QCOMPARE(rightItem->hoverEnterCount, 1);
1059     QCOMPARE(rightItem->hoverLeaveCount, 0);
1060
1061     sendMouseMove(canvas, insideLeft);
1062     QCOMPARE(parentItem->hoverEnterCount, 0);
1063     QCOMPARE(parentItem->hoverLeaveCount, 0);
1064     QCOMPARE(leftItem->hoverEnterCount, 1);
1065     QCOMPARE(leftItem->hoverLeaveCount, 1);
1066     QCOMPARE(rightItem->hoverEnterCount, 1);
1067     QCOMPARE(rightItem->hoverLeaveCount, 1);
1068
1069     delete canvas;
1070 }
1071
1072 QTEST_MAIN(tst_qquickitem)
1073
1074 #include "tst_qquickitem.moc"