diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-12-18 19:17:30 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-12-18 19:17:30 +0100 |
commit | 9f38956fc9a58a2fdfd83c91d65502964047eda3 (patch) | |
tree | 3156fa78c621e3588b230d8334944d4c9e857d45 /tests/auto/quick | |
parent | 57cd6337a87f4a8a77ea7136c60a32d2825426df (diff) | |
parent | 839d2d3e2368bc8e107d22203b0611c852f54319 (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts:
tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
Change-Id: I9588a3e2c7d590e031dd4c66905a79f0d74d3ac8
Diffstat (limited to 'tests/auto/quick')
8 files changed, 415 insertions, 6 deletions
diff --git a/tests/auto/quick/qquickanimations/data/animatorInvalidTargetCrash.qml b/tests/auto/quick/qquickanimations/data/animatorInvalidTargetCrash.qml new file mode 100644 index 0000000000..f2c378e4b5 --- /dev/null +++ b/tests/auto/quick/qquickanimations/data/animatorInvalidTargetCrash.qml @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.3 +import QtQuick.Window 2.2 + +Window { + visible: true + width: 100 + height: 100 + + OpacityAnimator { + id: anim + from: 1 + to:0 + duration: 5000 + running: false + } + + Loader { + id: loader + sourceComponent: Text { + text: "Hello World" + anchors.centerIn: parent + } + } + + Component.onCompleted: { + anim.target = loader.item; + anim.start(); + loader.active = false; + } +} diff --git a/tests/auto/quick/qquickanimations/data/defaultRotationAnimation.qml b/tests/auto/quick/qquickanimations/data/defaultRotationAnimation.qml new file mode 100644 index 0000000000..94692add60 --- /dev/null +++ b/tests/auto/quick/qquickanimations/data/defaultRotationAnimation.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 + +Rectangle { + id: rect + + RotationAnimation { + target: rect + from: 0 + to: 360 + running: true + duration: 1000 + loops: Animation.Infinite + } +} diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp index 2b805e9eeb..5cad68b275 100644 --- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp +++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp @@ -104,6 +104,8 @@ private slots: void scriptActionBug(); void groupAnimationNullChildBug(); void scriptActionCrash(); + void animatorInvalidTargetCrash(); + void defaultPropertyWarning(); }; #define QTIMED_COMPARE(lhs, rhs) do { \ @@ -1491,7 +1493,40 @@ void tst_qquickanimations::scriptActionCrash() delete obj; } +// QTBUG-49364 +// Test that we don't crash when the target of an Animator becomes +// invalid between the time the animator is started and the time the +// animator job is actually started +void tst_qquickanimations::animatorInvalidTargetCrash() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("animatorInvalidTargetCrash.qml")); + QObject *obj = c.create(); + + //just testing that we don't crash + QTest::qWait(5000); //animator duration + + delete obj; +} + +Q_DECLARE_METATYPE(QList<QQmlError>) +// QTBUG-22141 +void tst_qquickanimations::defaultPropertyWarning() +{ + QQmlEngine engine; + + qRegisterMetaType<QList<QQmlError> >(); + + QSignalSpy warnings(&engine, SIGNAL(warnings(QList<QQmlError>))); + QVERIFY(warnings.isValid()); + + QQmlComponent component(&engine, testFileUrl("defaultRotationAnimation.qml")); + QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(component.create())); + QVERIFY(root); + + QVERIFY(warnings.isEmpty()); +} QTEST_MAIN(tst_qquickanimations) diff --git a/tests/auto/quick/qquicklistview/data/qtbug48870.qml b/tests/auto/quick/qquicklistview/data/qtbug48870.qml new file mode 100644 index 0000000000..217f58af48 --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/qtbug48870.qml @@ -0,0 +1,24 @@ +import QtQuick 2.6 + +Rectangle { + width: 500 + height: 500 + color: "blue" + + ListView { + objectName: "list" + anchors.fill: parent + model: testModel + + delegate: Rectangle { + height: 50 + width: ListView.view ? ListView.view.width : height + color: "green" + + Text { + anchors.centerIn: parent + text: "Item " + index + } + } + } +} diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index ad6c6ec12d..86add7435c 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -40,6 +40,7 @@ #include <QtQml/qqmlcontext.h> #include <QtQml/qqmlexpression.h> #include <QtQml/qqmlincubator.h> +#include <QtQuick/private/qquickitemview_p_p.h> #include <QtQuick/private/qquicklistview_p.h> #include <QtQuick/private/qquicktext_p.h> #include <QtQml/private/qqmlobjectmodel_p.h> @@ -249,6 +250,7 @@ private slots: void contentHeightWithDelayRemove_data(); void QTBUG_48044_currentItemNotVisibleAfterTransition(); + void QTBUG_48870_fastModelUpdates(); void keyNavigationEnabled(); @@ -592,8 +594,7 @@ void tst_QQuickListView::inserted(const QUrl &source) QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0); QVERIFY(item); - QCOMPARE(item->y(), 0.); - QTRY_COMPARE(listview->contentY(), qreal(0)); + QTRY_COMPARE(item->y() - listview->contentY(), 0.); delete window; delete testObject; @@ -644,7 +645,8 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v QTRY_COMPARE(listview->property("count").toInt(), model.count()); - + // FIXME This is NOT checking anything about visibleItems.first() +#if 0 // check visibleItems.first() is in correct position QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0); QVERIFY(item0); @@ -652,6 +654,7 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v QCOMPARE(item0->y(), -item0->height() - itemsOffsetAfterMove); else QCOMPARE(item0->y(), itemsOffsetAfterMove); +#endif QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper"); int firstVisibleIndex = -1; @@ -667,12 +670,21 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v // Confirm items positioned correctly and indexes correct QQuickText *name; QQuickText *number; + const qreal visibleFromPos = listview->contentY() - listview->displayMarginBeginning() - listview->cacheBuffer(); + const qreal visibleToPos = listview->contentY() + listview->height() + listview->displayMarginEnd() + listview->cacheBuffer(); for (int i = firstVisibleIndex; i < model.count() && i < items.count(); ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); qreal pos = i*20.0 + itemsOffsetAfterMove; if (verticalLayoutDirection == QQuickItemView::BottomToTop) - pos = -item0->height() - pos; + pos = -item->height() - pos; + // Items outside the visible area (including cache buffer) should be skipped + if (pos > visibleToPos || pos < visibleFromPos) { + QTRY_VERIFY2(QQuickItemPrivate::get(item)->culled || item->y() < visibleFromPos || item->y() > visibleToPos, + QTest::toString(QString("index %5, y %1, from %2, to %3, expected pos %4, culled %6"). + arg(item->y()).arg(visibleFromPos).arg(visibleToPos).arg(pos).arg(i).arg(bool(QQuickItemPrivate::get(item)->culled)))); + continue; + } QTRY_COMPARE(item->y(), pos); name = findItem<QQuickText>(contentItem, "textName", i); QVERIFY(name != 0); @@ -8363,6 +8375,136 @@ void tst_QQuickListView::keyNavigationEnabled() QCOMPARE(listView->currentIndex(), 1); } +static bool testVisibleItems(const QQuickItemViewPrivate *priv, bool *nonUnique, FxViewItem **failItem, int *expectedIdx) +{ + QHash<QQuickItem*, int> uniqueItems; + + int skip = 0; + for (int i = 0; i < priv->visibleItems.count(); ++i) { + FxViewItem *item = priv->visibleItems.at(i); + if (!item) { + *failItem = Q_NULLPTR; + return false; + } +#if 0 + qDebug() << "\t" << item->index + << item->item + << item->position() + << (!item->item || QQuickItemPrivate::get(item->item)->culled ? "hidden" : "visible"); +#endif + if (item->index == -1) { + ++skip; + } else if (item->index != priv->visibleIndex + i - skip) { + *nonUnique = false; + *failItem = item; + *expectedIdx = priv->visibleIndex + i - skip; + return false; + } else if (uniqueItems.contains(item->item)) { + *nonUnique = true; + *failItem = item; + *expectedIdx = uniqueItems.find(item->item).value(); + return false; + } + + uniqueItems.insert(item->item, item->index); + } + + return true; +} + +class QTBUG_48870_Model : public QAbstractListModel +{ + Q_OBJECT + +public: + + QTBUG_48870_Model() + : QAbstractListModel() + , m_rowCount(20) + { + QTimer *t = new QTimer(this); + t->setInterval(500); + t->start(); + + qsrand(qHash(QDateTime::currentDateTime())); + connect(t, &QTimer::timeout, this, &QTBUG_48870_Model::updateModel); + } + + int rowCount(const QModelIndex &) const + { + return m_rowCount; + } + + QVariant data(const QModelIndex &, int) const + { + return QVariant(); + } + +public Q_SLOTS: + void updateModel() + { + if (m_rowCount > 10) { + for (int i = 0; i < 10; ++i) { + int rnum = qrand() % m_rowCount; + beginRemoveRows(QModelIndex(), rnum, rnum); + m_rowCount--; + endRemoveRows(); + } + } + if (m_rowCount < 20) { + for (int i = 0; i < 10; ++i) { + int rnum = qrand() % m_rowCount; + beginInsertRows(QModelIndex(), rnum, rnum); + m_rowCount++; + endInsertRows(); + } + } + } + +private: + int m_rowCount; +}; + +void tst_QQuickListView::QTBUG_48870_fastModelUpdates() +{ + QTBUG_48870_Model model; + + QQuickView *window = createView(); + QVERIFY(window); + QQmlContext *ctxt = window->rootContext(); + QVERIFY(ctxt); + ctxt->setContextProperty("testModel", &model); + + window->setSource(testFileUrl("qtbug48870.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list"); + QTRY_VERIFY(listview != 0); + + QQuickItemViewPrivate *priv = QQuickItemViewPrivate::get(listview); + bool nonUnique; + FxViewItem *item = Q_NULLPTR; + int expectedIdx; + QVERIFY(testVisibleItems(priv, &nonUnique, &item, &expectedIdx)); + + for (int i = 0; i < 10; i++) { + QTest::qWait(100); + QVERIFY2(testVisibleItems(priv, &nonUnique, &item, &expectedIdx), + qPrintable(!item ? QString("Unexpected null item") + : nonUnique ? QString("Non-unique item at %1 and %2").arg(item->index).arg(expectedIdx) + : QString("Found index %1, expected index is %3").arg(item->index).arg(expectedIdx))); + if (i % 3 != 0) { + if (i & 1) + flick(window, QPoint(100, 200), QPoint(100, 0), 100); + else + flick(window, QPoint(100, 200), QPoint(100, 400), 100); + } + } + + delete window; +} + QTEST_MAIN(tst_QQuickListView) #include "tst_qquicklistview.moc" diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index c7de73da88..7f454aaa11 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -286,6 +286,9 @@ QList<Key> &operator <<(QList<Key> &keys, Qt::Key key) tst_qquicktextedit::tst_qquicktextedit() { + qRegisterMetaType<QQuickTextEdit::TextFormat>(); + qRegisterMetaType<QQuickTextEdit::SelectionMode>(); + standard << "the quick brown fox jumped over the lazy dog" << "the quick brown fox\n jumped over the lazy dog" << "Hello, world!" @@ -596,7 +599,7 @@ void tst_qquicktextedit::textFormat() QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(object.data()); QVERIFY(edit); - QSignalSpy spy(edit, SIGNAL(textFormatChanged(TextFormat))); + QSignalSpy spy(edit, &QQuickTextEdit::textFormatChanged); QCOMPARE(edit->textFormat(), QQuickTextEdit::PlainText); @@ -2113,7 +2116,7 @@ void tst_qquicktextedit::mouseSelectionMode_accessors() QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(object.data()); QVERIFY(edit); - QSignalSpy spy(edit, SIGNAL(mouseSelectionModeChanged(SelectionMode))); + QSignalSpy spy(edit, &QQuickTextEdit::mouseSelectionModeChanged); QCOMPARE(edit->mouseSelectionMode(), QQuickTextEdit::SelectCharacters); diff --git a/tests/auto/quick/touchmouse/data/hoverMouseAreas.qml b/tests/auto/quick/touchmouse/data/hoverMouseAreas.qml new file mode 100644 index 0000000000..1bdd0b3caf --- /dev/null +++ b/tests/auto/quick/touchmouse/data/hoverMouseAreas.qml @@ -0,0 +1,39 @@ +import QtQuick 2.4 + +Item { + width: 500 + height: 500 + + Rectangle { + width: 300 + height: 90 + color: mouseArea1.containsMouse ? "red" : "grey" + x: 100 + y: 100 + + MouseArea { + id: mouseArea1 + objectName: "mouseArea1" + anchors.fill: parent + hoverEnabled: true + onPressed: parent.border.width = 4 + onReleased: parent.border.width = 0 + } + } + Rectangle { + width: 300 + height: 100 + color: mouseArea2.containsMouse ? "red" : "lightblue" + x: 100 + y: 200 + + MouseArea { + id: mouseArea2 + objectName: "mouseArea2" + anchors.fill: parent + hoverEnabled: true + onPressed: parent.border.width = 4 + onReleased: parent.border.width = 0 + } + } +} diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp index 90ee8215a1..e14b7d7c84 100644 --- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp +++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp @@ -161,6 +161,8 @@ private slots: void touchGrabCausesMouseUngrab(); + void hoverEnabled(); + protected: bool eventFilter(QObject *, QEvent *event) { @@ -1232,6 +1234,93 @@ void tst_TouchMouse::touchGrabCausesMouseUngrab() delete window; } +void tst_TouchMouse::hoverEnabled() +{ + // QTouchDevice *device = new QTouchDevice; + // device->setType(QTouchDevice::TouchScreen); + // QWindowSystemInterface::registerTouchDevice(device); + + QQuickView *window = createView(); + window->setSource(testFileUrl("hoverMouseAreas.qml")); + + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + QQuickItem *root = window->rootObject(); + QVERIFY(root != 0); + + QQuickMouseArea *mouseArea1 = root->findChild<QQuickMouseArea*>("mouseArea1"); + QVERIFY(mouseArea1 != 0); + + QQuickMouseArea *mouseArea2 = root->findChild<QQuickMouseArea*>("mouseArea2"); + QVERIFY(mouseArea2 != 0); + + QSignalSpy enterSpy1(mouseArea1, SIGNAL(entered())); + QSignalSpy exitSpy1(mouseArea1, SIGNAL(exited())); + QSignalSpy clickSpy1(mouseArea1, SIGNAL(clicked(QQuickMouseEvent *))); + + QSignalSpy enterSpy2(mouseArea2, SIGNAL(entered())); + QSignalSpy exitSpy2(mouseArea2, SIGNAL(exited())); + QSignalSpy clickSpy2(mouseArea2, SIGNAL(clicked(QQuickMouseEvent *))); + + QPoint p0(50, 50); + QPoint p1(150, 150); + QPoint p2(150, 250); + + // ------------------------- Mouse move to mouseArea1 + QTest::mouseMove(window, p1); + + QVERIFY(enterSpy1.count() == 1); + QVERIFY(mouseArea1->hovered()); + QVERIFY(!mouseArea2->hovered()); + + // ------------------------- Touch click on mouseArea1 + QTest::touchEvent(window, device).press(0, p1, window); + + QVERIFY(enterSpy1.count() == 1); + QVERIFY(enterSpy2.count() == 0); + QVERIFY(mouseArea1->pressed()); + QVERIFY(mouseArea1->hovered()); + QVERIFY(!mouseArea2->hovered()); + + QTest::touchEvent(window, device).release(0, p1, window); + QVERIFY(clickSpy1.count() == 1); + QVERIFY(mouseArea1->hovered()); + QVERIFY(!mouseArea2->hovered()); + + // ------------------------- Touch click on mouseArea2 + QTest::touchEvent(window, device).press(0, p2, window); + + QVERIFY(mouseArea1->hovered()); + QVERIFY(mouseArea2->hovered()); + QVERIFY(mouseArea2->pressed()); + QVERIFY(enterSpy1.count() == 1); + QVERIFY(enterSpy2.count() == 1); + + QTest::touchEvent(window, device).release(0, p2, window); + + QVERIFY(clickSpy2.count() == 1); + QVERIFY(mouseArea1->hovered()); + QVERIFY(!mouseArea2->hovered()); + QVERIFY(exitSpy1.count() == 0); + QVERIFY(exitSpy2.count() == 1); + + // ------------------------- Another touch click on mouseArea1 + QTest::touchEvent(window, device).press(0, p1, window); + + QVERIFY(enterSpy1.count() == 1); + QVERIFY(enterSpy2.count() == 1); + QVERIFY(mouseArea1->pressed()); + QVERIFY(mouseArea1->hovered()); + QVERIFY(!mouseArea2->hovered()); + + QTest::touchEvent(window, device).release(0, p1, window); + QVERIFY(clickSpy1.count() == 2); + QVERIFY(mouseArea1->hovered()); + QVERIFY(!mouseArea1->pressed()); + QVERIFY(!mouseArea2->hovered()); +} + QTEST_MAIN(tst_TouchMouse) #include "tst_touchmouse.moc" |