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