1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the test suite of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
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"
52 #include "../../shared/util.h"
54 class TestItem : public QQuickItem
58 TestItem(QQuickItem *parent = 0) : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0), wheelCount(0) {}
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; }
73 class TestCanvas: public QQuickCanvas
80 virtual bool event(QEvent *event)
82 return QQuickCanvas::event(event);
86 class TestPolishItem : public QQuickItem
90 TestPolishItem(QQuickItem *parent = 0)
91 : QQuickItem(parent), wasPolished(false) {
98 virtual void updatePolish() {
108 class TestFocusScope : public QQuickFocusScope
112 TestFocusScope(QQuickItem *parent = 0) : QQuickFocusScope(parent), focused(false) {}
116 virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
117 virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
120 class tst_qquickitem : public QDeclarativeDataTest
131 void addedToCanvas();
135 void setParentItem();
141 void touchEventAccept();
142 void polishOutsideAnimation();
143 void polishOnCompleted();
145 void wheelEvent_data();
147 void hoverEvent_data();
149 void hoverEventInParent();
151 void paintOrder_data();
157 NoOp, Append, Remove, StackBefore, StackAfter, SetZ
160 void ensureFocus(QWindow *w) {
162 w->requestActivateWindow();
163 qApp->processEvents();
167 void tst_qquickitem::initTestCase()
169 QDeclarativeDataTest::initTestCase();
170 qmlRegisterType<TestPolishItem>("Qt.test", 1, 0, "TestPolishItem");
173 // Focus has no effect when outside a canvas
174 void tst_qquickitem::noCanvas()
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);
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);
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);
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);
211 FocusData() : focus(false), activeFocus(false) {}
213 void set(bool f, bool af) { focus = f; activeFocus = af; }
217 struct FocusState : public QHash<QQuickItem *, FocusData>
219 FocusState() : activeFocusItem(0) {}
220 FocusState &operator<<(QQuickItem *item) {
221 insert(item, FocusData());
225 void active(QQuickItem *i) {
228 QQuickItem *activeFocusItem;
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); \
240 QCOMPARE(canvas.activeFocusItem(), canvas.rootItem()); \
242 for (QHash<QQuickItem *, FocusData>::Iterator iter = focusState.begin(); \
243 iter != focusState.end(); \
245 QCOMPARE(iter.key()->hasFocus(), iter.value().focus); \
246 QCOMPARE(iter.key()->hasActiveFocus(), iter.value().activeFocus); \
250 // Tests a simple set of top-level scoped items
251 void tst_qquickitem::simpleFocus()
254 ensureFocus(&canvas);
255 QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
257 QQuickItem *l1c1 = new TestItem(canvas.rootItem());
258 QQuickItem *l1c2 = new TestItem(canvas.rootItem());
259 QQuickItem *l1c3 = new TestItem(canvas.rootItem());
261 QQuickItem *l2c1 = new TestItem(l1c1);
262 QQuickItem *l2c2 = new TestItem(l1c1);
263 QQuickItem *l2c3 = new TestItem(l1c3);
265 FocusState focusState;
266 focusState << l1c1 << l1c2 << l1c3
267 << l2c1 << l2c2 << l2c3;
270 l1c1->setFocus(true);
271 focusState[l1c1].set(true, true);
272 focusState.active(l1c1);
275 l2c3->setFocus(true);
276 focusState[l1c1].set(false, false);
277 focusState[l2c3].set(true, true);
278 focusState.active(l2c3);
281 l1c3->setFocus(true);
282 focusState[l2c3].set(false, false);
283 focusState[l1c3].set(true, true);
284 focusState.active(l1c3);
287 l1c2->setFocus(false);
290 l1c3->setFocus(false);
291 focusState[l1c3].set(false, false);
292 focusState.active(0);
295 l2c1->setFocus(true);
296 focusState[l2c1].set(true, true);
297 focusState.active(l2c1);
301 // Items with a focus scope
302 void tst_qquickitem::scopedFocus()
305 ensureFocus(&canvas);
306 QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
308 QQuickItem *l1c1 = new TestItem(canvas.rootItem());
309 QQuickItem *l1c2 = new TestItem(canvas.rootItem());
310 QQuickItem *l1c3 = new TestItem(canvas.rootItem());
312 QQuickItem *l2c1 = new TestItem(l1c1);
313 QQuickItem *l2c2 = new TestItem(l1c1);
314 QQuickItem *l2c3 = new TestFocusScope(l1c3);
316 QQuickItem *l3c1 = new TestItem(l2c3);
317 QQuickItem *l3c2 = new TestFocusScope(l2c3);
319 QQuickItem *l4c1 = new TestItem(l3c2);
320 QQuickItem *l4c2 = new TestItem(l3c2);
322 FocusState focusState;
323 focusState << l1c1 << l1c2 << l1c3
324 << l2c1 << l2c2 << l2c3
329 l4c2->setFocus(true);
330 focusState[l4c2].set(true, false);
333 l4c1->setFocus(true);
334 focusState[l4c2].set(false, false);
335 focusState[l4c1].set(true, false);
338 l1c1->setFocus(true);
339 focusState[l1c1].set(true, true);
340 focusState.active(l1c1);
343 l3c2->setFocus(true);
344 focusState[l3c2].set(true, false);
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);
355 l3c2->setFocus(false);
356 focusState[l3c2].set(false, false);
357 focusState[l4c1].set(true, false);
358 focusState.active(l2c3);
361 l3c2->setFocus(true);
362 focusState[l3c2].set(true, true);
363 focusState[l4c1].set(true, true);
364 focusState.active(l4c1);
367 l4c1->setFocus(false);
368 focusState[l4c1].set(false, false);
369 focusState.active(l3c2);
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);
380 // Tests focus corrects itself when a tree is added to a canvas for the first time
381 void tst_qquickitem::addedToCanvas()
385 ensureFocus(&canvas);
386 QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
388 QQuickItem *item = new TestItem;
390 FocusState focusState;
393 item->setFocus(true);
394 focusState[item].set(true, false);
397 item->setParentItem(canvas.rootItem());
398 focusState[item].set(true, true);
399 focusState.active(item);
405 ensureFocus(&canvas);
406 QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
408 QQuickItem *item = new TestItem(canvas.rootItem());
410 QQuickItem *tree = new TestItem;
411 QQuickItem *c1 = new TestItem(tree);
412 QQuickItem *c2 = new TestItem(tree);
414 FocusState focusState;
415 focusState << item << tree << c1 << c2;
417 item->setFocus(true);
420 focusState[item].set(true, true);
421 focusState[c1].set(true, false);
422 focusState[c2].set(true, false);
423 focusState.active(item);
426 tree->setParentItem(item);
427 focusState[c1].set(false, false);
428 focusState[c2].set(false, false);
434 ensureFocus(&canvas);
435 QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
437 QQuickItem *tree = new TestItem;
438 QQuickItem *c1 = new TestItem(tree);
439 QQuickItem *c2 = new TestItem(tree);
441 FocusState focusState;
442 focusState << tree << c1 << c2;
445 focusState[c1].set(true, false);
446 focusState[c2].set(true, false);
449 tree->setParentItem(canvas.rootItem());
450 focusState[c1].set(true, true);
451 focusState[c2].set(false, false);
452 focusState.active(c1);
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);
464 FocusState focusState;
465 focusState << tree << c1 << c2;
468 focusState[c1].set(true, false);
469 focusState[c2].set(true, false);
472 tree->setParentItem(canvas.rootItem());
473 focusState[c1].set(true, false);
474 focusState[c2].set(false, false);
477 tree->setFocus(true);
478 focusState[tree].set(true, true);
479 focusState[c1].set(true, true);
480 focusState.active(c1);
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);
492 FocusState focusState;
493 focusState << tree << c1 << c2;
494 tree->setFocus(true);
497 focusState[tree].set(true, false);
498 focusState[c1].set(true, false);
499 focusState[c2].set(true, false);
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);
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);
519 FocusState focusState;
520 focusState << child << tree << c1 << c2;
521 child->setFocus(true);
522 tree->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);
532 tree->setParentItem(canvas.rootItem());
533 focusState[tree].set(false, false);
534 focusState[c1].set(true, false);
535 focusState[c2].set(false, false);
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);
547 void tst_qquickitem::changeParent()
549 // Parent to no parent
552 ensureFocus(&canvas);
553 QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
554 QQuickItem *child = new TestItem(canvas.rootItem());
556 FocusState focusState;
560 child->setFocus(true);
561 focusState[child].set(true, true);
562 focusState.active(child);
565 child->setParentItem(0);
566 focusState[child].set(true, false);
567 focusState.active(0);
571 // Different parent, same focus scope
574 ensureFocus(&canvas);
575 QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
576 QQuickItem *child = new TestItem(canvas.rootItem());
577 QQuickItem *child2 = new TestItem(canvas.rootItem());
579 FocusState focusState;
580 focusState << child << child2;
583 child->setFocus(true);
584 focusState[child].set(true, true);
585 focusState.active(child);
588 child->setParentItem(child2);
592 // Different parent, different focus scope
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);
601 FocusState focusState;
602 focusState << child << child2 << item;
605 item->setFocus(true);
606 focusState[item].set(true, true);
607 focusState.active(item);
610 item->setParentItem(child2);
611 focusState[item].set(true, false);
612 focusState.active(0);
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);
623 FocusState focusState;
624 focusState << child << child2 << item;
627 item->setFocus(true);
628 focusState[item].set(true, false);
629 focusState.active(0);
632 item->setParentItem(child);
633 focusState[item].set(true, true);
634 focusState.active(item);
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);
645 FocusState focusState;
646 focusState << child << child2 << item;
649 child->setFocus(true);
650 item->setFocus(true);
651 focusState[child].set(true, true);
652 focusState[item].set(true, false);
653 focusState.active(child);
656 item->setParentItem(child);
657 focusState[item].set(false, false);
663 void tst_qquickitem::constructor()
665 QQuickItem *root = new QQuickItem;
666 QVERIFY(root->parent() == 0);
667 QVERIFY(root->parentItem() == 0);
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);
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);
685 void tst_qquickitem::setParentItem()
687 QQuickItem *root = new QQuickItem;
688 QVERIFY(root->parent() == 0);
689 QVERIFY(root->parentItem() == 0);
691 QQuickItem *child1 = new QQuickItem;
692 QVERIFY(child1->parent() == 0);
693 QVERIFY(child1->parentItem() == 0);
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);
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);
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);
719 QVERIFY(child1->parent() == 0);
720 QVERIFY(child1->parentItem() == 0);
721 QVERIFY(child2->parent() == 0);
722 QVERIFY(child2->parentItem() == 0);
728 void tst_qquickitem::visible()
730 QQuickItem *root = new QQuickItem;
732 QQuickItem *child1 = new QQuickItem;
733 child1->setParentItem(root);
735 QQuickItem *child2 = new QQuickItem;
736 child2->setParentItem(root);
738 QVERIFY(child1->isVisible());
739 QVERIFY(child2->isVisible());
741 root->setVisible(false);
742 QVERIFY(!child1->isVisible());
743 QVERIFY(!child2->isVisible());
745 root->setVisible(true);
746 QVERIFY(child1->isVisible());
747 QVERIFY(child2->isVisible());
749 child1->setVisible(false);
750 QVERIFY(!child1->isVisible());
751 QVERIFY(child2->isVisible());
753 child2->setParentItem(child1);
754 QVERIFY(!child1->isVisible());
755 QVERIFY(!child2->isVisible());
757 child2->setParentItem(root);
758 QVERIFY(!child1->isVisible());
759 QVERIFY(child2->isVisible());
766 void tst_qquickitem::enabled()
768 QQuickItem *root = new QQuickItem;
770 QQuickItem *child1 = new QQuickItem;
771 child1->setParentItem(root);
773 QQuickItem *child2 = new QQuickItem;
774 child2->setParentItem(root);
776 QVERIFY(child1->isEnabled());
777 QVERIFY(child2->isEnabled());
779 root->setEnabled(false);
780 QVERIFY(!child1->isEnabled());
781 QVERIFY(!child2->isEnabled());
783 root->setEnabled(true);
784 QVERIFY(child1->isEnabled());
785 QVERIFY(child2->isEnabled());
787 child1->setEnabled(false);
788 QVERIFY(!child1->isEnabled());
789 QVERIFY(child2->isEnabled());
791 child2->setParentItem(child1);
792 QVERIFY(!child1->isEnabled());
793 QVERIFY(!child2->isEnabled());
795 child2->setParentItem(root);
796 QVERIFY(!child1->isEnabled());
797 QVERIFY(child2->isEnabled());
804 void tst_qquickitem::mouseGrab()
806 QQuickCanvas *canvas = new QQuickCanvas;
807 canvas->resize(200, 200);
810 TestItem *child1 = new TestItem;
811 child1->setAcceptedMouseButtons(Qt::LeftButton);
812 child1->setSize(QSizeF(200, 100));
813 child1->setParentItem(canvas->rootItem());
815 TestItem *child2 = new TestItem;
816 child2->setAcceptedMouseButtons(Qt::LeftButton);
818 child2->setSize(QSizeF(200, 100));
819 child2->setParentItem(canvas->rootItem());
821 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
823 QVERIFY(canvas->mouseGrabberItem() == child1);
826 QCOMPARE(child1->pressCount, 1);
827 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
829 QVERIFY(canvas->mouseGrabberItem() == 0);
830 QCOMPARE(child1->releaseCount, 1);
832 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,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));
840 QCOMPARE(child1->releaseCount, 1);
841 child1->setEnabled(true);
843 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,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);
853 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
855 QVERIFY(canvas->mouseGrabberItem() == child1);
856 QCOMPARE(child1->pressCount, 4);
858 QVERIFY(canvas->mouseGrabberItem() == child2);
859 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
861 QCOMPARE(child1->releaseCount, 1);
862 QCOMPARE(child2->releaseCount, 1);
865 QVERIFY(canvas->mouseGrabberItem() == child2);
866 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
868 QCOMPARE(child1->pressCount, 4);
869 QCOMPARE(child2->pressCount, 1);
870 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
872 QCOMPARE(child1->releaseCount, 1);
873 QCOMPARE(child2->releaseCount, 2);
880 void tst_qquickitem::touchEventAccept()
882 TestCanvas *canvas = new TestCanvas;
883 canvas->resize(100, 100);
886 TestItem *item = new TestItem;
887 item->setSize(QSizeF(100, 100));
888 item->setParentItem(canvas->rootItem());
890 static QTouchDevice* device = new QTouchDevice;
891 device->setType(QTouchDevice::TouchScreen);
892 QWindowSystemInterface::registerTouchDevice(device);
894 QTouchEvent *event = new QTouchEvent(QEvent::TouchBegin, device);
896 bool accepted = canvas->event(event);
898 QVERIFY(accepted && event->isAccepted());
905 void tst_qquickitem::polishOutsideAnimation()
907 QQuickCanvas *canvas = new QQuickCanvas;
908 canvas->resize(200, 200);
911 TestPolishItem *item = new TestPolishItem(canvas->rootItem());
912 item->setSize(QSizeF(200, 100));
915 QTimer::singleShot(10, item, SLOT(doPolish()));
916 QTRY_VERIFY(item->wasPolished);
922 void tst_qquickitem::polishOnCompleted()
924 QQuickView *view = new QQuickView;
925 view->setSource(testFileUrl("polishOnCompleted.qml"));
928 TestPolishItem *item = qobject_cast<TestPolishItem*>(view->rootObject());
932 QSKIP("QTBUG-21590 view does not reliably receive polish without a running animation");
935 QTRY_VERIFY(item->wasPolished);
940 void tst_qquickitem::wheelEvent_data()
942 QTest::addColumn<bool>("visible");
943 QTest::addColumn<bool>("enabled");
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;
951 void tst_qquickitem::wheelEvent()
953 QFETCH(bool, visible);
954 QFETCH(bool, enabled);
956 const bool shouldReceiveWheelEvents = visible && enabled;
958 QQuickCanvas *canvas = new QQuickCanvas;
959 canvas->resize(200, 200);
962 TestItem *item = new TestItem;
963 item->setSize(QSizeF(200, 100));
964 item->setParentItem(canvas->rootItem());
966 item->setEnabled(enabled);
967 item->setVisible(visible);
969 QWheelEvent event(QPoint(100, 50), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical);
970 event.setAccepted(false);
971 QGuiApplication::sendEvent(canvas, &event);
973 if (shouldReceiveWheelEvents) {
974 QVERIFY(event.isAccepted());
975 QCOMPARE(item->wheelCount, 1);
977 QVERIFY(!event.isAccepted());
978 QCOMPARE(item->wheelCount, 0);
984 class HoverItem : public QQuickItem
988 HoverItem(QQuickItem *parent = 0)
989 : QQuickItem(parent), hoverEnterCount(0), hoverMoveCount(0), hoverLeaveCount(0)
991 void resetCounters() {
1000 virtual void hoverEnterEvent(QHoverEvent *event) {
1004 virtual void hoverMoveEvent(QHoverEvent *event) {
1008 virtual void hoverLeaveEvent(QHoverEvent *event) {
1014 void tst_qquickitem::hoverEvent_data()
1016 QTest::addColumn<bool>("visible");
1017 QTest::addColumn<bool>("enabled");
1018 QTest::addColumn<bool>("acceptHoverEvents");
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;
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;
1031 // ### For some unknown reason QTest::mouseMove() isn't working correctly.
1032 static void sendMouseMove(QObject *object, const QPoint &position)
1034 QMouseEvent moveEvent(QEvent::MouseMove, position, Qt::NoButton, Qt::NoButton, 0);
1035 QGuiApplication::sendEvent(object, &moveEvent);
1038 void tst_qquickitem::hoverEvent()
1040 QFETCH(bool, visible);
1041 QFETCH(bool, enabled);
1042 QFETCH(bool, acceptHoverEvents);
1044 QQuickCanvas *canvas = new QQuickCanvas();
1045 canvas->resize(200, 200);
1048 HoverItem *item = new HoverItem;
1049 item->setSize(QSizeF(100, 100));
1050 item->setParentItem(canvas->rootItem());
1052 item->setEnabled(enabled);
1053 item->setVisible(visible);
1054 item->setAcceptHoverEvents(acceptHoverEvents);
1056 const QPoint outside(150, 150);
1057 const QPoint inside(50, 50);
1058 const QPoint anotherInside(51, 51);
1060 sendMouseMove(canvas, outside);
1061 item->resetCounters();
1063 // Enter, then move twice inside, then leave.
1064 sendMouseMove(canvas, inside);
1065 sendMouseMove(canvas, anotherInside);
1066 sendMouseMove(canvas, inside);
1067 sendMouseMove(canvas, outside);
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);
1075 QCOMPARE(item->hoverEnterCount, 0);
1076 QCOMPARE(item->hoverMoveCount, 0);
1077 QCOMPARE(item->hoverLeaveCount, 0);
1083 void tst_qquickitem::hoverEventInParent()
1085 QQuickCanvas *canvas = new QQuickCanvas();
1086 canvas->resize(200, 200);
1089 HoverItem *parentItem = new HoverItem(canvas->rootItem());
1090 parentItem->setSize(QSizeF(200, 200));
1091 parentItem->setAcceptHoverEvents(true);
1093 HoverItem *leftItem = new HoverItem(parentItem);
1094 leftItem->setSize(QSizeF(100, 200));
1095 leftItem->setAcceptHoverEvents(true);
1097 HoverItem *rightItem = new HoverItem(parentItem);
1098 rightItem->setSize(QSizeF(100, 200));
1099 rightItem->setPos(QPointF(100, 0));
1100 rightItem->setAcceptHoverEvents(true);
1102 const QPoint insideLeft(50, 100);
1103 const QPoint insideRight(150, 100);
1105 sendMouseMove(canvas, insideLeft);
1106 parentItem->resetCounters();
1107 leftItem->resetCounters();
1108 rightItem->resetCounters();
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);
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);
1129 void tst_qquickitem::paintOrder_data()
1131 const QUrl order1Url = testFileUrl("order.1.qml");
1132 const QUrl order2Url = testFileUrl("order.2.qml");
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");
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");
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");
1188 void tst_qquickitem::paintOrder()
1190 QFETCH(QUrl, source);
1192 QFETCH(QVariant, param1);
1193 QFETCH(QVariant, param2);
1194 QFETCH(QStringList, expected);
1197 view.setSource(source);
1199 QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject());
1204 QQuickItem *item = new QQuickItem(root);
1205 item->setObjectName(param1.toString());
1209 QQuickItem *item = root->childItems().at(param1.toInt());
1214 QQuickItem *item1 = root->childItems().at(param1.toInt());
1215 QQuickItem *item2 = root->childItems().at(param2.toInt());
1216 item1->stackBefore(item2);
1220 QQuickItem *item1 = root->childItems().at(param1.toInt());
1221 QQuickItem *item2 = root->childItems().at(param2.toInt());
1222 item1->stackAfter(item2);
1226 QQuickItem *item = root->childItems().at(param1.toInt());
1227 item->setZ(param2.toReal());
1234 QList<QQuickItem*> list = QQuickItemPrivate::get(root)->paintOrderChildItems();
1237 for (int i = 0; i < list.count(); ++i)
1238 items << list.at(i)->objectName();
1240 QCOMPARE(items, expected);
1244 QTEST_MAIN(tst_qquickitem)
1246 #include "tst_qquickitem.moc"