diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2011-11-23 15:14:07 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-12-02 14:18:20 +0100 |
commit | 6c8378eaf1edbbefe6aaa3672b0127816a004fd7 (patch) | |
tree | 8ee08fb447e052f7a7a685fbeaaa04f04ea60126 /tests/auto/qtquick2/qquickitem/tst_qquickitem.cpp | |
parent | e01219b77b1e889e70437635905d7ff820568e23 (diff) |
Say hello to QtQuick module
This change moves the QtQuick 2 types and C++ API (including
SceneGraph) to a new module (AKA library), QtQuick.
99% of this change is moving files from src/declarative to
src/quick, and from tests/auto/declarative to
tests/auto/qtquick2.
The loading of QtQuick 2 ("import QtQuick 2.0") is now delegated to
a plugin, src/imports/qtquick2, just like it's done for QtQuick 1.
All tools, examples, and tests that use QtQuick C++ API have gotten
"QT += quick" or "QT += quick-private" added to their .pro file.
A few additional internal QtDeclarative classes had to be exported
(via Q_DECLARATIVE_PRIVATE_EXPORT) since they're needed by the
QtQuick 2 implementation.
The old header locations (e.g. QtDeclarative/qquickitem.h) will
still be supported for some time, but will produce compile-time
warnings. (To avoid the QtQuick implementation using the
compatibility headers (since QtDeclarative's includepath comes
first), a few include statements were modified, e.g. from
"#include <qsgnode.h>" to "#include <QtQuick/qsgnode.h>".)
There's a change in qtbase that automatically adds QtQuick to the
module list if QtDeclarative is used. Together with the compatibility
headers, this should help reduce the migration pain for existing
projects.
In theory, simply getting an existing QtDeclarative-based project
to compile and link shouldn't require any changes for now -- but
porting to the new scheme is of course recommended, and will
eventually become mandatory.
Task-number: QTBUG-22889
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Change-Id: Ia52be9373172ba2f37e7623231ecb060316c96a7
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Reviewed-by: Sergio Ahumada <sergio.ahumada@nokia.com>
Diffstat (limited to 'tests/auto/qtquick2/qquickitem/tst_qquickitem.cpp')
-rw-r--r-- | tests/auto/qtquick2/qquickitem/tst_qquickitem.cpp | 1190 |
1 files changed, 1190 insertions, 0 deletions
diff --git a/tests/auto/qtquick2/qquickitem/tst_qquickitem.cpp b/tests/auto/qtquick2/qquickitem/tst_qquickitem.cpp new file mode 100644 index 0000000000..fd7433b64e --- /dev/null +++ b/tests/auto/qtquick2/qquickitem/tst_qquickitem.cpp @@ -0,0 +1,1190 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> + +#include <QtQuick/qquickitem.h> +#include <QtQuick/qquickcanvas.h> +#include <QtQuick/qquickview.h> +#include <QtWidgets/QGraphicsSceneMouseEvent> +#include "private/qquickfocusscope_p.h" +#include "private/qquickitem_p.h" +#include <QDebug> +#include <QTimer> +#include "../../shared/util.h" + +class TestItem : public QQuickItem +{ +Q_OBJECT +public: + TestItem(QQuickItem *parent = 0) : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0), wheelCount(0) {} + + bool focused; + int pressCount; + int releaseCount; + int wheelCount; +protected: + virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; } + virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; } + virtual void mousePressEvent(QMouseEvent *event) { event->accept(); ++pressCount; } + virtual void mouseReleaseEvent(QMouseEvent *event) { event->accept(); ++releaseCount; } + virtual void wheelEvent(QWheelEvent *event) { event->accept(); ++wheelCount; } +}; + +class TestPolishItem : public QQuickItem +{ +Q_OBJECT +public: + TestPolishItem(QQuickItem *parent) + : QQuickItem(parent), wasPolished(false) { + QTimer::singleShot(10, this, SLOT(doPolish())); + } + + bool wasPolished; + +protected: + virtual void updatePolish() { + wasPolished = true; + } + +public slots: + void doPolish() { + polish(); + } +}; + +class TestFocusScope : public QQuickFocusScope +{ +Q_OBJECT +public: + TestFocusScope(QQuickItem *parent = 0) : QQuickFocusScope(parent), focused(false) {} + + bool focused; +protected: + virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; } + virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; } +}; + +class tst_qquickitem : public QObject +{ + Q_OBJECT +public: + tst_qquickitem(); + +private slots: + void initTestCase(); + void cleanupTestCase(); + + void noCanvas(); + void simpleFocus(); + void scopedFocus(); + void addedToCanvas(); + void changeParent(); + + void constructor(); + void setParentItem(); + + void visible(); + void enabled(); + + void mouseGrab(); + void polishOutsideAnimation(); + + void wheelEvent_data(); + void wheelEvent(); + void hoverEvent_data(); + void hoverEvent(); + void hoverEventInParent(); + + void paintOrder_data(); + void paintOrder(); + +private: + + enum PaintOrderOp { + NoOp, Append, Remove, StackBefore, StackAfter, SetZ + }; + + void ensureFocus(QWindow *w) { + w->show(); + w->requestActivateWindow(); + qApp->processEvents(); + } +}; + +tst_qquickitem::tst_qquickitem() +{ +} + +void tst_qquickitem::initTestCase() +{ +} + +void tst_qquickitem::cleanupTestCase() +{ +} + +// Focus has no effect when outside a canvas +void tst_qquickitem::noCanvas() +{ + QQuickItem *root = new TestItem; + QQuickItem *child = new TestItem(root); + QQuickItem *scope = new TestItem(root); + QQuickFocusScope *scopedChild = new TestFocusScope(scope); + QQuickFocusScope *scopedChild2 = new TestFocusScope(scope); + + QCOMPARE(root->hasFocus(), false); + QCOMPARE(child->hasFocus(), false); + QCOMPARE(scope->hasFocus(), false); + QCOMPARE(scopedChild->hasFocus(), false); + QCOMPARE(scopedChild2->hasFocus(), false); + + root->setFocus(true); + scope->setFocus(true); + scopedChild2->setFocus(true); + QCOMPARE(root->hasFocus(), true); + QCOMPARE(child->hasFocus(), false); + QCOMPARE(scope->hasFocus(), true); + QCOMPARE(scopedChild->hasFocus(), false); + QCOMPARE(scopedChild2->hasFocus(), true); + + root->setFocus(false); + child->setFocus(true); + scopedChild->setFocus(true); + scope->setFocus(false); + QCOMPARE(root->hasFocus(), false); + QCOMPARE(child->hasFocus(), true); + QCOMPARE(scope->hasFocus(), false); + QCOMPARE(scopedChild->hasFocus(), true); + QCOMPARE(scopedChild2->hasFocus(), true); + + delete root; +} + +struct FocusData { + FocusData() : focus(false), activeFocus(false) {} + + void set(bool f, bool af) { focus = f; activeFocus = af; } + bool focus; + bool activeFocus; +}; +struct FocusState : public QHash<QQuickItem *, FocusData> +{ + FocusState() : activeFocusItem(0) {} + FocusState &operator<<(QQuickItem *item) { + insert(item, FocusData()); + return *this; + } + + void active(QQuickItem *i) { + activeFocusItem = i; + } + QQuickItem *activeFocusItem; +}; + +#define FVERIFY() \ + do { \ + if (focusState.activeFocusItem) { \ + QCOMPARE(canvas.activeFocusItem(), focusState.activeFocusItem); \ + if (qobject_cast<TestItem *>(canvas.activeFocusItem())) \ + QCOMPARE(qobject_cast<TestItem *>(canvas.activeFocusItem())->focused, true); \ + else if (qobject_cast<TestFocusScope *>(canvas.activeFocusItem())) \ + QCOMPARE(qobject_cast<TestFocusScope *>(canvas.activeFocusItem())->focused, true); \ + } else { \ + QCOMPARE(canvas.activeFocusItem(), canvas.rootItem()); \ + } \ + for (QHash<QQuickItem *, FocusData>::Iterator iter = focusState.begin(); \ + iter != focusState.end(); \ + iter++) { \ + QCOMPARE(iter.key()->hasFocus(), iter.value().focus); \ + QCOMPARE(iter.key()->hasActiveFocus(), iter.value().activeFocus); \ + } \ + } while (false) + +// Tests a simple set of top-level scoped items +void tst_qquickitem::simpleFocus() +{ + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + + QQuickItem *l1c1 = new TestItem(canvas.rootItem()); + QQuickItem *l1c2 = new TestItem(canvas.rootItem()); + QQuickItem *l1c3 = new TestItem(canvas.rootItem()); + + QQuickItem *l2c1 = new TestItem(l1c1); + QQuickItem *l2c2 = new TestItem(l1c1); + QQuickItem *l2c3 = new TestItem(l1c3); + + FocusState focusState; + focusState << l1c1 << l1c2 << l1c3 + << l2c1 << l2c2 << l2c3; + FVERIFY(); + + l1c1->setFocus(true); + focusState[l1c1].set(true, true); + focusState.active(l1c1); + FVERIFY(); + + l2c3->setFocus(true); + focusState[l1c1].set(false, false); + focusState[l2c3].set(true, true); + focusState.active(l2c3); + FVERIFY(); + + l1c3->setFocus(true); + focusState[l2c3].set(false, false); + focusState[l1c3].set(true, true); + focusState.active(l1c3); + FVERIFY(); + + l1c2->setFocus(false); + FVERIFY(); + + l1c3->setFocus(false); + focusState[l1c3].set(false, false); + focusState.active(0); + FVERIFY(); + + l2c1->setFocus(true); + focusState[l2c1].set(true, true); + focusState.active(l2c1); + FVERIFY(); +} + +// Items with a focus scope +void tst_qquickitem::scopedFocus() +{ + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + + QQuickItem *l1c1 = new TestItem(canvas.rootItem()); + QQuickItem *l1c2 = new TestItem(canvas.rootItem()); + QQuickItem *l1c3 = new TestItem(canvas.rootItem()); + + QQuickItem *l2c1 = new TestItem(l1c1); + QQuickItem *l2c2 = new TestItem(l1c1); + QQuickItem *l2c3 = new TestFocusScope(l1c3); + + QQuickItem *l3c1 = new TestItem(l2c3); + QQuickItem *l3c2 = new TestFocusScope(l2c3); + + QQuickItem *l4c1 = new TestItem(l3c2); + QQuickItem *l4c2 = new TestItem(l3c2); + + FocusState focusState; + focusState << l1c1 << l1c2 << l1c3 + << l2c1 << l2c2 << l2c3 + << l3c1 << l3c2 + << l4c1 << l4c2; + FVERIFY(); + + l4c2->setFocus(true); + focusState[l4c2].set(true, false); + FVERIFY(); + + l4c1->setFocus(true); + focusState[l4c2].set(false, false); + focusState[l4c1].set(true, false); + FVERIFY(); + + l1c1->setFocus(true); + focusState[l1c1].set(true, true); + focusState.active(l1c1); + FVERIFY(); + + l3c2->setFocus(true); + focusState[l3c2].set(true, false); + FVERIFY(); + + l2c3->setFocus(true); + focusState[l1c1].set(false, false); + focusState[l2c3].set(true, true); + focusState[l3c2].set(true, true); + focusState[l4c1].set(true, true); + focusState.active(l4c1); + FVERIFY(); + + l3c2->setFocus(false); + focusState[l3c2].set(false, false); + focusState[l4c1].set(true, false); + focusState.active(l2c3); + FVERIFY(); + + l3c2->setFocus(true); + focusState[l3c2].set(true, true); + focusState[l4c1].set(true, true); + focusState.active(l4c1); + FVERIFY(); + + l4c1->setFocus(false); + focusState[l4c1].set(false, false); + focusState.active(l3c2); + FVERIFY(); + + l1c3->setFocus(true); + focusState[l1c3].set(true, true); + focusState[l2c3].set(false, false); + focusState[l3c2].set(true, false); + focusState.active(l1c3); + FVERIFY(); +} + +// Tests focus corrects itself when a tree is added to a canvas for the first time +void tst_qquickitem::addedToCanvas() +{ + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + + QQuickItem *item = new TestItem; + + FocusState focusState; + focusState << item; + + item->setFocus(true); + focusState[item].set(true, false); + FVERIFY(); + + item->setParentItem(canvas.rootItem()); + focusState[item].set(true, true); + focusState.active(item); + FVERIFY(); + } + + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + + QQuickItem *item = new TestItem(canvas.rootItem()); + + QQuickItem *tree = new TestItem; + QQuickItem *c1 = new TestItem(tree); + QQuickItem *c2 = new TestItem(tree); + + FocusState focusState; + focusState << item << tree << c1 << c2; + + item->setFocus(true); + c1->setFocus(true); + c2->setFocus(true); + focusState[item].set(true, true); + focusState[c1].set(true, false); + focusState[c2].set(true, false); + focusState.active(item); + FVERIFY(); + + tree->setParentItem(item); + focusState[c1].set(false, false); + focusState[c2].set(false, false); + FVERIFY(); + } + + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + + QQuickItem *tree = new TestItem; + QQuickItem *c1 = new TestItem(tree); + QQuickItem *c2 = new TestItem(tree); + + FocusState focusState; + focusState << tree << c1 << c2; + c1->setFocus(true); + c2->setFocus(true); + focusState[c1].set(true, false); + focusState[c2].set(true, false); + FVERIFY(); + + tree->setParentItem(canvas.rootItem()); + focusState[c1].set(true, true); + focusState[c2].set(false, false); + focusState.active(c1); + FVERIFY(); + } + + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + QQuickItem *tree = new TestFocusScope; + QQuickItem *c1 = new TestItem(tree); + QQuickItem *c2 = new TestItem(tree); + + FocusState focusState; + focusState << tree << c1 << c2; + c1->setFocus(true); + c2->setFocus(true); + focusState[c1].set(true, false); + focusState[c2].set(true, false); + FVERIFY(); + + tree->setParentItem(canvas.rootItem()); + focusState[c1].set(true, false); + focusState[c2].set(false, false); + FVERIFY(); + + tree->setFocus(true); + focusState[tree].set(true, true); + focusState[c1].set(true, true); + focusState.active(c1); + FVERIFY(); + } + + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + QQuickItem *tree = new TestFocusScope; + QQuickItem *c1 = new TestItem(tree); + QQuickItem *c2 = new TestItem(tree); + + FocusState focusState; + focusState << tree << c1 << c2; + tree->setFocus(true); + c1->setFocus(true); + c2->setFocus(true); + focusState[tree].set(true, false); + focusState[c1].set(true, false); + focusState[c2].set(true, false); + FVERIFY(); + + tree->setParentItem(canvas.rootItem()); + focusState[tree].set(true, true); + focusState[c1].set(true, true); + focusState[c2].set(false, false); + focusState.active(c1); + FVERIFY(); + } + + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + QQuickItem *child = new TestItem(canvas.rootItem()); + QQuickItem *tree = new TestFocusScope; + QQuickItem *c1 = new TestItem(tree); + QQuickItem *c2 = new TestItem(tree); + + FocusState focusState; + focusState << child << tree << c1 << c2; + child->setFocus(true); + tree->setFocus(true); + c1->setFocus(true); + c2->setFocus(true); + focusState[child].set(true, true); + focusState[tree].set(true, false); + focusState[c1].set(true, false); + focusState[c2].set(true, false); + focusState.active(child); + FVERIFY(); + + tree->setParentItem(canvas.rootItem()); + focusState[tree].set(false, false); + focusState[c1].set(true, false); + focusState[c2].set(false, false); + FVERIFY(); + + tree->setFocus(true); + focusState[child].set(false, false); + focusState[tree].set(true, true); + focusState[c1].set(true, true); + focusState.active(c1); + FVERIFY(); + } +} + +void tst_qquickitem::changeParent() +{ + // Parent to no parent + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + QQuickItem *child = new TestItem(canvas.rootItem()); + + FocusState focusState; + focusState << child; + FVERIFY(); + + child->setFocus(true); + focusState[child].set(true, true); + focusState.active(child); + FVERIFY(); + + child->setParentItem(0); + focusState[child].set(true, false); + focusState.active(0); + FVERIFY(); + } + + // Different parent, same focus scope + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + QQuickItem *child = new TestItem(canvas.rootItem()); + QQuickItem *child2 = new TestItem(canvas.rootItem()); + + FocusState focusState; + focusState << child << child2; + FVERIFY(); + + child->setFocus(true); + focusState[child].set(true, true); + focusState.active(child); + FVERIFY(); + + child->setParentItem(child2); + FVERIFY(); + } + + // Different parent, different focus scope + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + QQuickItem *child = new TestItem(canvas.rootItem()); + QQuickItem *child2 = new TestFocusScope(canvas.rootItem()); + QQuickItem *item = new TestItem(child); + + FocusState focusState; + focusState << child << child2 << item; + FVERIFY(); + + item->setFocus(true); + focusState[item].set(true, true); + focusState.active(item); + FVERIFY(); + + item->setParentItem(child2); + focusState[item].set(true, false); + focusState.active(0); + FVERIFY(); + } + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + QQuickItem *child = new TestItem(canvas.rootItem()); + QQuickItem *child2 = new TestFocusScope(canvas.rootItem()); + QQuickItem *item = new TestItem(child2); + + FocusState focusState; + focusState << child << child2 << item; + FVERIFY(); + + item->setFocus(true); + focusState[item].set(true, false); + focusState.active(0); + FVERIFY(); + + item->setParentItem(child); + focusState[item].set(true, true); + focusState.active(item); + FVERIFY(); + } + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + QQuickItem *child = new TestItem(canvas.rootItem()); + QQuickItem *child2 = new TestFocusScope(canvas.rootItem()); + QQuickItem *item = new TestItem(child2); + + FocusState focusState; + focusState << child << child2 << item; + FVERIFY(); + + child->setFocus(true); + item->setFocus(true); + focusState[child].set(true, true); + focusState[item].set(true, false); + focusState.active(child); + FVERIFY(); + + item->setParentItem(child); + focusState[item].set(false, false); + FVERIFY(); + } + +} + +void tst_qquickitem::constructor() +{ + QQuickItem *root = new QQuickItem; + QVERIFY(root->parent() == 0); + QVERIFY(root->parentItem() == 0); + + QQuickItem *child1 = new QQuickItem(root); + QVERIFY(child1->parent() == root); + QVERIFY(child1->parentItem() == root); + QCOMPARE(root->childItems().count(), 1); + QCOMPARE(root->childItems().at(0), child1); + + QQuickItem *child2 = new QQuickItem(root); + QVERIFY(child2->parent() == root); + QVERIFY(child2->parentItem() == root); + QCOMPARE(root->childItems().count(), 2); + QCOMPARE(root->childItems().at(0), child1); + QCOMPARE(root->childItems().at(1), child2); + + delete root; +} + +void tst_qquickitem::setParentItem() +{ + QQuickItem *root = new QQuickItem; + QVERIFY(root->parent() == 0); + QVERIFY(root->parentItem() == 0); + + QQuickItem *child1 = new QQuickItem; + QVERIFY(child1->parent() == 0); + QVERIFY(child1->parentItem() == 0); + + child1->setParentItem(root); + QVERIFY(child1->parent() == 0); + QVERIFY(child1->parentItem() == root); + QCOMPARE(root->childItems().count(), 1); + QCOMPARE(root->childItems().at(0), child1); + + QQuickItem *child2 = new QQuickItem; + QVERIFY(child2->parent() == 0); + QVERIFY(child2->parentItem() == 0); + child2->setParentItem(root); + QVERIFY(child2->parent() == 0); + QVERIFY(child2->parentItem() == root); + QCOMPARE(root->childItems().count(), 2); + QCOMPARE(root->childItems().at(0), child1); + QCOMPARE(root->childItems().at(1), child2); + + child1->setParentItem(0); + QVERIFY(child1->parent() == 0); + QVERIFY(child1->parentItem() == 0); + QCOMPARE(root->childItems().count(), 1); + QCOMPARE(root->childItems().at(0), child2); + + delete root; + + QVERIFY(child1->parent() == 0); + QVERIFY(child1->parentItem() == 0); + QVERIFY(child2->parent() == 0); + QVERIFY(child2->parentItem() == 0); + + delete child1; + delete child2; +} + +void tst_qquickitem::visible() +{ + QQuickItem *root = new QQuickItem; + + QQuickItem *child1 = new QQuickItem; + child1->setParentItem(root); + + QQuickItem *child2 = new QQuickItem; + child2->setParentItem(root); + + QVERIFY(child1->isVisible()); + QVERIFY(child2->isVisible()); + + root->setVisible(false); + QVERIFY(!child1->isVisible()); + QVERIFY(!child2->isVisible()); + + root->setVisible(true); + QVERIFY(child1->isVisible()); + QVERIFY(child2->isVisible()); + + child1->setVisible(false); + QVERIFY(!child1->isVisible()); + QVERIFY(child2->isVisible()); + + child2->setParentItem(child1); + QVERIFY(!child1->isVisible()); + QVERIFY(!child2->isVisible()); + + child2->setParentItem(root); + QVERIFY(!child1->isVisible()); + QVERIFY(child2->isVisible()); + + delete root; + delete child1; + delete child2; +} + +void tst_qquickitem::enabled() +{ + QQuickItem *root = new QQuickItem; + + QQuickItem *child1 = new QQuickItem; + child1->setParentItem(root); + + QQuickItem *child2 = new QQuickItem; + child2->setParentItem(root); + + QVERIFY(child1->isEnabled()); + QVERIFY(child2->isEnabled()); + + root->setEnabled(false); + QVERIFY(!child1->isEnabled()); + QVERIFY(!child2->isEnabled()); + + root->setEnabled(true); + QVERIFY(child1->isEnabled()); + QVERIFY(child2->isEnabled()); + + child1->setEnabled(false); + QVERIFY(!child1->isEnabled()); + QVERIFY(child2->isEnabled()); + + child2->setParentItem(child1); + QVERIFY(!child1->isEnabled()); + QVERIFY(!child2->isEnabled()); + + child2->setParentItem(root); + QVERIFY(!child1->isEnabled()); + QVERIFY(child2->isEnabled()); + + delete root; + delete child1; + delete child2; +} + +void tst_qquickitem::mouseGrab() +{ + QQuickCanvas *canvas = new QQuickCanvas; + canvas->resize(200, 200); + canvas->show(); + + TestItem *child1 = new TestItem; + child1->setAcceptedMouseButtons(Qt::LeftButton); + child1->setSize(QSizeF(200, 100)); + child1->setParentItem(canvas->rootItem()); + + TestItem *child2 = new TestItem; + child2->setAcceptedMouseButtons(Qt::LeftButton); + child2->setY(51); + child2->setSize(QSizeF(200, 100)); + child2->setParentItem(canvas->rootItem()); + + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50)); + QTest::qWait(100); + QVERIFY(canvas->mouseGrabberItem() == child1); + QTest::qWait(100); + + QCOMPARE(child1->pressCount, 1); + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50)); + QTest::qWait(50); + QVERIFY(canvas->mouseGrabberItem() == 0); + QCOMPARE(child1->releaseCount, 1); + + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50)); + QTest::qWait(50); + QVERIFY(canvas->mouseGrabberItem() == child1); + QCOMPARE(child1->pressCount, 2); + child1->setEnabled(false); + QVERIFY(canvas->mouseGrabberItem() == 0); + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50)); + QTest::qWait(50); + QCOMPARE(child1->releaseCount, 1); + child1->setEnabled(true); + + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50)); + QTest::qWait(50); + QVERIFY(canvas->mouseGrabberItem() == child1); + QCOMPARE(child1->pressCount, 3); + child1->setVisible(false); + QVERIFY(canvas->mouseGrabberItem() == 0); + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50)); + QCOMPARE(child1->releaseCount, 1); + child1->setVisible(true); + + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50)); + QTest::qWait(50); + QVERIFY(canvas->mouseGrabberItem() == child1); + QCOMPARE(child1->pressCount, 4); + child2->grabMouse(); + QVERIFY(canvas->mouseGrabberItem() == child2); + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50)); + QTest::qWait(50); + QCOMPARE(child1->releaseCount, 1); + QCOMPARE(child2->releaseCount, 1); + + child2->grabMouse(); + QVERIFY(canvas->mouseGrabberItem() == child2); + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50)); + QTest::qWait(50); + QCOMPARE(child1->pressCount, 4); + QCOMPARE(child2->pressCount, 1); + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50)); + QTest::qWait(50); + QCOMPARE(child1->releaseCount, 1); + QCOMPARE(child2->releaseCount, 2); + + delete child1; + delete child2; + delete canvas; +} + +void tst_qquickitem::polishOutsideAnimation() +{ + QQuickCanvas *canvas = new QQuickCanvas; + canvas->resize(200, 200); + canvas->show(); + + TestPolishItem *item = new TestPolishItem(canvas->rootItem()); + item->setSize(QSizeF(200, 100)); + QTest::qWait(50); + QTRY_VERIFY(item->wasPolished); + + delete item; + delete canvas; +} + +void tst_qquickitem::wheelEvent_data() +{ + QTest::addColumn<bool>("visible"); + QTest::addColumn<bool>("enabled"); + + QTest::newRow("visible and enabled") << true << true; + QTest::newRow("visible and disabled") << true << false; + QTest::newRow("invisible and enabled") << false << true; + QTest::newRow("invisible and disabled") << false << false; +} + +void tst_qquickitem::wheelEvent() +{ + QFETCH(bool, visible); + QFETCH(bool, enabled); + + const bool shouldReceiveWheelEvents = visible && enabled; + + QQuickCanvas *canvas = new QQuickCanvas; + canvas->resize(200, 200); + canvas->show(); + + TestItem *item = new TestItem; + item->setSize(QSizeF(200, 100)); + item->setParentItem(canvas->rootItem()); + + item->setEnabled(enabled); + item->setVisible(visible); + + QWheelEvent event(QPoint(100, 50), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical); + event.setAccepted(false); + QApplication::sendEvent(canvas, &event); + + if (shouldReceiveWheelEvents) { + QVERIFY(event.isAccepted()); + QCOMPARE(item->wheelCount, 1); + } else { + QVERIFY(!event.isAccepted()); + QCOMPARE(item->wheelCount, 0); + } + + delete canvas; +} + +class HoverItem : public QQuickItem +{ +Q_OBJECT +public: + HoverItem(QQuickItem *parent = 0) + : QQuickItem(parent), hoverEnterCount(0), hoverMoveCount(0), hoverLeaveCount(0) + { } + void resetCounters() { + hoverEnterCount = 0; + hoverMoveCount = 0; + hoverLeaveCount = 0; + } + int hoverEnterCount; + int hoverMoveCount; + int hoverLeaveCount; +protected: + virtual void hoverEnterEvent(QHoverEvent *event) { + event->accept(); + ++hoverEnterCount; + } + virtual void hoverMoveEvent(QHoverEvent *event) { + event->accept(); + ++hoverMoveCount; + } + virtual void hoverLeaveEvent(QHoverEvent *event) { + event->accept(); + ++hoverLeaveCount; + } +}; + +void tst_qquickitem::hoverEvent_data() +{ + QTest::addColumn<bool>("visible"); + QTest::addColumn<bool>("enabled"); + QTest::addColumn<bool>("acceptHoverEvents"); + + QTest::newRow("visible, enabled, accept hover") << true << true << true; + QTest::newRow("visible, disabled, accept hover") << true << false << true; + QTest::newRow("invisible, enabled, accept hover") << false << true << true; + QTest::newRow("invisible, disabled, accept hover") << false << false << true; + + QTest::newRow("visible, enabled, not accept hover") << true << true << false; + QTest::newRow("visible, disabled, not accept hover") << true << false << false; + QTest::newRow("invisible, enabled, not accept hover") << false << true << false; + QTest::newRow("invisible, disabled, not accept hover") << false << false << false; +} + +// ### For some unknown reason QTest::mouseMove() isn't working correctly. +static void sendMouseMove(QObject *object, const QPoint &position) +{ + QMouseEvent moveEvent(QEvent::MouseMove, position, Qt::NoButton, Qt::NoButton, 0); + QApplication::sendEvent(object, &moveEvent); +} + +void tst_qquickitem::hoverEvent() +{ + QFETCH(bool, visible); + QFETCH(bool, enabled); + QFETCH(bool, acceptHoverEvents); + + QQuickCanvas *canvas = new QQuickCanvas(); + canvas->resize(200, 200); + canvas->show(); + + HoverItem *item = new HoverItem; + item->setSize(QSizeF(100, 100)); + item->setParentItem(canvas->rootItem()); + + item->setEnabled(enabled); + item->setVisible(visible); + item->setAcceptHoverEvents(acceptHoverEvents); + + const QPoint outside(150, 150); + const QPoint inside(50, 50); + const QPoint anotherInside(51, 51); + + sendMouseMove(canvas, outside); + item->resetCounters(); + + // Enter, then move twice inside, then leave. + sendMouseMove(canvas, inside); + sendMouseMove(canvas, anotherInside); + sendMouseMove(canvas, inside); + sendMouseMove(canvas, outside); + + const bool shouldReceiveHoverEvents = visible && enabled && acceptHoverEvents; + if (shouldReceiveHoverEvents) { + QCOMPARE(item->hoverEnterCount, 1); + QCOMPARE(item->hoverMoveCount, 2); + QCOMPARE(item->hoverLeaveCount, 1); + } else { + QCOMPARE(item->hoverEnterCount, 0); + QCOMPARE(item->hoverMoveCount, 0); + QCOMPARE(item->hoverLeaveCount, 0); + } + + delete canvas; +} + +void tst_qquickitem::hoverEventInParent() +{ + QQuickCanvas *canvas = new QQuickCanvas(); + canvas->resize(200, 200); + canvas->show(); + + HoverItem *parentItem = new HoverItem(canvas->rootItem()); + parentItem->setSize(QSizeF(200, 200)); + parentItem->setAcceptHoverEvents(true); + + HoverItem *leftItem = new HoverItem(parentItem); + leftItem->setSize(QSizeF(100, 200)); + leftItem->setAcceptHoverEvents(true); + + HoverItem *rightItem = new HoverItem(parentItem); + rightItem->setSize(QSizeF(100, 200)); + rightItem->setPos(QPointF(100, 0)); + rightItem->setAcceptHoverEvents(true); + + const QPoint insideLeft(50, 100); + const QPoint insideRight(150, 100); + + sendMouseMove(canvas, insideLeft); + parentItem->resetCounters(); + leftItem->resetCounters(); + rightItem->resetCounters(); + + sendMouseMove(canvas, insideRight); + QCOMPARE(parentItem->hoverEnterCount, 0); + QCOMPARE(parentItem->hoverLeaveCount, 0); + QCOMPARE(leftItem->hoverEnterCount, 0); + QCOMPARE(leftItem->hoverLeaveCount, 1); + QCOMPARE(rightItem->hoverEnterCount, 1); + QCOMPARE(rightItem->hoverLeaveCount, 0); + + sendMouseMove(canvas, insideLeft); + QCOMPARE(parentItem->hoverEnterCount, 0); + QCOMPARE(parentItem->hoverLeaveCount, 0); + QCOMPARE(leftItem->hoverEnterCount, 1); + QCOMPARE(leftItem->hoverLeaveCount, 1); + QCOMPARE(rightItem->hoverEnterCount, 1); + QCOMPARE(rightItem->hoverLeaveCount, 1); + + delete canvas; +} + +void tst_qquickitem::paintOrder_data() +{ + QTest::addColumn<QUrl>("source"); + QTest::addColumn<int>("op"); + QTest::addColumn<QVariant>("param1"); + QTest::addColumn<QVariant>("param2"); + QTest::addColumn<QStringList>("expected"); + + QTest::newRow("test 1 noop") << QUrl::fromLocalFile(TESTDATA("order.1.qml")) + << int(NoOp) << QVariant() << QVariant() + << (QStringList() << "1" << "2" << "3"); + QTest::newRow("test 1 add") << QUrl::fromLocalFile(TESTDATA("order.1.qml")) + << int(Append) << QVariant("new") << QVariant() + << (QStringList() << "1" << "2" << "3" << "new"); + QTest::newRow("test 1 remove") << QUrl::fromLocalFile(TESTDATA("order.1.qml")) + << int(Remove) << QVariant(1) << QVariant() + << (QStringList() << "1" << "3"); + QTest::newRow("test 1 stack before") << QUrl::fromLocalFile(TESTDATA("order.1.qml")) + << int(StackBefore) << QVariant(2) << QVariant(1) + << (QStringList() << "1" << "3" << "2"); + QTest::newRow("test 1 stack after") << QUrl::fromLocalFile(TESTDATA("order.1.qml")) + << int(StackAfter) << QVariant(0) << QVariant(1) + << (QStringList() << "2" << "1" << "3"); + QTest::newRow("test 1 set z") << QUrl::fromLocalFile(TESTDATA("order.1.qml")) + << int(SetZ) << QVariant(1) << QVariant(qreal(1.)) + << (QStringList() << "1" << "3" << "2"); + + QTest::newRow("test 2 noop") << QUrl::fromLocalFile(TESTDATA("order.2.qml")) + << int(NoOp) << QVariant() << QVariant() + << (QStringList() << "1" << "3" << "2"); + QTest::newRow("test 2 add") << QUrl::fromLocalFile(TESTDATA("order.2.qml")) + << int(Append) << QVariant("new") << QVariant() + << (QStringList() << "1" << "3" << "new" << "2"); + QTest::newRow("test 2 remove 1") << QUrl::fromLocalFile(TESTDATA("order.2.qml")) + << int(Remove) << QVariant(1) << QVariant() + << (QStringList() << "1" << "3"); + QTest::newRow("test 2 remove 2") << QUrl::fromLocalFile(TESTDATA("order.2.qml")) + << int(Remove) << QVariant(2) << QVariant() + << (QStringList() << "1" << "2"); + QTest::newRow("test 2 stack before 1") << QUrl::fromLocalFile(TESTDATA("order.2.qml")) + << int(StackBefore) << QVariant(1) << QVariant(0) + << (QStringList() << "1" << "3" << "2"); + QTest::newRow("test 2 stack before 2") << QUrl::fromLocalFile(TESTDATA("order.2.qml")) + << int(StackBefore) << QVariant(2) << QVariant(0) + << (QStringList() << "3" << "1" << "2"); + QTest::newRow("test 2 stack after 1") << QUrl::fromLocalFile(TESTDATA("order.2.qml")) + << int(StackAfter) << QVariant(0) << QVariant(1) + << (QStringList() << "1" << "3" << "2"); + QTest::newRow("test 2 stack after 2") << QUrl::fromLocalFile(TESTDATA("order.2.qml")) + << int(StackAfter) << QVariant(0) << QVariant(2) + << (QStringList() << "3" << "1" << "2"); + QTest::newRow("test 1 set z") << QUrl::fromLocalFile(TESTDATA("order.1.qml")) + << int(SetZ) << QVariant(2) << QVariant(qreal(2.)) + << (QStringList() << "1" << "2" << "3"); +} + +void tst_qquickitem::paintOrder() +{ + QFETCH(QUrl, source); + QFETCH(int, op); + QFETCH(QVariant, param1); + QFETCH(QVariant, param2); + QFETCH(QStringList, expected); + + QQuickView view; + view.setSource(source); + + QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject()); + QVERIFY(root); + + switch (op) { + case Append: { + QQuickItem *item = new QQuickItem(root); + item->setObjectName(param1.toString()); + } + break; + case Remove: { + QQuickItem *item = root->childItems().at(param1.toInt()); + delete item; + } + break; + case StackBefore: { + QQuickItem *item1 = root->childItems().at(param1.toInt()); + QQuickItem *item2 = root->childItems().at(param2.toInt()); + item1->stackBefore(item2); + } + break; + case StackAfter: { + QQuickItem *item1 = root->childItems().at(param1.toInt()); + QQuickItem *item2 = root->childItems().at(param2.toInt()); + item1->stackAfter(item2); + } + break; + case SetZ: { + QQuickItem *item = root->childItems().at(param1.toInt()); + item->setZ(param2.toReal()); + } + break; + default: + break; + } + + QList<QQuickItem*> list = QQuickItemPrivate::get(root)->paintOrderChildItems(); + + QStringList items; + for (int i = 0; i < list.count(); ++i) + items << list.at(i)->objectName(); + + QCOMPARE(items, expected); +} + + +QTEST_MAIN(tst_qquickitem) + +#include "tst_qquickitem.moc" |