aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quick')
-rw-r--r--tests/auto/quick/nodes/tst_nodestest.cpp9
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST1
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml58
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/mousearea_interop.pro15
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp178
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp4
-rw-r--r--tests/auto/quick/pointerhandlers/pointerhandlers.pro1
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml1
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp22
-rw-r--r--tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp34
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp218
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml33
-rw-r--r--tests/auto/quick/qquicklistview/data/listview-initCurrent.qml1
-rw-r--r--tests/auto/quick/qquicklistview/data/moveObjectModelItemToAnotherObjectModel.qml140
-rw-r--r--tests/auto/quick/qquicklistview/data/reusedelegateitems.qml98
-rw-r--r--tests/auto/quick/qquicklistview/qquicklistview.pro3
-rw-r--r--tests/auto/quick/qquicklistview/reusemodel.h84
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp257
-rw-r--r--tests/auto/quick/qquickmousearea/BLACKLIST4
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp50
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp66
-rw-r--r--tests/auto/quick/qquickpathview/data/ungrabNestedinFlickable.qml75
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp35
-rw-r--r--tests/auto/quick/qquickpixmapcache/data/asynchronousNoCache.qml17
-rw-r--r--tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp15
-rw-r--r--tests/auto/quick/qquickrepeater/data/contextProperty.qml13
-rw-r--r--tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp24
-rw-r--r--tests/auto/quick/qquicktableview/data/checkalwaysemit.qml87
-rw-r--r--tests/auto/quick/qquicktableview/data/replaceModelTableView.qml56
-rw-r--r--tests/auto/quick/qquicktableview/qquicktableview.pro2
-rw-r--r--tests/auto/quick/qquicktableview/testmodel.h33
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp114
-rw-r--r--tests/auto/quick/qquicktextedit/BLACKLIST4
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp4
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp67
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/filterGroupForDelegate.qml77
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/data/readFromProxyObject.qml23
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp30
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp6
-rw-r--r--tests/auto/quick/shared/viewtestutil.cpp4
40 files changed, 1792 insertions, 171 deletions
diff --git a/tests/auto/quick/nodes/tst_nodestest.cpp b/tests/auto/quick/nodes/tst_nodestest.cpp
index bd5e6c6383..249ecd5aa5 100644
--- a/tests/auto/quick/nodes/tst_nodestest.cpp
+++ b/tests/auto/quick/nodes/tst_nodestest.cpp
@@ -121,9 +121,6 @@ class DummyRenderer : public QSGBatchRenderer::Renderer
public:
DummyRenderer(QSGRootNode *root, QSGDefaultRenderContext *renderContext)
: QSGBatchRenderer::Renderer(renderContext)
- , changedNode(nullptr)
- , changedState(nullptr)
- , renderCount(0)
{
setRootNode(root);
}
@@ -139,11 +136,11 @@ public:
QSGBatchRenderer::Renderer::nodeChanged(node, state);
}
- QSGNode *changedNode;
+ QSGNode *changedNode = nullptr;
QSGNode::DirtyState changedState;
- int renderCount;
- int renderingOrder;
+ int renderCount = 0;
+ int renderingOrder = 0;
static int globalRendereringOrder;
};
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST b/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
index 20f989fc50..92903955ac 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
@@ -1,5 +1,6 @@
[touchAndDragHandlerOnFlickable]
windows gcc
+opensuse-leap
[touchDragFlickableBehindSlider]
windows gcc
[touchDragFlickableBehindButton]
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml b/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml
new file mode 100644
index 0000000000..48b1dc86f0
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/data/dragTakeOverFromSibling.qml
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ width: 640
+ height: 480
+
+ Rectangle {
+ width: 200
+ height: 200
+ color: mouseArea.pressed ? "red" : "blue"
+ opacity: 0.6
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ }
+ }
+ Rectangle {
+ y: 100
+ z: -1
+ width: 200
+ height: 200
+ color: dragHandler.active ? "orange" : "green"
+ opacity: 0.6
+
+ DragHandler {
+ id: dragHandler
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/mousearea_interop.pro b/tests/auto/quick/pointerhandlers/mousearea_interop/mousearea_interop.pro
new file mode 100644
index 0000000000..0bf0ec86a9
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/mousearea_interop.pro
@@ -0,0 +1,15 @@
+CONFIG += testcase
+
+TARGET = tst_mousearea_interop
+QT += core-private gui-private qml-private quick-private testlib
+
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_mousearea_interop.cpp
+
+include (../../../shared/util.pri)
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+OTHER_FILES += data/dragTakeOverFromSibling.qml
diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp b/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
new file mode 100644
index 0000000000..794562fea0
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlproperty.h>
+#include <QtQuick/private/qquickdraghandler_p.h>
+#include <QtQuick/private/qquickmousearea_p.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
+
+#include "../../../shared/util.h"
+#include "../../shared/viewtestutil.h"
+
+Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
+
+class tst_MouseAreaInterop : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_MouseAreaInterop()
+ : touchDevice(QTest::createTouchDevice())
+ , touchPointerDevice(QQuickPointerDevice::touchDevice(touchDevice))
+ {}
+
+private slots:
+ void dragHandlerInSiblingStealingGrabFromMouseAreaViaMouse();
+ void dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch_data();
+ void dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch();
+
+private:
+ void createView(QScopedPointer<QQuickView> &window, const char *fileName);
+ QTouchDevice *touchDevice;
+ QQuickPointerDevice *touchPointerDevice;
+};
+
+void tst_MouseAreaInterop::createView(QScopedPointer<QQuickView> &window, const char *fileName)
+{
+ window.reset(new QQuickView);
+ window->setSource(testFileUrl(fileName));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QVERIFY(window->rootObject() != nullptr);
+}
+
+void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaMouse()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "dragTakeOverFromSibling.qml");
+ QQuickView * window = windowPtr.data();
+ auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(QQuickPointerDevice::genericMouseDevice());
+
+ QPointer<QQuickPointerHandler> handler = window->rootObject()->findChild<QQuickPointerHandler*>();
+ QVERIFY(handler);
+ QQuickMouseArea *ma = window->rootObject()->findChild<QQuickMouseArea*>();
+ QVERIFY(ma);
+
+ QPoint p1(150, 150);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QCOMPARE(window->mouseGrabberItem(), ma);
+ QCOMPARE(ma->pressed(), true);
+
+ // Start dragging
+ // DragHandler keeps monitoring, due to its passive grab,
+ // and eventually steals the exclusive grab from MA
+ int dragStoleGrab = 0;
+ for (int i = 0; i < 4; ++i) {
+ p1 += QPoint(dragThreshold / 2, 0);
+ QTest::mouseMove(window, p1);
+ if (!dragStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == handler)
+ dragStoleGrab = i;
+ }
+ if (dragStoleGrab)
+ qCDebug(lcPointerTests, "DragHandler stole the grab after %d events", dragStoleGrab);
+ QVERIFY(dragStoleGrab > 1);
+ QCOMPARE(handler->active(), true);
+ QCOMPARE(ma->pressed(), false);
+
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QCOMPARE(handler->active(), false);
+}
+
+void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch_data()
+{
+ QTest::addColumn<bool>("preventStealing");
+
+ QTest::newRow("allow stealing") << false;
+ QTest::newRow("prevent stealing") << true;
+}
+
+void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch() // QTBUG-77624 and QTBUG-79163
+{
+ QFETCH(bool, preventStealing);
+
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "dragTakeOverFromSibling.qml");
+ QQuickView * window = windowPtr.data();
+ auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(touchPointerDevice);
+
+ QPointer<QQuickPointerHandler> handler = window->rootObject()->findChild<QQuickPointerHandler*>();
+ QVERIFY(handler);
+ QQuickMouseArea *ma = window->rootObject()->findChild<QQuickMouseArea*>();
+ QVERIFY(ma);
+ ma->setPreventStealing(preventStealing);
+
+ QPoint p1(150, 150);
+ QTest::QTouchEventSequence touch = QTest::touchEvent(window, touchDevice);
+
+ touch.press(1, p1).commit();
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(pointerEvent->point(0)->passiveGrabbers().contains(handler));
+ QCOMPARE(pointerEvent->point(0)->grabberItem(), ma);
+ QCOMPARE(window->mouseGrabberItem(), ma);
+ QCOMPARE(ma->pressed(), true);
+
+ // Start dragging
+ // DragHandler keeps monitoring, due to its passive grab,
+ // and eventually steals the exclusive grab from MA if MA allows it
+ int dragStoleGrab = 0;
+ for (int i = 0; i < 4; ++i) {
+ p1 += QPoint(dragThreshold / 2, 0);
+ touch.move(1, p1).commit();
+ QQuickTouchUtils::flush(window);
+ if (!dragStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == handler)
+ dragStoleGrab = i;
+ }
+ if (dragStoleGrab)
+ qCDebug(lcPointerTests, "DragHandler stole the grab after %d events", dragStoleGrab);
+ if (preventStealing) {
+ QCOMPARE(dragStoleGrab, 0);
+ QCOMPARE(handler->active(), false);
+ QCOMPARE(ma->pressed(), true);
+ } else {
+ QVERIFY(dragStoleGrab > 1);
+ QCOMPARE(handler->active(), true);
+ QCOMPARE(ma->pressed(), false);
+ }
+
+ touch.release(1, p1).commit();
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(handler->active(), false);
+}
+
+QTEST_MAIN(tst_MouseAreaInterop)
+
+#include "tst_mousearea_interop.moc"
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
index 35fed99e8b..4a7a132be2 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
@@ -295,10 +295,10 @@ void tst_MptaInterop::unloadHandlerWithPassiveGrab()
QVERIFY(mpta);
QPoint point(90, 90);
- QTest::mousePress(window, Qt::LeftButton, 0, point);
+ QTest::mousePress(window, Qt::LeftButton, {}, point);
QCOMPARE(window->mouseGrabberItem(), mpta);
QTRY_VERIFY(handler.isNull()); // it got unloaded
- QTest::mouseRelease(window, Qt::LeftButton, 0, point); // QTBUG-73819: don't crash
+ QTest::mouseRelease(window, Qt::LeftButton, {}, point); // QTBUG-73819: don't crash
}
void tst_MptaInterop::dragHandlerInParentStealingGrabFromItem() // QTBUG-75025
diff --git a/tests/auto/quick/pointerhandlers/pointerhandlers.pro b/tests/auto/quick/pointerhandlers/pointerhandlers.pro
index 4d6311bdb2..7db28b6583 100644
--- a/tests/auto/quick/pointerhandlers/pointerhandlers.pro
+++ b/tests/auto/quick/pointerhandlers/pointerhandlers.pro
@@ -3,6 +3,7 @@ TEMPLATE = subdirs
qtConfig(private_tests) {
SUBDIRS += \
flickableinterop \
+ mousearea_interop \
multipointtoucharea_interop \
qquickdraghandler \
qquickhoverhandler \
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
index 042b730799..800c25c77d 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
@@ -31,6 +31,7 @@ import QtQuick 2.12
Rectangle {
id: root
property alias label: label.text
+ property alias active: tap.active
property alias pressed: tap.pressed
property bool checked: false
property alias gesturePolicy: tap.gesturePolicy
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
index e77ea97518..419afed3ac 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
@@ -600,10 +600,32 @@ void tst_TapHandler::buttonsMultiTouch()
touchSeq.stationary(1).press(2, p2, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(buttonWithinBounds->property("pressed").toBool());
+ QVERIFY(buttonWithinBounds->property("active").toBool());
QPoint p3 = buttonReleaseWithinBounds->mapToScene(QPointF(20, 20)).toPoint();
touchSeq.stationary(1).stationary(2).press(3, p3, window).commit();
QQuickTouchUtils::flush(window);
QTRY_VERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ QVERIFY(buttonReleaseWithinBounds->property("active").toBool());
+ QVERIFY(buttonWithinBounds->property("pressed").toBool());
+ QVERIFY(buttonWithinBounds->property("active").toBool());
+ QVERIFY(buttonDragThreshold->property("pressed").toBool());
+
+ // combinations of small touchpoint movements and stationary points should not cause state changes
+ p1 += QPoint(2, 0);
+ p2 += QPoint(3, 0);
+ touchSeq.move(1, p1).move(2, p2).stationary(3).commit();
+ QVERIFY(buttonDragThreshold->property("pressed").toBool());
+ QVERIFY(buttonWithinBounds->property("pressed").toBool());
+ QVERIFY(buttonWithinBounds->property("active").toBool());
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ QVERIFY(buttonReleaseWithinBounds->property("active").toBool());
+ p3 += QPoint(4, 0);
+ touchSeq.stationary(1).stationary(2).move(3, p3).commit();
+ QVERIFY(buttonDragThreshold->property("pressed").toBool());
+ QVERIFY(buttonWithinBounds->property("pressed").toBool());
+ QVERIFY(buttonWithinBounds->property("active").toBool());
+ QVERIFY(buttonReleaseWithinBounds->property("pressed").toBool());
+ QVERIFY(buttonReleaseWithinBounds->property("active").toBool());
// can release top button and press again: others stay pressed the whole time
touchSeq.stationary(2).stationary(3).release(1, p1, window).commit();
diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
index d1f6d67aa1..061d5f8a1a 100644
--- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
+++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
@@ -185,7 +185,8 @@ void tst_QQuickAccessible::quickAttachedProperties()
QObject *object = component.create();
QVERIFY(object != nullptr);
- QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object);
+ const auto attachedObject = qobject_cast<QQuickAccessibleAttached*>(
+ QQuickAccessibleAttached::attachedProperties(object));
QVERIFY(attachedObject);
if (attachedObject) {
QVariant p = attachedObject->property("role");
@@ -195,6 +196,7 @@ void tst_QQuickAccessible::quickAttachedProperties()
QCOMPARE(p.isNull(), true);
p = attachedObject->property("description");
QCOMPARE(p.isNull(), true);
+ QCOMPARE(attachedObject->wasNameExplicitlySet(), false);
}
delete object;
}
@@ -211,7 +213,8 @@ void tst_QQuickAccessible::quickAttachedProperties()
QObject *object = component.create();
QVERIFY(object != nullptr);
- QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object);
+ const auto attachedObject = qobject_cast<QQuickAccessibleAttached*>(
+ QQuickAccessibleAttached::attachedProperties(object));
QVERIFY(attachedObject);
if (attachedObject) {
QVariant p = attachedObject->property("role");
@@ -223,6 +226,7 @@ void tst_QQuickAccessible::quickAttachedProperties()
p = attachedObject->property("description");
QCOMPARE(p.isNull(), false);
QCOMPARE(p.toString(), QLatin1String("Duck"));
+ QCOMPARE(attachedObject->wasNameExplicitlySet(), true);
}
delete object;
}
@@ -292,6 +296,32 @@ void tst_QQuickAccessible::quickAttachedProperties()
}
delete object;
}
+ // Check that a name can be implicitly set.
+ {
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(R"(
+ import QtQuick 2.0
+ Text {
+ Accessible.role: Accessible.Button
+ Accessible.description: "Text Button"
+ })", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object);
+
+ const auto attachedObject = qobject_cast<QQuickAccessibleAttached*>(
+ QQuickAccessibleAttached::attachedProperties(object.data()));
+ QVERIFY(attachedObject);
+ QVERIFY(!attachedObject->wasNameExplicitlySet());
+
+ attachedObject->setNameImplicitly(QLatin1String("Implicit"));
+ QCOMPARE(attachedObject->name(), QLatin1String("Implicit"));
+ QVERIFY(!attachedObject->wasNameExplicitlySet());
+
+ attachedObject->setName(QLatin1String("Explicit"));
+ QCOMPARE(attachedObject->name(), QLatin1String("Explicit"));
+ QVERIFY(attachedObject->wasNameExplicitlySet());
+ }
QTestAccessibility::clearEvents();
}
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index 48f779a490..55957fa71a 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -265,7 +265,8 @@ void tst_qquickanimations::simplePath()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathAnimation.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
@@ -299,14 +300,13 @@ void tst_qquickanimations::simplePath()
pathAnim->start();
QTRY_VERIFY(redRect->rotation() != 0);
pathAnim->stop();
-
- delete rect;
}
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathAnimation2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
@@ -334,8 +334,6 @@ void tst_qquickanimations::simplePath()
QCOMPARE(redRect->x(), qreal(300));
QCOMPARE(redRect->y(), qreal(300));
QCOMPARE(redRect->rotation(), qreal(0));
-
- delete rect;
}
}
@@ -343,7 +341,8 @@ void tst_qquickanimations::simpleAnchor()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("reanchor.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *greenRect = rect->findChild<QQuickRectangle*>();
@@ -411,15 +410,14 @@ void tst_qquickanimations::simpleAnchor()
QCOMPARE(greenRect->y(), qreal(50));
QCOMPARE(greenRect->width(), qreal(150));
QCOMPARE(greenRect->height(), qreal(125));
-
- delete rect;
}
void tst_qquickanimations::reparent()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("reparent.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *target = rect->findChild<QQuickRectangle*>("target");
@@ -460,15 +458,14 @@ void tst_qquickanimations::reparent()
QCOMPARE(target->height(), qreal(50));
QCOMPARE(target->rotation(), qreal(0));
QCOMPARE(target->scale(), qreal(1));
-
- delete rect;
}
void tst_qquickanimations::pathInterpolator()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathInterpolator.qml"));
- QQuickPathInterpolator *interpolator = qobject_cast<QQuickPathInterpolator*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *interpolator = qobject_cast<QQuickPathInterpolator*>(obj.data());
QVERIFY(interpolator);
QCOMPARE(interpolator->progress(), qreal(0));
@@ -504,7 +501,8 @@ void tst_qquickanimations::pathInterpolatorBackwardJump()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathInterpolatorBack.qml"));
- QQuickPathInterpolator *interpolator = qobject_cast<QQuickPathInterpolator*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *interpolator = qobject_cast<QQuickPathInterpolator*>(obj.data());
QVERIFY(interpolator);
QCOMPARE(interpolator->progress(), qreal(0));
@@ -535,7 +533,8 @@ void tst_qquickanimations::pathInterpolatorBackwardJump()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathInterpolatorBack2.qml"));
- QQuickPathInterpolator *interpolator = qobject_cast<QQuickPathInterpolator*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *interpolator = qobject_cast<QQuickPathInterpolator*>(obj.data());
QVERIFY(interpolator);
QCOMPARE(interpolator->progress(), qreal(0));
@@ -562,7 +561,8 @@ void tst_qquickanimations::pathWithNoStart()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathAnimationNoStart.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
@@ -728,12 +728,9 @@ void tst_qquickanimations::badTypes()
{
//don't crash
{
- QQuickView *view = new QQuickView;
+ QScopedPointer<QQuickView> view(new QQuickView);
view->setSource(testFileUrl("badtype1.qml"));
-
qApp->processEvents();
-
- delete view;
}
//make sure we get a compiler error
@@ -741,7 +738,8 @@ void tst_qquickanimations::badTypes()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("badtype2.qml"));
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
- c.create();
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY(obj.isNull());
QCOMPARE(c.errors().count(), 1);
QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: number expected"));
@@ -752,7 +750,8 @@ void tst_qquickanimations::badTypes()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("badtype3.qml"));
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
- c.create();
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY(obj.isNull());
QCOMPARE(c.errors().count(), 1);
QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: color expected"));
@@ -762,7 +761,8 @@ void tst_qquickanimations::badTypes()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("badtype4.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickItemPrivate::get(rect)->setState("state1");
@@ -782,13 +782,15 @@ void tst_qquickanimations::badProperties()
QQmlComponent c1(&engine, testFileUrl("badproperty1.qml"));
QByteArray message = testFileUrl("badproperty1.qml").toString().toUtf8() + ":18:9: QML ColorAnimation: Cannot animate non-existent property \"border.colr\"";
QTest::ignoreMessage(QtWarningMsg, message);
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c1.create());
+ QScopedPointer<QObject> obj(c1.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQmlComponent c2(&engine, testFileUrl("badproperty2.qml"));
message = testFileUrl("badproperty2.qml").toString().toUtf8() + ":18:9: QML ColorAnimation: Cannot animate read-only property \"border\"";
QTest::ignoreMessage(QtWarningMsg, message);
- rect = qobject_cast<QQuickRectangle*>(c2.create());
+ QScopedPointer<QObject> obj2(c2.create());
+ rect = qobject_cast<QQuickRectangle*>(obj2.data());
QVERIFY(rect);
//### should we warn here are well?
@@ -804,7 +806,8 @@ void tst_qquickanimations::mixedTypes()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("mixedtype1.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickItemPrivate::get(rect)->setState("state1");
@@ -820,7 +823,8 @@ void tst_qquickanimations::mixedTypes()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("mixedtype2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickItemPrivate::get(rect)->setState("state1");
@@ -840,7 +844,8 @@ void tst_qquickanimations::properties()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("properties.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -852,7 +857,8 @@ void tst_qquickanimations::properties()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("properties2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -864,7 +870,8 @@ void tst_qquickanimations::properties()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("properties3.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -876,7 +883,8 @@ void tst_qquickanimations::properties()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("properties4.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -889,7 +897,8 @@ void tst_qquickanimations::properties()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("properties5.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -906,7 +915,8 @@ void tst_qquickanimations::propertiesTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickItemPrivate::get(rect)->setState("moved");
@@ -919,7 +929,8 @@ void tst_qquickanimations::propertiesTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -934,7 +945,8 @@ void tst_qquickanimations::propertiesTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition3.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -947,7 +959,8 @@ void tst_qquickanimations::propertiesTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition4.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -961,7 +974,8 @@ void tst_qquickanimations::propertiesTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition5.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -975,7 +989,8 @@ void tst_qquickanimations::propertiesTransition()
/*{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition6.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -989,7 +1004,8 @@ void tst_qquickanimations::propertiesTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("propertiesTransition7.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickItemPrivate::get(rect)->setState("moved");
@@ -1005,7 +1021,8 @@ void tst_qquickanimations::pathTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathTransition.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("redRect");
@@ -1025,7 +1042,8 @@ void tst_qquickanimations::disabledTransition()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("disabledTransition.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
@@ -1053,12 +1071,12 @@ void tst_qquickanimations::disabledTransition()
void tst_qquickanimations::invalidDuration()
{
- QQuickPropertyAnimation *animation = new QQuickPropertyAnimation;
+ QScopedPointer<QQuickPropertyAnimation> animation(new QQuickPropertyAnimation);
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML PropertyAnimation: Cannot set a duration of < 0");
animation->setDuration(-1);
QCOMPARE(animation->duration(), 250);
- QQuickPauseAnimation *pauseAnimation = new QQuickPauseAnimation;
+ QScopedPointer<QQuickPauseAnimation> pauseAnimation(new QQuickPauseAnimation);
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML PauseAnimation: Cannot set a duration of < 0");
pauseAnimation->setDuration(-1);
QCOMPARE(pauseAnimation->duration(), 250);
@@ -1071,7 +1089,8 @@ void tst_qquickanimations::attached()
QQmlComponent c(&engine, testFileUrl("attached.qml"));
QTest::ignoreMessage(QtDebugMsg, "off");
QTest::ignoreMessage(QtDebugMsg, "on");
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
}
@@ -1082,7 +1101,8 @@ void tst_qquickanimations::propertyValueSourceDefaultStart()
QQmlComponent c(&engine, testFileUrl("valuesource.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
@@ -1095,7 +1115,8 @@ void tst_qquickanimations::propertyValueSourceDefaultStart()
QQmlComponent c(&engine, testFileUrl("valuesource2.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
@@ -1108,7 +1129,8 @@ void tst_qquickanimations::propertyValueSourceDefaultStart()
QQmlComponent c(&engine, testFileUrl("dontAutoStart.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
@@ -1127,7 +1149,8 @@ void tst_qquickanimations::dontStart()
QString warning = c.url().toString() + ":14:13: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
@@ -1142,7 +1165,8 @@ void tst_qquickanimations::dontStart()
QString warning = c.url().toString() + ":15:17: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
@@ -1158,7 +1182,8 @@ void tst_qquickanimations::easingProperties()
QString componentStr = "import QtQuick 2.0\nNumberAnimation { easing.type: \"InOutQuad\" }";
QQmlComponent animationComponent(&engine);
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
+ QScopedPointer<QObject> obj(animationComponent.create());
+ auto *animObject = qobject_cast<QQuickPropertyAnimation *>(obj.data());
QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::InOutQuad);
@@ -1169,7 +1194,8 @@ void tst_qquickanimations::easingProperties()
QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"OutBounce\"; easing.amplitude: 5.0 }";
QQmlComponent animationComponent(&engine);
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
+ QScopedPointer<QObject> obj(animationComponent.create());
+ auto *animObject = qobject_cast<QQuickPropertyAnimation *>(obj.data());
QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::OutBounce);
@@ -1181,7 +1207,8 @@ void tst_qquickanimations::easingProperties()
QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"OutElastic\"; easing.amplitude: 5.0; easing.period: 3.0}";
QQmlComponent animationComponent(&engine);
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
+ QScopedPointer<QObject> obj(animationComponent.create());
+ auto *animObject = qobject_cast<QQuickPropertyAnimation *>(obj.data());
QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::OutElastic);
@@ -1194,7 +1221,8 @@ void tst_qquickanimations::easingProperties()
QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"InOutBack\"; easing.overshoot: 2 }";
QQmlComponent animationComponent(&engine);
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
+ QScopedPointer<QObject> obj(animationComponent.create());
+ auto *animObject = qobject_cast<QQuickPropertyAnimation *>(obj.data());
QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::InOutBack);
@@ -1206,7 +1234,8 @@ void tst_qquickanimations::easingProperties()
QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"Bezier\"; easing.bezierCurve: [0.5, 0.2, 0.13, 0.65, 1.0, 1.0] }";
QQmlComponent animationComponent(&engine);
animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
- QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
+ QScopedPointer<QObject> obj(animationComponent.create());
+ auto *animObject = qobject_cast<QQuickPropertyAnimation *>(obj.data());
QVERIFY(animObject != nullptr);
QCOMPARE(animObject->easing().type(), QEasingCurve::BezierSpline);
@@ -1222,7 +1251,8 @@ void tst_qquickanimations::rotation()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("rotation.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *rr = rect->findChild<QQuickRectangle*>("rr");
@@ -1252,7 +1282,8 @@ void tst_qquickanimations::startStopSignals()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("signals.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *root = qobject_cast<QQuickItem *>(obj.data());
QVERIFY(root);
QCOMPARE(root->property("startedCount").toInt(), 1); //autostart
@@ -1297,7 +1328,8 @@ void tst_qquickanimations::runningTrueBug()
//ensure we start correctly when "running: true" is explicitly set
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("runningTrueBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *cloud = rect->findChild<QQuickRectangle*>("cloud");
@@ -1312,7 +1344,8 @@ void tst_qquickanimations::pathAnimationInOutBackBug()
//ensure we don't pass bad progress value (out of [0,1]) to QQuickPath::backwardsPointAt()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pathAnimationInOutBackCrash.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *item = qobject_cast<QQuickItem *>(obj.data());
QVERIFY(item);
QQuickRectangle *rect = item->findChild<QQuickRectangle *>("rect");
@@ -1330,7 +1363,8 @@ void tst_qquickanimations::nonTransitionBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("nonTransitionBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect != nullptr);
QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
@@ -1356,7 +1390,8 @@ void tst_qquickanimations::registrationBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("registrationBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect != nullptr);
QTRY_COMPARE(rect->property("value"), QVariant(int(100)));
}
@@ -1366,7 +1401,8 @@ void tst_qquickanimations::doubleRegistrationBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("doubleRegistrationBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect != nullptr);
QQuickAbstractAnimation *anim = rect->findChild<QQuickAbstractAnimation*>("animation");
@@ -1407,7 +1443,8 @@ void tst_qquickanimations::transitionAssignmentBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("transitionAssignmentBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect != nullptr);
QCOMPARE(rect->property("nullObject").toBool(), false);
@@ -1419,12 +1456,11 @@ void tst_qquickanimations::pauseBindingBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pauseBindingBug.qml"));
- QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect != nullptr);
QQuickAbstractAnimation *anim = rect->findChild<QQuickAbstractAnimation*>("animation");
QCOMPARE(anim->qtAnimation()->state(), QAbstractAnimationJob::Paused);
-
- delete rect;
}
//QTBUG-13598
@@ -1433,13 +1469,12 @@ void tst_qquickanimations::pauseBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("pauseBug.qml"));
- QQuickAbstractAnimation *anim = qobject_cast<QQuickAbstractAnimation*>(c.create());
+ QScopedPointer<QObject> obj(c.create());
+ auto *anim = qobject_cast<QQuickAbstractAnimation*>(obj.data());
QVERIFY(anim != nullptr);
QCOMPARE(anim->qtAnimation()->state(), QAbstractAnimationJob::Paused);
QCOMPARE(anim->isPaused(), true);
QCOMPARE(anim->isRunning(), true);
-
- delete anim;
}
//QTBUG-23092
@@ -1448,7 +1483,7 @@ void tst_qquickanimations::loopingBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("looping.qml"));
- QObject *obj = c.create();
+ QScopedPointer<QObject> obj(c.create());
QQuickAbstractAnimation *anim = obj->findChild<QQuickAbstractAnimation*>();
QVERIFY(anim != nullptr);
@@ -1460,8 +1495,6 @@ void tst_qquickanimations::loopingBug()
QQuickRectangle *rect = obj->findChild<QQuickRectangle*>();
QVERIFY(rect != nullptr);
QCOMPARE(rect->rotation(), qreal(90));
-
- delete obj;
}
//QTBUG-24532
@@ -1482,7 +1515,7 @@ void tst_qquickanimations::scriptActionBug()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("scriptActionBug.qml"));
- QObject *obj = c.create();
+ QScopedPointer<QObject> obj(c.create());
//Both the ScriptAction and StateChangeScript should be triggered
QCOMPARE(obj->property("actionTriggered").toBool(), true);
@@ -1496,20 +1529,16 @@ void tst_qquickanimations::groupAnimationNullChildBug()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("sequentialAnimationNullChildBug.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QObject> root(c.create());
QVERIFY(root);
-
- delete root;
}
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("parallelAnimationNullChildBug.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QScopedPointer<QObject> root(c.create());
QVERIFY(root);
-
- delete root;
}
}
@@ -1518,12 +1547,10 @@ void tst_qquickanimations::scriptActionCrash()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("scriptActionCrash.qml"));
- QObject *obj = c.create();
+ QScopedPointer<QObject> obj(c.create());
//just testing that we don't crash
QTest::qWait(1000); //5x transition duration
-
- delete obj;
}
// QTBUG-49364
@@ -1534,12 +1561,10 @@ void tst_qquickanimations::animatorInvalidTargetCrash()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("animatorInvalidTargetCrash.qml"));
- QObject *obj = c.create();
+ QScopedPointer<QObject> obj(c.create());
//just testing that we don't crash
QTest::qWait(5000); //animator duration
-
- delete obj;
}
Q_DECLARE_METATYPE(QList<QQmlError>)
@@ -1555,7 +1580,8 @@ void tst_qquickanimations::defaultPropertyWarning()
QVERIFY(warnings.isValid());
QQmlComponent component(&engine, testFileUrl("defaultRotationAnimation.qml"));
- QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(component.create()));
+ QScopedPointer<QObject> obj(component.create());
+ auto *root = qobject_cast<QQuickItem *>(obj.data());
QVERIFY(root);
QVERIFY(warnings.isEmpty());
@@ -1566,7 +1592,8 @@ void tst_qquickanimations::pathSvgAnimation()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("pathSvgAnimation.qml"));
- QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(component.create()));
+ QScopedPointer<QObject> obj(component.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
@@ -1587,7 +1614,8 @@ void tst_qquickanimations::pathLineUnspecifiedXYBug()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("pathLineUnspecifiedXYBug.qml"));
- QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(component.create()));
+ QScopedPointer<QObject> obj(component.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
QVERIFY(rect);
QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
@@ -1623,7 +1651,8 @@ void tst_qquickanimations::finished()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("finished.qml"));
- QScopedPointer<QObject> root(component.create());
+ QScopedPointer<QObject> obj(component.create());
+ auto *root = qobject_cast<QQuickItem *>(obj.data());
QVERIFY(root);
// Test that finished() is emitted for a simple top-level animation.
@@ -1696,7 +1725,8 @@ void tst_qquickanimations::replacingTransitions()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("replacingTransitions.qml"));
- QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));
+ QScopedPointer<QObject> obj(c.create());
+ auto *rect = qobject_cast<QQuickRectangle*>(obj.data());
if (!c.errors().isEmpty())
qDebug() << c.errorString();
QVERIFY(rect);
@@ -1732,13 +1762,14 @@ void tst_qquickanimations::animationJobSelfDestruction()
QQmlEngine engine;
engine.clearComponentCache();
QQmlComponent c(&engine, testFileUrl("animationJobSelfDestructionBug.qml"));
- QScopedPointer<QQuickWindow> win(qobject_cast<QQuickWindow*>(c.create()));
+ QScopedPointer<QObject> obj(c.create());
+ auto *win = qobject_cast<QQuickWindow *>(obj.data());
if (!c.errors().isEmpty())
qDebug() << c.errorString();
QVERIFY(win);
win->setTitle(QTest::currentTestFunction());
win->show();
- QVERIFY(QTest::qWaitForWindowExposed(win.data()));
+ QVERIFY(QTest::qWaitForWindowExposed(win));
QQmlTimer *timer = win->property("timer").value<QQmlTimer*>();
QVERIFY(timer);
QCOMPARE(timer->isRunning(), false);
@@ -1752,13 +1783,14 @@ void tst_qquickanimations::fastFlickingBug()
QQmlEngine engine;
engine.clearComponentCache();
QQmlComponent c(&engine, testFileUrl("fastFlickingBug.qml"));
- QScopedPointer<QQuickWindow> win(qobject_cast<QQuickWindow*>(c.create()));
+ QScopedPointer<QObject> obj(c.create());
+ auto *win = qobject_cast<QQuickWindow *>(obj.data());
if (!c.errors().isEmpty())
qDebug() << c.errorString();
QVERIFY(win);
win->setTitle(QTest::currentTestFunction());
win->show();
- QVERIFY(QTest::qWaitForWindowExposed(win.data()));
+ QVERIFY(QTest::qWaitForWindowExposed(win));
auto timer = win->property("timer").value<QQmlTimer*>();
QVERIFY(timer);
QCOMPARE(timer->isRunning(), false);
diff --git a/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
index e8b3960486..be94fca8d4 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_gridlayout.qml
@@ -1073,5 +1073,38 @@ Item {
layout[propName] = data.value
compare(layout.spy.count, 1)
}
+
+ Component {
+ id: layout_columnIsOutsideGrid_Component
+ GridLayout {
+ columns: 2
+ Item {
+ Layout.row: 0
+ Layout.column: 1
+ }
+ Item {
+ implicitWidth: 10
+ implicitHeight: 10
+ Layout.row: 0
+ Layout.column: 2
+ }
+ Item {
+ Layout.columnSpan: 2
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ }
+ }
+
+ function test_columnIsOutsideGrid()
+ {
+ ignoreWarning(/QML Item: Layout: column \(2\) should be less than the number of columns \(2\)/);
+ var layout = layout_columnIsOutsideGrid_Component.createObject(container);
+ layout.width = layout.implicitWidth
+ layout.height = layout.implicitHeight
+ waitForRendering(layout);
+ layout.destroy()
+ }
+
}
}
diff --git a/tests/auto/quick/qquicklistview/data/listview-initCurrent.qml b/tests/auto/quick/qquicklistview/data/listview-initCurrent.qml
index 8aff649a67..41d5bd3491 100644
--- a/tests/auto/quick/qquicklistview/data/listview-initCurrent.qml
+++ b/tests/auto/quick/qquicklistview/data/listview-initCurrent.qml
@@ -7,6 +7,7 @@ Rectangle {
property bool showHeader: false
property bool showFooter: false
property int currentItemChangedCount: 0
+ property string s: ""+list.currentIndex
width: 240
height: 320
diff --git a/tests/auto/quick/qquicklistview/data/moveObjectModelItemToAnotherObjectModel.qml b/tests/auto/quick/qquicklistview/data/moveObjectModelItemToAnotherObjectModel.qml
new file mode 100644
index 0000000000..ebdebeb449
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/moveObjectModelItemToAnotherObjectModel.qml
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import QtQml.Models 2.14
+
+Item {
+ id: root
+ width: 400
+ height: 400
+
+ readonly property int rectCount: 3
+ property var rectColors: ["red", "green", "blue"]
+
+ property alias listView1: listView1
+ property alias listView2: listView2
+
+ function moveRedRectToModel2() {
+ var appItem = objectModel1.get(0)
+ objectModel1.remove(0, 1)
+ objectModel2.insert(0, appItem)
+ }
+
+ function moveRedRectToModel1() {
+ var appItem = objectModel2.get(0)
+ objectModel2.remove(0, 1)
+ objectModel1.insert(0, appItem)
+ }
+
+ ObjectModel {
+ id: objectModel1
+ objectName: "objectModel1"
+
+ Component.onCompleted: {
+ for (var i = 0; i < root.rectCount; i++) {
+ var outerRect = rectComponent.createObject(null, {
+ "objectName": root.rectColors[i] + "Rect",
+ "color": root.rectColors[i]
+ })
+ objectModel1.append(outerRect)
+ }
+ }
+ }
+
+ ObjectModel {
+ id: objectModel2
+ objectName: "objectModel2"
+ }
+
+ ListView {
+ id: listView1
+ objectName: "listView1"
+ anchors.left: parent.left
+ anchors.top: parent.top
+ height: 100
+ width: 100
+ anchors.margins: 20
+ clip: true
+ cacheBuffer: 0
+ model: objectModel1
+ orientation: ListView.Horizontal
+ spacing: 20
+
+ Component.onCompleted: contentItem.objectName = "listView1ContentItem"
+ }
+
+ ListView {
+ id: listView2
+ objectName: "listView2"
+ anchors.right: parent.right
+ anchors.top: parent.top
+ height: 100
+ width: 100
+ anchors.margins: 20
+ clip: true
+ cacheBuffer: 0
+ model: objectModel2
+ orientation: ListView.Horizontal
+ spacing: 20
+
+ Component.onCompleted: contentItem.objectName = "listView2ContentItem"
+ }
+
+ Component {
+ id: rectComponent
+
+ Rectangle {
+ height: 100
+ width: 100
+ opacity: 0.2
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/reusedelegateitems.qml b/tests/auto/quick/qquicklistview/data/reusedelegateitems.qml
new file mode 100644
index 0000000000..773fb50f81
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/reusedelegateitems.qml
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.15
+
+Rectangle {
+ id: root
+ width: 640
+ height: 480
+
+ property int rows: 500
+ property int columns: 20
+ property real delegateHeight: 30
+ property real delegateWidth: 50
+
+ ListView {
+ id: list
+ anchors.fill: parent
+ anchors.margins: 10
+ objectName: "list"
+
+ model: reuseModel
+ reuseItems: true
+
+ cacheBuffer: 0
+ contentWidth: columns * delegateWidth
+ contentHeight: rows * delegateHeight
+ clip: true
+
+ property int delegatesCreatedCount: 0
+
+ delegate: Item {
+ objectName: "delegate"
+ width: list.contentWidth
+ height: delegateHeight
+
+ property int modelIndex: index
+ property int reusedCount: 0
+ property int pooledCount: 0
+ property string displayBinding: display
+
+ ListView.onPooled: pooledCount++
+ ListView.onReused: reusedCount++
+ Component.onCompleted: list.delegatesCreatedCount++
+
+ Text {
+ id: text1
+ text: display + " (Model index: " + modelIndex + ", Reused count: " + reusedCount + ")"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/qquicklistview.pro b/tests/auto/quick/qquicklistview/qquicklistview.pro
index b08fca2b1d..10edb06549 100644
--- a/tests/auto/quick/qquicklistview/qquicklistview.pro
+++ b/tests/auto/quick/qquicklistview/qquicklistview.pro
@@ -5,7 +5,8 @@ macx:CONFIG -= app_bundle
HEADERS += incrementalmodel.h \
proxytestinnermodel.h \
- randomsortmodel.h
+ randomsortmodel.h \
+ reusemodel.h
SOURCES += tst_qquicklistview.cpp \
incrementalmodel.cpp \
proxytestinnermodel.cpp \
diff --git a/tests/auto/quick/qquicklistview/reusemodel.h b/tests/auto/quick/qquicklistview/reusemodel.h
new file mode 100644
index 0000000000..21e6739384
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/reusemodel.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef REUSEMODEL_H
+#define REUSEMODEL_H
+
+#include <QAbstractListModel>
+#include <QList>
+#include <QStringList>
+
+class ReuseModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ ReuseModel(int rowCount, QObject *parent = nullptr)
+ : QAbstractListModel(parent)
+ , m_rowCount(rowCount)
+ {}
+
+ int rowCount(const QModelIndex & = QModelIndex()) const override
+ {
+ return m_rowCount;
+ }
+
+ QVariant data(const QModelIndex &index, int role) const override
+ {
+ if (!index.isValid())
+ return QVariant();
+
+ switch (role) {
+ case Qt::DisplayRole:
+ return displayStringForRow(index.row());
+ default:
+ break;
+ }
+
+ return QVariant();
+ }
+
+ QString displayStringForRow(int row) const
+ {
+ return row % 2 == 0 ?
+ QStringLiteral("Even%1").arg(row) :
+ QStringLiteral("Odd%1").arg(row);
+ }
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return {
+ {Qt::DisplayRole, "display"},
+ };
+ }
+
+private:
+ int m_rowCount;
+};
+
+#endif
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index fb5ae168e8..e527853148 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -49,6 +49,7 @@
#include "incrementalmodel.h"
#include "proxytestinnermodel.h"
#include "randomsortmodel.h"
+#include "reusemodel.h"
#include <math.h>
Q_DECLARE_METATYPE(Qt::LayoutDirection)
@@ -268,6 +269,7 @@ private slots:
void QTBUG_61269_appendDuringScrollDown_data();
void QTBUG_50097_stickyHeader_positionViewAtIndex();
void QTBUG_63974_stickyHeader_positionViewAtIndex_Contain();
+ void QTBUG_66163_setModelViewPortSizeChange();
void itemFiltered();
void releaseItems();
@@ -280,9 +282,14 @@ private slots:
void setPositionOnLayout();
void touchCancel();
void resizeAfterComponentComplete();
+ void dragOverFloatingHeaderOrFooter();
void delegateWithRequiredProperties();
+ void reuse_reuseIsOffByDefault();
+ void reuse_checkThatItemsAreReused();
+ void moveObjectModelItemToAnotherObjectModel();
+
private:
template <class T> void items(const QUrl &source);
template <class T> void changed(const QUrl &source);
@@ -2901,7 +2908,11 @@ void tst_QQuickListView::currentIndex()
// empty model should reset currentIndex to -1
QaimModel emptyModel;
+ window->rootObject()->setProperty("currentItemChangedCount", QVariant(0));
+ QVERIFY(QQmlProperty(window->rootObject(), "s").read().toString() != QLatin1String("-1"));
ctxt->setContextProperty("testModel", &emptyModel);
+ QCOMPARE(QQmlProperty(window->rootObject(), "s").read().toString(), "-1");
+ QCOMPARE(window->rootObject()->property("currentItemChangedCount").toInt(), 1);
QCOMPARE(listview->currentIndex(), -1);
delete window;
@@ -8855,6 +8866,62 @@ void tst_QQuickListView::QTBUG_63974_stickyHeader_positionViewAtIndex_Contain()
QTRY_COMPARE(listview->contentY(), -headerSize);
}
+void tst_QQuickListView::QTBUG_66163_setModelViewPortSizeChange()
+{
+ QScopedPointer<QQuickView> window(createView());
+ QQmlComponent comp(window->engine());
+ comp.setData(R"(
+ import QtQuick 2.0
+
+ Item {
+ id: root
+ width: 400
+ height: 400
+
+ ListView {
+ id: view
+ objectName: "view"
+ anchors.fill: parent
+
+ model: 4
+ highlightRangeMode: ListView.StrictlyEnforceRange
+
+ delegate: Rectangle {
+ color: index % 2 ? "green" : "orange"
+ width: parent.width
+ height: 50
+ }
+
+ populate: Transition {
+ SequentialAnimation {
+ NumberAnimation { property: "y"; from: 100; duration: 1000 }
+ }
+ }
+ }
+ }
+ )", QUrl("testData"));
+ auto root {qobject_cast<QQuickItem*>(comp.create())};
+ QVERIFY(root);
+ window->setContent(QUrl(), &comp, root);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ auto view = root->findChild<QQuickListView *>("view");
+ QVERIFY(view);
+ QVERIFY(QQuickTest::qWaitForItemPolished(view));
+ QSignalSpy spy(view, &QQuickListView::contentYChanged);
+ auto transition = view->property("populate").value<QQuickTransition*>();
+ QVERIFY(transition);
+ QQmlProperty model(view, "model");
+ QVERIFY(model.isValid());
+ model.write(5);
+ // Animations inside a Transition do not emit a finished signal
+ // so we cannot wait for them in that way
+ QTest::qWait(1100); // animation takes 1000ms, + 10% extra delay
+ /* the viewport should not have changed, thus there should not have
+ been any contentYChanged signal*/
+ QCOMPARE(spy.count(), 0);
+}
+
void tst_QQuickListView::itemFiltered()
{
QStringListModel model(QStringList() << "one" << "two" << "three" << "four" << "five" << "six");
@@ -9158,6 +9225,196 @@ void tst_QQuickListView::delegateWithRequiredProperties()
}
}
+void tst_QQuickListView::reuse_reuseIsOffByDefault()
+{
+ // Check that delegate recycling is off by default. The reason is that
+ // ListView needs to be backwards compatible with legacy applications. And
+ // when using delegate recycling, there are certain differences, like that
+ // a delegates Component.onCompleted will just be called the first time the
+ // item is created, and not when it's reused.
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("listviewtest.qml"));
+ window->resize(640, 480);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listView = findItem<QQuickListView>(window->rootObject(), "list");
+ QVERIFY(listView != nullptr);
+ QVERIFY(!listView->reuseItems());
+}
+
+void tst_QQuickListView::reuse_checkThatItemsAreReused()
+{
+ // Flick up and down one page of items. Check that this results in the
+ // delegate items being reused once.
+ // Note that this is slightly different from tableview, which will reuse the items
+ // twice during a similar down-then-up flick. The reason is that listview fills up
+ // free space in the view with items _before_ it release old items that have been
+ // flicked out. But changing this will break other auto tests (and perhaps legacy
+ // apps), so we have chosen to stick with this behavior for now.
+ QScopedPointer<QQuickView> window(createView());
+
+ ReuseModel model(100);
+ QQmlContext *ctxt = window->rootContext();
+ ctxt->setContextProperty("reuseModel", &model);
+
+ window->setSource(testFileUrl("reusedelegateitems.qml"));
+ window->resize(640, 480);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listView = findItem<QQuickListView>(window->rootObject(), "list");
+ QTRY_VERIFY(listView != nullptr);
+ const auto itemView_d = QQuickItemViewPrivate::get(listView);
+
+ QVERIFY(listView->reuseItems());
+
+ auto items = findItems<QQuickItem>(listView, "delegate");
+ const int initialItemCount = items.count();
+ QVERIFY(initialItemCount > 0);
+
+ // Sanity check that the size of the initial list of items match the count we tracked from QML
+ QCOMPARE(listView->property("delegatesCreatedCount").toInt(), initialItemCount);
+
+ // Go through all the initial items and check that they have not been reused yet
+ for (const auto item : qAsConst(items))
+ QCOMPARE(item->property("reusedCount").toInt(), 0);
+
+ // Flick one page down and count how many items we have created thus
+ // far. We expect this number to be twice as high as the initial count
+ // since we flicked one whole page.
+ const qreal delegateHeight = items.at(0)->height();
+ const qreal flickDistance = (initialItemCount * delegateHeight) + 1;
+ listView->setContentY(flickDistance);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listView));
+ const int countAfterDownFlick = listView->property("delegatesCreatedCount").toInt();
+ QCOMPARE(countAfterDownFlick, initialItemCount * 2);
+
+ // Check that the reuse pool is now populated. We expect all initial items to be pooled,
+ // except model index 0, which was never reused or released, since it's ListView.currentItem.
+ const int poolSizeAfterDownFlick = itemView_d->model->poolSize();
+ QCOMPARE(poolSizeAfterDownFlick, initialItemCount - 1);
+
+ // Go through all items and check that all model data inside the delegate
+ // have values updated according to their model index. Since model roles
+ // like 'display' are injected into the context in a special way by the
+ // QML model classes, we need to catch it through a binding instead (which is
+ // OK, since then we can also check that bindings are updated when reused).
+ items = findItems<QQuickItem>(listView, "delegate");
+ for (const auto item : qAsConst(items)) {
+ const QString display = item->property("displayBinding").toString();
+ const int modelIndex = item->property("modelIndex").toInt();
+ QVERIFY(modelIndex >= initialItemCount);
+ QCOMPARE(display, model.displayStringForRow(modelIndex));
+ }
+
+ // Flick one page up. This time there shouldn't be any new items created, so
+ // delegatesCreatedCount should remain unchanged. But while we reuse all the items
+ // in the pool during the flick, we also fill it up again with all the items that
+ // were inside the page that was flicked out.
+ listView->setContentY(0);
+ QVERIFY(QQuickTest::qWaitForItemPolished(listView));
+ const int countAfterUpFlick = listView->property("delegatesCreatedCount").toInt();
+ const int poolSizeAfterUpFlick = itemView_d->model->poolSize();
+ QCOMPARE(countAfterUpFlick, countAfterDownFlick);
+ QCOMPARE(poolSizeAfterUpFlick, initialItemCount);
+
+ // Go through all items and check that they have been reused exactly once
+ // (except for ListView.currentItem, which was never released).
+ const auto listViewCurrentItem = listView->currentItem();
+ items = findItems<QQuickItem>(listView, "delegate");
+ for (const auto item : qAsConst(items)) {
+ const int reusedCount = item->property("reusedCount").toInt();
+ if (item == listViewCurrentItem)
+ QCOMPARE(reusedCount, 0);
+ else
+ QCOMPARE(reusedCount, 1);
+ }
+
+ // Go through all items again and check that all model data inside the delegate
+ // have correct values now that they have been reused.
+ items = findItems<QQuickItem>(listView, "delegate");
+ for (const auto item : qAsConst(items)) {
+ const QString display = item->property("displayBinding").toString();
+ const int modelIndex = item->property("modelIndex").toInt();
+ QVERIFY(modelIndex < initialItemCount);
+ QCOMPARE(display, model.displayStringForRow(modelIndex));
+ }
+}
+
+void tst_QQuickListView::dragOverFloatingHeaderOrFooter() // QTBUG-74046
+{
+ QQuickView *window = getView();
+ QQuickViewTestUtil::moveMouseAway(window);
+ window->setSource(testFileUrl("qtbug63974.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = qmlobject_cast<QQuickListView *>(window->rootObject());
+ QVERIFY(listview);
+ QCOMPARE(listview->contentY(), -20);
+
+ // Drag downwards from the header: the list shouldn't move
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(10,10));
+ for (int i = 0; i < 10; ++i)
+ QTest::mouseMove(window, QPoint(10, 10 + i * 10));
+ QCOMPARE(listview->isMoving(), false);
+ QCOMPARE(listview->contentY(), -20);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier);
+
+ // Drag upwards from the footer: the list shouldn't move
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(10,190));
+ for (int i = 0; i < 10; ++i)
+ QTest::mouseMove(window, QPoint(10, 190 - i * 10));
+ QCOMPARE(listview->isMoving(), false);
+ QCOMPARE(listview->contentY(), -20);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier);
+
+ // Drag upwards from the middle: the list should move
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(10,100));
+ for (int i = 0; i < 10 && listview->contentY() == -20; ++i)
+ QTest::mouseMove(window, QPoint(10, 100 - i * 10));
+ QVERIFY(listview->isMoving());
+ QVERIFY(listview->contentY() > -20);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier);
+
+ releaseView(window);
+}
+
+void tst_QQuickListView::moveObjectModelItemToAnotherObjectModel()
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("moveObjectModelItemToAnotherObjectModel.qml"));
+ QCOMPARE(window->status(), QQuickView::Ready);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QObject *root = window->rootObject();
+ QVERIFY(root);
+
+ const QQuickListView *listView1 = root->property("listView1").value<QQuickListView*>();
+ QVERIFY(listView1);
+
+ const QQuickListView *listView2 = root->property("listView2").value<QQuickListView*>();
+ QVERIFY(listView2);
+
+ const QQuickItem *redRect = listView1->itemAtIndex(0);
+ QVERIFY(redRect);
+ QCOMPARE(redRect->objectName(), QString::fromLatin1("redRect"));
+
+ QVERIFY(QMetaObject::invokeMethod(root, "moveRedRectToModel2"));
+ QVERIFY(QQuickTest::qIsPolishScheduled(listView2));
+ QVERIFY(QQuickTest::qWaitForItemPolished(listView2));
+ QVERIFY(redRect->isVisible());
+ QVERIFY(!QQuickItemPrivate::get(redRect)->culled);
+
+ QVERIFY(QMetaObject::invokeMethod(root, "moveRedRectToModel1"));
+ QVERIFY(QQuickTest::qIsPolishScheduled(listView1));
+ QVERIFY(QQuickTest::qWaitForItemPolished(listView1));
+ QVERIFY(redRect->isVisible());
+ QVERIFY(!QQuickItemPrivate::get(redRect)->culled);
+}
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"
diff --git a/tests/auto/quick/qquickmousearea/BLACKLIST b/tests/auto/quick/qquickmousearea/BLACKLIST
deleted file mode 100644
index f2cb00225b..0000000000
--- a/tests/auto/quick/qquickmousearea/BLACKLIST
+++ /dev/null
@@ -1,4 +0,0 @@
-# QTBUG-78153
-[nestedStopAtBounds]
-opensuse-leap
-
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index 54a29dbc7f..6efa2e6b3a 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -717,7 +717,7 @@ void tst_QQuickMouseArea::updateMouseAreaPosOnClick()
QCOMPARE(mouseRegion->mouseX(), rect->x());
QCOMPARE(mouseRegion->mouseY(), rect->y());
- QMouseEvent event(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent event(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &event);
QCOMPARE(mouseRegion->mouseX(), 100.0);
@@ -745,7 +745,7 @@ void tst_QQuickMouseArea::updateMouseAreaPosOnResize()
QCOMPARE(mouseRegion->mouseX(), 0.0);
QCOMPARE(mouseRegion->mouseY(), 0.0);
- QMouseEvent event(QEvent::MouseButtonPress, rect->position().toPoint(), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent event(QEvent::MouseButtonPress, rect->position().toPoint(), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &event);
QVERIFY(!mouseRegion->property("emitPositionChanged").toBool());
@@ -774,7 +774,7 @@ void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
QQuickMouseArea *mouseArea = qobject_cast<QQuickMouseArea*>(window.rootObject()->children().first());
QVERIFY(mouseArea);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QCOMPARE(mouseArea->pressedButtons(), Qt::LeftButton);
@@ -788,7 +788,7 @@ void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
QVERIFY(!window.rootObject()->property("clicked").toBool());
QVERIFY(window.rootObject()->property("held").toBool());
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QTRY_VERIFY(window.rootObject()->property("held").toBool());
@@ -804,14 +804,14 @@ void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
QVERIFY(QTest::qWaitForWindowExposed(&window));
QVERIFY(window.rootObject() != nullptr);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QVERIFY(!window.rootObject()->property("clicked").toBool());
QTest::qWait(1000);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QVERIFY(window.rootObject()->property("clicked").toBool());
@@ -835,7 +835,7 @@ void tst_QQuickMouseArea::onMousePressRejected()
QVERIFY(!window.rootObject()->property("mr2_released").toBool());
QVERIFY(!window.rootObject()->property("mr2_canceled").toBool());
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QVERIFY(window.rootObject()->property("mr1_pressed").toBool());
@@ -847,7 +847,7 @@ void tst_QQuickMouseArea::onMousePressRejected()
QTest::qWait(200);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QVERIFY(window.rootObject()->property("mr1_released").toBool());
@@ -882,8 +882,8 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
QCOMPARE(window.rootObject()->property("clicked").toInt(), expectedClicks);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent);
@@ -900,7 +900,7 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
QCOMPARE(window.rootObject()->property("clicked").toInt(), ++expectedClicks);
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent pressEvent2(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent pressEvent2(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent2);
QTRY_VERIFY(window.rootObject()->property("pressed").toBool());
@@ -953,16 +953,16 @@ void tst_QQuickMouseArea::doubleClick()
// The sequence for a double click is:
// press, release, (click), press, double click, release
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("released").toInt(), 1);
QGuiApplication::sendEvent(&window, &pressEvent);
- pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, nullptr);
+ pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QGuiApplication::sendEvent(&window, &releaseEvent);
@@ -988,10 +988,10 @@ void tst_QQuickMouseArea::clickTwice()
QVERIFY(mouseArea);
mouseArea->setAcceptedButtons(acceptedButtons);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("pressed").toInt(), 1);
@@ -999,7 +999,7 @@ void tst_QQuickMouseArea::clickTwice()
QCOMPARE(window.rootObject()->property("clicked").toInt(), 1);
QGuiApplication::sendEvent(&window, &pressEvent);
- pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, nullptr);
+ pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QGuiApplication::sendEvent(&window, &releaseEvent);
@@ -1026,16 +1026,16 @@ void tst_QQuickMouseArea::invalidClick()
// The sequence for a double click is:
// press, release, (click), press, double click, release
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("released").toInt(), 0);
QGuiApplication::sendEvent(&window, &pressEvent);
- pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, nullptr);
+ pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QGuiApplication::sendEvent(&window, &releaseEvent);
@@ -1055,12 +1055,12 @@ void tst_QQuickMouseArea::pressedOrdering()
QCOMPARE(window.rootObject()->property("value").toString(), QLatin1String("base"));
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent);
QCOMPARE(window.rootObject()->property("value").toString(), QLatin1String("pressed"));
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, nullptr);
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("value").toString(), QLatin1String("toggled"));
@@ -1319,13 +1319,13 @@ void tst_QQuickMouseArea::hoverPropagation()
QCOMPARE(root->property("point1").toBool(), false);
QCOMPARE(root->property("point2").toBool(), false);
- QMouseEvent moveEvent(QEvent::MouseMove, QPoint(32, 32), Qt::NoButton, Qt::NoButton, nullptr);
+ QMouseEvent moveEvent(QEvent::MouseMove, QPoint(32, 32), Qt::NoButton, Qt::NoButton, {});
QGuiApplication::sendEvent(&window, &moveEvent);
QCOMPARE(root->property("point1").toBool(), true);
QCOMPARE(root->property("point2").toBool(), false);
- QMouseEvent moveEvent2(QEvent::MouseMove, QPoint(232, 32), Qt::NoButton, Qt::NoButton, nullptr);
+ QMouseEvent moveEvent2(QEvent::MouseMove, QPoint(232, 32), Qt::NoButton, Qt::NoButton, {});
QGuiApplication::sendEvent(&window, &moveEvent2);
QCOMPARE(root->property("point1").toBool(), false);
QCOMPARE(root->property("point2").toBool(), true);
@@ -1887,7 +1887,7 @@ void tst_QQuickMouseArea::nestedStopAtBounds()
QTest::mouseMove(&view, position);
axis += invert ? threshold : -threshold;
QTest::mouseMove(&view, position);
- QCOMPARE(outer->drag()->active(), true);
+ QTRY_COMPARE(outer->drag()->active(), true);
QCOMPARE(inner->drag()->active(), false);
QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index e96b892b54..c18a220996 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -31,12 +31,15 @@
#include <private/qquickmultipointtoucharea_p.h>
#include <private/qquickflickable_p.h>
#include <private/qquickmousearea_p.h>
+#include <private/qquickwindow_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtQuick/qquickview.h>
#include <QtGui/QScreen>
#include "../../shared/util.h"
#include "../shared/viewtestutil.h"
+Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
+
class tst_QQuickMultiPointTouchArea : public QQmlDataTest
{
Q_OBJECT
@@ -62,6 +65,7 @@ private slots:
void nested();
void inFlickable();
void inFlickable2();
+ void inFlickableWithPressDelay();
void inMouseArea();
void mouseAsTouchpoint();
void invisible();
@@ -812,6 +816,68 @@ void tst_QQuickMultiPointTouchArea::inFlickable2()
QTRY_VERIFY(!flickable->isMoving());
}
+void tst_QQuickMultiPointTouchArea::inFlickableWithPressDelay() // QTBUG-78818
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> window(createAndShowView("inFlickable.qml"));
+ QVERIFY(window->rootObject() != nullptr);
+ QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data());
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(window->rootObject());
+ QVERIFY(flickable != nullptr);
+ flickable->setPressDelay(50);
+
+ QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>();
+ QVERIFY(mpta != nullptr);
+ mpta->setMinimumTouchPoints(1);
+ QQuickTouchPoint *point11 = window->rootObject()->findChild<QQuickTouchPoint*>("point1");
+ QPoint p1(20,100);
+
+ // press: Flickable prevents delivery of TouchBegin, but sends mouse press instead, after the delay.
+ // MPTA handles the mouse press, and its first declared touchpoint is pressed.
+ QTest::touchEvent(window.data(), device).press(0, p1);
+ QQuickTouchUtils::flush(window.data());
+ QTRY_COMPARE(point11->pressed(), true);
+ auto pointerEvent = windowPriv->pointerEventInstance(QQuickPointerDevice::touchDevices().at(0));
+ QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta);
+
+ // release: MPTA receives TouchEnd (which is asymmetric with mouse press); does NOT emit canceled.
+ QTest::touchEvent(window.data(), device).release(0, p1);
+ QQuickTouchUtils::flush(window.data());
+ QCOMPARE(flickable->property("cancelCount").toInt(), 0);
+
+ // press again
+ QTest::touchEvent(window.data(), device).press(0, p1);
+ QQuickTouchUtils::flush(window.data());
+ QTRY_COMPARE(point11->pressed(), true); // wait until pressDelay exceeded
+ QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta);
+
+ // drag past the threshold: Flickable takes over the grab, MPTA gets touchUngrab and is no longer pressed
+ int i = 0;
+ for (; i < 10 && window->mouseGrabberItem() != flickable; ++i) {
+ p1 += QPoint(0,dragThreshold);
+ QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
+ }
+ QCOMPARE(window->mouseGrabberItem(), flickable);
+ qCDebug(lcTests, "Flickable stole grab from MPTA after %d moves", i);
+ QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), flickable);
+ QCOMPARE(point11->pressed(), false);
+ QVERIFY(flickable->property("cancelCount").toInt() > 0); // actually 2 because 2 touchPoints are declared... but only one was really cancelled
+
+ // drag a little more and the Flickable moves
+ p1 += QPoint(0,1);
+ QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
+ QVERIFY(flickable->contentY() < 0);
+ QVERIFY(flickable->isMoving());
+
+ QTest::touchEvent(window.data(), device).release(0, p1);
+ QQuickTouchUtils::flush(window.data());
+
+ QTRY_VERIFY(!flickable->isMoving());
+}
+
// QTBUG-31047
void tst_QQuickMultiPointTouchArea::inMouseArea()
{
diff --git a/tests/auto/quick/qquickpathview/data/ungrabNestedinFlickable.qml b/tests/auto/quick/qquickpathview/data/ungrabNestedinFlickable.qml
new file mode 100644
index 0000000000..4258d8fef4
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/ungrabNestedinFlickable.qml
@@ -0,0 +1,75 @@
+import QtQuick 2.9
+
+Flickable {
+ width: 480
+ height: 480
+ contentX: 0
+ contentWidth: width
+ contentHeight: height
+ leftMargin: 408
+ rightMargin: 36
+ maximumFlickVelocity: 0
+ boundsBehavior: Flickable.StopAtBounds
+ flickableDirection: Flickable.HorizontalFlick
+
+ PathView {
+ id:pathView
+ objectName: "pathView"
+
+ property int countclick: 0
+
+ readonly property int contentsWidth: 348
+ readonly property int contentsHeight: 480
+
+ width: contentsWidth
+ height: contentsHeight
+
+ interactive: true
+
+ cacheItemCount: 10
+ currentIndex: 2
+ pathItemCount: 4
+ highlightMoveDuration: 300
+ highlightRangeMode : PathView.StrictlyEnforceRange
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+ snapMode : PathView.SnapOneItem
+
+ path: Path {
+ startX: pathView.contentsWidth / 2 - 800
+ startY: pathView.contentsHeight / 2 - 800
+
+ PathArc {
+ x: pathView.contentsWidth / 2 - 800
+ y: pathView.contentsHeight / 2 + 800
+ radiusX: 800
+ radiusY: 800
+ direction: PathArc.Clockwise
+ }
+ }
+
+ model: ListModel {
+ ListElement { objectName:"aqua"; name: "aqua" ;mycolor:"aqua"}
+ ListElement { objectName:"blue"; name: "blue" ;mycolor:"blue"}
+ ListElement { objectName:"blueviolet"; name: "blueviolet" ;mycolor:"blueviolet"}
+ ListElement { objectName:"brown"; name: "brown" ;mycolor:"brown"}
+ ListElement { objectName:"chartreuse"; name: "chartreuse" ;mycolor:"chartreuse"}
+ }
+
+ delegate: Item {
+ id: revolveritem
+ objectName: model.objectName
+
+ width: pathView.contentsWidth
+ height: pathView.contentsHeight
+
+ Rectangle
+ {
+ id:myRectangle
+ color: mycolor
+ width: pathView.contentsWidth -20
+ height: pathView.contentsHeight -20
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index a8e847a5c7..8ba09fa509 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -140,6 +140,7 @@ private slots:
void cacheItemCount();
void changePathDuringRefill();
void nestedinFlickable();
+ void ungrabNestedinFlickable();
void flickableDelegate();
void jsArrayChange();
void qtbug37815();
@@ -2413,6 +2414,40 @@ void tst_QQuickPathView::nestedinFlickable()
}
+void tst_QQuickPathView::ungrabNestedinFlickable()
+{
+ QScopedPointer<QQuickView> window(createView());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+ window->setSource(testFileUrl("ungrabNestedinFlickable.qml"));
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QCOMPARE(window.data(), qGuiApp->focusWindow());
+
+ QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "pathView");
+ QVERIFY(pathview != nullptr);
+
+ double pathviewOffsetBefore = pathview->offset();
+
+ // Drag slowly upwards so that it does not flick, release, and let it start snapping back
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(200, 350));
+ for (int i = 0; i < 4; ++i)
+ QTest::mouseMove(window.data(), QPoint(200, 325 - i * 25), 500);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(200, 250));
+ QCOMPARE(pathview->isMoving(), true);
+
+ // Press again to stop moving
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(200, 350));
+ QTRY_COMPARE(pathview->isMoving(), false);
+
+ // Cancel the grab, wait for movement to stop, and expect it to snap to
+ // the nearest delegate, which should be at the same offset as where we started
+ pathview->ungrabMouse();
+ QTRY_COMPARE(pathview->offset(), pathviewOffsetBefore);
+ QCOMPARE(pathview->isMoving(), false);
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(200, 350));
+}
+
void tst_QQuickPathView::flickableDelegate()
{
QScopedPointer<QQuickView> window(createView());
diff --git a/tests/auto/quick/qquickpixmapcache/data/asynchronousNoCache.qml b/tests/auto/quick/qquickpixmapcache/data/asynchronousNoCache.qml
new file mode 100644
index 0000000000..5331be5a15
--- /dev/null
+++ b/tests/auto/quick/qquickpixmapcache/data/asynchronousNoCache.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.12
+
+Item {
+ visible: true
+ width: 640
+ height: 480
+
+ Image{
+ asynchronous: true
+ anchors.fill: parent
+ fillMode: Image.Stretch
+ source: "exists1.png"
+ cache: false
+ sourceSize.width: width/2
+ sourceSize.height: height/2
+ }
+}
diff --git a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
index bffaaf7c6e..88cf6ece96 100644
--- a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
+++ b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
@@ -30,6 +30,7 @@
#include <QtQuick/private/qquickpixmapcache_p.h>
#include <QtQml/qqmlengine.h>
#include <QtQuick/qquickimageprovider.h>
+#include <QtQml/QQmlComponent>
#include <QNetworkReply>
#include "../../shared/util.h"
#include "testhttpserver.h"
@@ -62,6 +63,7 @@ private slots:
#endif
void lockingCrash();
void uncached();
+ void asynchronousNoCache();
#if PIXMAP_DATA_LEAK_TEST
void dataLeak();
#endif
@@ -431,7 +433,7 @@ void tst_qquickpixmapcache::uncached()
QUrl url("image://mypixmaps/mypix");
{
QQuickPixmap p;
- p.load(&engine, url, nullptr);
+ p.load(&engine, url, QQuickPixmap::Options{});
QImage img = p.image();
QCOMPARE(img.pixel(0,0), qRgb(255, 0, 0));
}
@@ -440,7 +442,7 @@ void tst_qquickpixmapcache::uncached()
MyPixmapProvider::fillColor = qRgb(0, 255, 0);
{
QQuickPixmap p;
- p.load(&engine, url, nullptr);
+ p.load(&engine, url, QQuickPixmap::Options{});
QImage img = p.image();
QCOMPARE(img.pixel(0,0), qRgb(0, 255, 0));
}
@@ -458,7 +460,7 @@ void tst_qquickpixmapcache::uncached()
MyPixmapProvider::fillColor = qRgb(255, 0, 255);
{
QQuickPixmap p;
- p.load(&engine, url, nullptr);
+ p.load(&engine, url, QQuickPixmap::Options{});
QImage img = p.image();
QCOMPARE(img.pixel(0,0), qRgb(255, 0, 255));
}
@@ -473,6 +475,13 @@ void tst_qquickpixmapcache::uncached()
}
}
+void tst_qquickpixmapcache::asynchronousNoCache()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("asynchronousNoCache.qml"));
+ QScopedPointer<QObject> root {component.create()}; // should not crash
+}
+
#if PIXMAP_DATA_LEAK_TEST
// This test should not be enabled by default as it
diff --git a/tests/auto/quick/qquickrepeater/data/contextProperty.qml b/tests/auto/quick/qquickrepeater/data/contextProperty.qml
new file mode 100644
index 0000000000..44e76f474f
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/contextProperty.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.14
+
+Item {
+ Column {
+ Repeater {
+ model: ["apples", "oranges", "pears"]
+ Text {
+ id: txt
+ text: modelData + index
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
index ccfef63902..33b8742170 100644
--- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
+++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
@@ -81,6 +81,7 @@ private slots:
void package();
void ownership();
void requiredProperties();
+ void contextProperties();
};
class TestObject : public QObject
@@ -1131,6 +1132,29 @@ void tst_QQuickRepeater::requiredProperties()
QVERIFY(o);
}
+void tst_QQuickRepeater::contextProperties()
+{
+ QQmlEngine engine;
+
+ QQmlComponent component(&engine, testFileUrl("contextProperty.qml"));
+ QScopedPointer<QObject> o {component.create()};
+ QVERIFY(o);
+
+ auto *root = qobject_cast<QQuickItem *>(o.get());
+ QVERIFY(root);
+
+ QQueue<QQuickItem *> items;
+ items.append(root);
+
+ while (!items.isEmpty()) {
+ QQuickItem *item = items.dequeue();
+ QQmlContextData *data = QQmlContextData::get(qmlContext(item));
+ QVERIFY(!data->hasExtraObject);
+ for (QQuickItem *child : item->childItems())
+ items.enqueue(child);
+ }
+}
+
QTEST_MAIN(tst_QQuickRepeater)
#include "tst_qquickrepeater.moc"
diff --git a/tests/auto/quick/qquicktableview/data/checkalwaysemit.qml b/tests/auto/quick/qquicktableview/data/checkalwaysemit.qml
new file mode 100644
index 0000000000..33db6f6d02
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/checkalwaysemit.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+ property real delegateWidth: 100
+ property real delegateHeight: 50
+ property Component delegate: tableViewDelegate
+ property bool delegateParentSetBeforeCompleted: false
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ anchors.margins: 1
+ clip: true
+ delegate: tableViewDelegate
+ columnSpacing: 1
+ rowSpacing: 1
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ objectName: "tableViewDelegate"
+ implicitWidth: delegateWidth
+ implicitHeight: delegateHeight
+ color: "lightgray"
+ border.width: 1
+
+ property string modelDataFromIndex: tableView.model.dataFromSerializedIndex(index)
+ property string modelDataBinding: modelData
+
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ }
+
+ Component.onCompleted: {
+ delegateParentSetBeforeCompleted = parent != null;
+ }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/replaceModelTableView.qml b/tests/auto/quick/qquicktableview/data/replaceModelTableView.qml
new file mode 100644
index 0000000000..cc109bb469
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/replaceModelTableView.qml
@@ -0,0 +1,56 @@
+import QtQuick 2.14
+import QtQml.Models 2.14
+
+Item {
+ id: root
+ visible: true
+ width: 640
+ height: 480
+
+ property alias tableView: tv
+ property alias objectModel: om
+ property alias listModel: lm
+ property alias delegateModel: dm
+
+ ObjectModel {
+ id: om
+ Rectangle { implicitHeight: 30; implicitWidth: 80; color: "red" }
+ Rectangle { implicitHeight: 30; implicitWidth: 80; color: "green" }
+ Rectangle { implicitHeight: 30; implicitWidth: 80; color: "blue" }
+ }
+
+ ListModel {
+ id: lm
+ ListElement { name: "1" }
+ ListElement { name: "44"}
+ }
+
+ DelegateModel {
+ id: dm
+ model: ListModel {
+ ListElement { name: "Apple" }
+ ListElement { name: "Orange" }
+ }
+ delegate: Rectangle {
+ implicitHeight: 25
+ implicitWidth: 100
+ Text { text: "Name: " + name}
+ }
+ }
+ TableView {
+ id: tv
+ visible: true
+ anchors.fill: parent
+
+ delegate: Rectangle {
+ id: dlg
+ implicitWidth: 40
+ implicitHeight: 20
+ color: "red"
+ Text {
+ text: qsTr("name: " + name)
+ }
+ border.color: "green"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktableview/qquicktableview.pro b/tests/auto/quick/qquicktableview/qquicktableview.pro
index da0c0b01d0..735c728fc6 100644
--- a/tests/auto/quick/qquicktableview/qquicktableview.pro
+++ b/tests/auto/quick/qquicktableview/qquicktableview.pro
@@ -13,3 +13,5 @@ TESTDATA = data/*
QT += core-private gui-private qml-private quick-private testlib qmlmodels-private
+DISTFILES +=
+
diff --git a/tests/auto/quick/qquicktableview/testmodel.h b/tests/auto/quick/qquicktableview/testmodel.h
index 50f434019e..2697b1e801 100644
--- a/tests/auto/quick/qquicktableview/testmodel.h
+++ b/tests/auto/quick/qquicktableview/testmodel.h
@@ -46,6 +46,13 @@ public:
, m_columns(columns)
{}
+ TestModel(int rows, int columns, bool dataCanBeFetched, QObject *parent = nullptr)
+ : QAbstractTableModel(parent)
+ , m_rows(rows)
+ , m_columns(columns)
+ , m_dataCanBeFetched(dataCanBeFetched)
+ {}
+
int rowCount(const QModelIndex & = QModelIndex()) const override { return m_rows; }
void setRowCount(int count) { beginResetModel(); m_rows = count; emit rowCountChanged(); endResetModel(); }
@@ -63,6 +70,13 @@ public:
return QStringLiteral("%1").arg(index.row());
}
+ Q_INVOKABLE QVariant dataFromSerializedIndex(int index) const
+ {
+ if (modelData.contains(index))
+ return modelData.value(index);
+ return QString();
+ }
+
QHash<int, QByteArray> roleNames() const override
{
return { {Qt::DisplayRole, "display"} };
@@ -102,6 +116,12 @@ public:
beginRemoveRows(parent, row, row + count - 1);
m_rows -= count;
+ for (int c = 0; c < m_columns; ++c) {
+ for (int r = 0; r < count; ++r) {
+ const int serializedIndex = (row + r) + (c * m_rows);
+ modelData.remove(serializedIndex);
+ }
+ }
endRemoveRows();
return true;
}
@@ -128,6 +148,12 @@ public:
return true;
}
+ bool canFetchMore(const QModelIndex &parent) const override
+ {
+ Q_UNUSED(parent)
+ return m_dataCanBeFetched;
+ }
+
void swapRows(int row1, int row2)
{
layoutAboutToBeChanged();
@@ -139,6 +165,12 @@ public:
layoutChanged();
}
+ void fetchMore(const QModelIndex &parent) override
+ {
+ Q_UNUSED(parent)
+ addRow(m_rows - 1);
+ }
+
void clear() {
beginResetModel();
m_rows = 0;
@@ -159,6 +191,7 @@ signals:
private:
int m_rows = 0;
int m_columns = 0;
+ bool m_dataCanBeFetched = false;
QHash<int, QString> modelData;
};
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 230dcc9446..ef39a91a65 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -60,7 +60,7 @@ Q_DECLARE_METATYPE(QMarginsF);
auto PROPNAME = view->rootObject()->property(#PROPNAME).value<QQuickTableView *>(); \
QVERIFY(PROPNAME); \
auto PROPNAME ## Private = QQuickTableViewPrivate::get(PROPNAME); \
- Q_UNUSED(PROPNAME ## Private)
+ Q_UNUSED(PROPNAME ## Private) void()
#define LOAD_TABLEVIEW(fileName) \
view->setSource(testFileUrl(fileName)); \
@@ -120,6 +120,7 @@ private slots:
void checkRowHeightProviderNotCallable();
void checkForceLayoutFunction();
void checkForceLayoutEndUpDoingALayout();
+ void checkForceLayoutDuringModelChange();
void checkContentWidthAndHeight();
void checkPageFlicking();
void checkExplicitContentWidthAndHeight();
@@ -159,6 +160,7 @@ private slots:
void checkContextPropertiesQQmlListProperyModel_data();
void checkContextPropertiesQQmlListProperyModel();
void checkRowAndColumnChangedButNotIndex();
+ void checkThatWeAlwaysEmitChangedUponItemReused();
void checkChangingModelFromDelegate();
void checkRebuildViewportOnly();
void useDelegateChooserWithoutDefault();
@@ -174,6 +176,8 @@ private slots:
void checkSyncView_connect_late_data();
void checkSyncView_connect_late();
void delegateWithRequiredProperties();
+ void checkThatFetchMoreIsCalledWhenScrolledToTheEndOfTable();
+ void replaceModel();
};
tst_QQuickTableView::tst_QQuickTableView()
@@ -390,7 +394,7 @@ void tst_QQuickTableView::checkColumnWidthProviderInvalidReturnValues()
tableView->setModel(model);
- QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*implicitHeight.*zero"));
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*implicit.*zero"));
WAIT_UNTIL_POLISHED;
@@ -487,7 +491,7 @@ void tst_QQuickTableView::checkRowHeightProviderInvalidReturnValues()
tableView->setModel(model);
- QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*implicitHeight.*zero"));
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*implicit.*zero"));
WAIT_UNTIL_POLISHED;
@@ -588,6 +592,29 @@ void tst_QQuickTableView::checkForceLayoutEndUpDoingALayout()
QCOMPARE(fxItem->item->height(), newDelegateSize);
}
+void tst_QQuickTableView::checkForceLayoutDuringModelChange()
+{
+ // Check that TableView doesn't assert if we call
+ // forceLayout() in the middle of a model change.
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const int initialRowCount = 10;
+ TestModel model(initialRowCount, 10);
+ tableView->setModel(QVariant::fromValue(&model));
+
+ connect(&model, &QAbstractItemModel::rowsInserted, [=](){
+ QCOMPARE(tableView->rows(), initialRowCount);
+ tableView->forceLayout();
+ QCOMPARE(tableView->rows(), initialRowCount + 1);
+ });
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableView->rows(), initialRowCount);
+ model.addRow(0);
+ QCOMPARE(tableView->rows(), initialRowCount + 1);
+}
+
void tst_QQuickTableView::checkContentWidthAndHeight()
{
// Check that contentWidth/Height reports the correct size of the
@@ -2060,6 +2087,41 @@ void tst_QQuickTableView::checkRowAndColumnChangedButNotIndex()
QCOMPARE(contextColumn, 1);
}
+void tst_QQuickTableView::checkThatWeAlwaysEmitChangedUponItemReused()
+{
+ // Check that we always emit changes to index when we reuse an item, even
+ // if it doesn't change. This is needed since the model can have changed
+ // row or column count while the item was in the pool, which means that
+ // any data referred to by the index property inside the delegate
+ // will change too. So we need to refresh any bindings to index.
+ // QTBUG-79209
+ LOAD_TABLEVIEW("checkalwaysemit.qml");
+
+ TestModel model(1, 1);
+ tableView->setModel(QVariant::fromValue(&model));
+ model.setModelData(QPoint(0, 0), QSize(1, 1), "old value");
+
+ WAIT_UNTIL_POLISHED;
+
+ const auto reuseItem = tableViewPrivate->loadedTableItem(QPoint(0, 0))->item;
+ const auto context = qmlContext(reuseItem.data());
+
+ // Remove the cell/row that has "old value" as model data, and
+ // add a new one right after. The new cell will have the same
+ // index, but with no model data assigned.
+ // This change will not be detected by items in the pool. But since
+ // we emit indexChanged when the item is reused, it will be updated then.
+ model.removeRow(0);
+ model.insertRow(0);
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(context->contextProperty("index").toInt(), 0);
+ QCOMPARE(context->contextProperty("row").toInt(), 0);
+ QCOMPARE(context->contextProperty("column").toInt(), 0);
+ QCOMPARE(context->contextProperty("modelDataFromIndex").toString(), "");
+}
+
void tst_QQuickTableView::checkChangingModelFromDelegate()
{
// Check that we don't restart a rebuild of the table
@@ -2617,7 +2679,27 @@ void tst_QQuickTableView::checkSyncView_connect_late()
QCOMPARE(tableViewVPrivate->loadedTableOuterRect.left(), 0);
QCOMPARE(tableViewHVPrivate->loadedTableOuterRect, tableViewPrivate->loadedTableOuterRect);
+}
+
+void tst_QQuickTableView::checkThatFetchMoreIsCalledWhenScrolledToTheEndOfTable()
+{
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ auto model = TestModelAsVariant(5, 5, true);
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableView->rows(), 5);
+ QCOMPARE(tableView->columns(), 5);
+ // Flick table out of view on top
+ tableView->setContentX(0);
+ tableView->setContentY(-tableView->height() - 10);
+ tableView->polish();
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableView->rows(), 6);
+ QCOMPARE(tableView->columns(), 5);
}
void tst_QQuickTableView::delegateWithRequiredProperties()
@@ -2648,7 +2730,7 @@ void tst_QQuickTableView::delegateWithRequiredProperties()
auto model = QVariant::fromValue(QSharedPointer<MyTable>(new MyTable));
{
QTest::ignoreMessage(QtMsgType::QtInfoMsg, "success");
- LOAD_TABLEVIEW("delegateWithRequired.qml")
+ LOAD_TABLEVIEW("delegateWithRequired.qml");
QVERIFY(tableView);
tableView->setModel(model);
WAIT_UNTIL_POLISHED;
@@ -2656,7 +2738,7 @@ void tst_QQuickTableView::delegateWithRequiredProperties()
}
{
QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression(R"|(TableView: failed loading index: \d)|"));
- LOAD_TABLEVIEW("delegatewithRequiredUnset.qml")
+ LOAD_TABLEVIEW("delegatewithRequiredUnset.qml");
QVERIFY(tableView);
tableView->setModel(model);
WAIT_UNTIL_POLISHED;
@@ -2664,6 +2746,28 @@ void tst_QQuickTableView::delegateWithRequiredProperties()
}
}
+void tst_QQuickTableView::replaceModel()
+{
+ LOAD_TABLEVIEW("replaceModelTableView.qml");
+
+ const auto objectModel = view->rootObject()->property("objectModel");
+ const auto listModel = view->rootObject()->property("listModel");
+ const auto delegateModel = view->rootObject()->property("delegateModel");
+
+ tableView->setModel(listModel);
+ QTRY_COMPARE(tableView->rows(), 2);
+ tableView->setModel(objectModel);
+ QTRY_COMPARE(tableView->rows(), 3);
+ tableView->setModel(delegateModel);
+ QTRY_COMPARE(tableView->rows(), 2);
+ tableView->setModel(listModel);
+ QTRY_COMPARE(tableView->rows(), 2);
+ tableView->setModel(QVariant());
+ QTRY_COMPARE(tableView->rows(), 0);
+ QCOMPARE(tableView->contentWidth(), 0);
+ QCOMPARE(tableView->contentHeight(), 0);
+}
+
QTEST_MAIN(tst_QQuickTableView)
#include "tst_qquicktableview.moc"
diff --git a/tests/auto/quick/qquicktextedit/BLACKLIST b/tests/auto/quick/qquicktextedit/BLACKLIST
index 9df9c7d75a..36c7f0042f 100644
--- a/tests/auto/quick/qquicktextedit/BLACKLIST
+++ b/tests/auto/quick/qquicktextedit/BLACKLIST
@@ -1,2 +1,6 @@
[mouseSelection]
opensuse-leap
+
+# QTBUG-78846
+[mouseSelectionMode]
+opensuse-leap
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index d03441e052..85342d4c1e 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -226,7 +226,7 @@ private:
void simulateKeys(QWindow *window, const QKeySequence &sequence);
#endif
- void simulateKey(QWindow *, int key, Qt::KeyboardModifiers modifiers = nullptr);
+ void simulateKey(QWindow *, int key, Qt::KeyboardModifiers modifiers = {});
QStringList standard;
QStringList richText;
@@ -1389,7 +1389,7 @@ void tst_qquicktextedit::focusOnPress()
QCOMPARE(textEditObject->hasActiveFocus(), false);
QPoint centerPoint(window.width()/2, window.height()/2);
- Qt::KeyboardModifiers noModifiers = nullptr;
+ Qt::KeyboardModifiers noModifiers;
QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(textEditObject->hasFocus(), true);
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 1d12121a6f..2e64c80b85 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -2073,11 +2073,15 @@ void tst_qquicktextinput::validators()
QTest::keyPress(&window, Qt::Key_Comma);
QTest::keyRelease(&window, Qt::Key_Comma, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12,"));
- QCOMPARE(dblInput->hasAcceptableInput(), true);
- QTest::keyPress(&window, Qt::Key_1);
- QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
- QTRY_COMPARE(dblInput->text(), QLatin1String("12,"));
- QCOMPARE(dblInput->hasAcceptableInput(), true);
+ int extraSignals = 2;
+ if (dblInput->hasAcceptableInput()) {
+ // TODO: old behavior of QDoubleValidator - remove when merged from qtbase
+ QTest::keyPress(&window, Qt::Key_1);
+ QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
+ QTRY_COMPARE(dblInput->text(), QLatin1String("12,"));
+ QCOMPARE(dblInput->hasAcceptableInput(), true);
+ extraSignals = 0;
+ }
dblValidator->setLocaleName(deLocale.name());
QCOMPARE(dblInput->hasAcceptableInput(), true);
QTest::keyPress(&window, Qt::Key_1);
@@ -2106,84 +2110,84 @@ void tst_qquicktextinput::validators()
QTRY_COMPARE(dblInput->text(), QLatin1String("12."));
QCOMPARE(dblInput->hasAcceptableInput(), true);
QCOMPARE(dblInput->property("acceptable").toBool(), true);
- QCOMPARE(dblSpy.count(), 1);
+ QCOMPARE(dblSpy.count(), 1 + extraSignals);
QTest::keyPress(&window, Qt::Key_1);
QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12.1"));
QCOMPARE(dblInput->hasAcceptableInput(), true);
QCOMPARE(dblInput->property("acceptable").toBool(), true);
- QCOMPARE(dblSpy.count(), 1);
+ QCOMPARE(dblSpy.count(), 1 + extraSignals);
QTest::keyPress(&window, Qt::Key_1);
QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
QCOMPARE(dblInput->hasAcceptableInput(), true);
QCOMPARE(dblInput->property("acceptable").toBool(), true);
- QCOMPARE(dblSpy.count(), 1);
+ QCOMPARE(dblSpy.count(), 1 + extraSignals);
QTest::keyPress(&window, Qt::Key_1);
QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
QCOMPARE(dblInput->hasAcceptableInput(), true);
QCOMPARE(dblInput->property("acceptable").toBool(), true);
- QCOMPARE(dblSpy.count(), 1);
+ QCOMPARE(dblSpy.count(), 1 + extraSignals);
// Ensure the validator doesn't prevent characters being removed.
dblInput->setValidator(intInput->validator());
QCOMPARE(dblInput->text(), QLatin1String("12.11"));
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
QTest::keyPress(&window, Qt::Key_Backspace);
QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12.1"));
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
// Once unacceptable input is in anything goes until it reaches an acceptable state again.
QTest::keyPress(&window, Qt::Key_1);
QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
QCOMPARE(dblInput->hasAcceptableInput(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
QTest::keyPress(&window, Qt::Key_Backspace);
QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12.1"));
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
QTest::keyPress(&window, Qt::Key_Backspace);
QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12."));
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
QTest::keyPress(&window, Qt::Key_Backspace);
QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("12"));
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
QTest::keyPress(&window, Qt::Key_Backspace);
QTest::keyRelease(&window, Qt::Key_Backspace, Qt::NoModifier);
QTRY_COMPARE(dblInput->text(), QLatin1String("1"));
QCOMPARE(dblInput->hasAcceptableInput(), false);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
- QCOMPARE(dblSpy.count(), 2);
+ QCOMPARE(dblSpy.count(), 2 + extraSignals);
QTest::keyPress(&window, Qt::Key_1);
QTest::keyRelease(&window, Qt::Key_1, Qt::NoModifier);
QCOMPARE(dblInput->text(), QLatin1String("11"));
QCOMPARE(dblInput->property("acceptable").toBool(), true);
QCOMPARE(dblInput->hasAcceptableInput(), true);
- QCOMPARE(dblSpy.count(), 3);
+ QCOMPARE(dblSpy.count(), 3 + extraSignals);
// Changing the validator properties will re-evaluate whether the input is acceptable.
intValidator->setTop(10);
QCOMPARE(dblInput->property("acceptable").toBool(), false);
QCOMPARE(dblInput->hasAcceptableInput(), false);
- QCOMPARE(dblSpy.count(), 4);
+ QCOMPARE(dblSpy.count(), 4 + extraSignals);
intValidator->setTop(12);
QCOMPARE(dblInput->property("acceptable").toBool(), true);
QCOMPARE(dblInput->hasAcceptableInput(), true);
- QCOMPARE(dblSpy.count(), 5);
+ QCOMPARE(dblSpy.count(), 5 + extraSignals);
QQuickTextInput *strInput = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(window.rootObject()->property("strInput")));
QVERIFY(strInput);
@@ -6408,8 +6412,20 @@ void tst_qquicktextinput::setInputMask_data()
QTest::newRow(QString(insert_mode + "blank=input").toLatin1())
<< QString("9999;0")
<< QString("2004")
+ << QString("24")
<< QString("2004")
- << QString("2004")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "any_opt").toLatin1())
+ << QString("@xxx@")
+ << QString("@A C@")
+ << QString("@AC@")
+ << QString("@A C@")
+ << bool(insert_text);
+ QTest::newRow(QString(insert_mode + "any_req").toLatin1())
+ << QString("@XXX@")
+ << QString("@A C@")
+ << QString("@AC@@")
+ << QString("@AC@@")
<< bool(insert_text);
}
}
@@ -6428,6 +6444,14 @@ void tst_qquicktextinput::setInputMask()
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
QVERIFY(textInput != nullptr);
+ // [QTBUG-80190] check if setting the same property value again doesn't emit an
+ // inputMaskChanged signal
+ QString unescapedMask = mask; // mask is escaped, because '\' is also escape in a JS string
+ unescapedMask.replace(QLatin1String("\\\\"), QLatin1String("\\")); // simple unescape
+ QSignalSpy spy(textInput, SIGNAL(inputMaskChanged(const QString &)));
+ textInput->setInputMask(unescapedMask);
+ QCOMPARE(spy.count(), 0);
+
// then either insert using insert() or keyboard
if (insert_text) {
textInput->insert(0, input);
@@ -6444,9 +6468,6 @@ void tst_qquicktextinput::setInputMask()
QTest::keyClick(&window, input.at(i).toLatin1());
}
- QEXPECT_FAIL( "keys blank=input", "To eat blanks or not? Known issue. Task 43172", Abort);
- QEXPECT_FAIL( "insert blank=input", "To eat blanks or not? Known issue. Task 43172", Abort);
-
QCOMPARE(textInput->text(), expectedText);
QCOMPARE(textInput->displayText(), expectedDisplay);
}
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/filterGroupForDelegate.qml b/tests/auto/quick/qquickvisualdatamodel/data/filterGroupForDelegate.qml
new file mode 100644
index 0000000000..d72ca51d7f
--- /dev/null
+++ b/tests/auto/quick/qquickvisualdatamodel/data/filterGroupForDelegate.qml
@@ -0,0 +1,77 @@
+import QtQml.Models 2.12
+import Qt.labs.qmlmodels 1.0
+import QtQuick 2.12
+
+Item {
+ id: root
+ width: 200
+ height: 320
+
+ property int numChanges: 0
+ property bool ok: true
+
+ DelegateModel {
+ id: theModel
+
+ model: ListModel {
+ ListElement { role: "section" }
+ ListElement { role: "item" }
+ ListElement { role: "section" }
+ ListElement { role: "item" }
+ ListElement { role: "section" }
+ ListElement { role: "item" }
+ ListElement { role: "item" }
+ ListElement { role: "item" }
+ }
+
+ filterOnGroup: "expanded"
+ groups: DelegateModelGroup {
+ name: "expanded"
+ }
+
+ delegate: DelegateChooser {
+ role: "role"
+
+ DelegateChoice {
+ roleValue: "section"
+ Text {
+ text: "+ Section " + index
+
+ Timer {
+ interval: (index + 10)
+ repeat: true
+ running: true
+ onTriggered: {
+ ++ root.numChanges;
+ if (model.role !== "section") {
+ root.ok = false;
+ console.warn("wrong!", root.numChanges);
+ }
+ let i = parent.DelegateModel.itemsIndex + 1;
+ for (; i < theModel.items.count; ++i) {
+ let item = theModel.items.get(i);
+ if (item.model.role === "section")
+ break;
+ item.inExpanded = !item.inExpanded;
+ }
+ }
+ }
+ }
+ }
+
+ DelegateChoice {
+ roleValue: "item"
+ Text {
+ text: "Item " + index
+ }
+ }
+ }
+
+ Component.onCompleted: items.addGroups(0, items.count, ["expanded"])
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: theModel
+ }
+}
diff --git a/tests/auto/quick/qquickvisualdatamodel/data/readFromProxyObject.qml b/tests/auto/quick/qquickvisualdatamodel/data/readFromProxyObject.qml
new file mode 100644
index 0000000000..3983c707a1
--- /dev/null
+++ b/tests/auto/quick/qquickvisualdatamodel/data/readFromProxyObject.qml
@@ -0,0 +1,23 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ id: window
+ width: 200
+ height: 200
+ color: "red"
+ visible: true
+ Repeater {
+ model: Qt.application.screens
+ Text {
+ required property string name
+ required property int virtualX
+ required property int virtualY
+
+ text: name + virtualX + ", " + virtualY
+ Component.onCompleted: window.name = name
+ }
+ }
+
+ property string name: "wrong"
+}
diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
index fe56cad018..66069c48cb 100644
--- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
+++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
@@ -433,6 +433,8 @@ private slots:
void invalidContext();
void externalManagedModel();
void delegateModelChangeDelegate();
+ void checkFilterGroupForDelegate();
+ void readFromProxyObject();
private:
template <int N> void groups_verify(
@@ -4342,6 +4344,34 @@ void tst_qquickvisualdatamodel::delegateModelChangeDelegate()
QCOMPARE(visualModel->count(), 3);
}
+void tst_qquickvisualdatamodel::checkFilterGroupForDelegate()
+{
+ QQuickView view;
+ view.setSource(testFileUrl("filterGroupForDelegate.qml"));
+ view.show();
+
+ QQuickItem *obj = view.rootObject();
+ QVERIFY(obj);
+
+ QTRY_VERIFY(obj->property("numChanges").toInt() > 100);
+ QVERIFY(obj->property("ok").toBool());
+}
+
+void tst_qquickvisualdatamodel::readFromProxyObject()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("readFromProxyObject.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj);
+
+ auto *window = qobject_cast<QQuickWindow *>(obj.get());
+ QVERIFY(window);
+
+ QCOMPARE(window->property("name").type(), QMetaType::QString);
+ QTRY_VERIFY(window->property("name").toString() != QLatin1String("wrong"));
+}
+
QTEST_MAIN(tst_qquickvisualdatamodel)
#include "tst_qquickvisualdatamodel.moc"
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index 7faa621e86..5b6b11c746 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -73,7 +73,7 @@ static QTouchEvent::TouchPoint makeTouchPoint(QQuickItem *item, const QPointF &p
return tp;
}
-static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states = nullptr,
+static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states = {},
const QList<QTouchEvent::TouchPoint>& touchPoints = QList<QTouchEvent::TouchPoint>())
{
TouchEventData d = { type, nullptr, w, states, touchPoints };
@@ -157,7 +157,7 @@ public:
setEnabled(true);
setVisible(true);
- lastEvent = makeTouchData(QEvent::None, window(), nullptr, QList<QTouchEvent::TouchPoint>());//CHECK_VALID
+ lastEvent = makeTouchData(QEvent::None, window(), {}, QList<QTouchEvent::TouchPoint>());//CHECK_VALID
lastVelocity = lastVelocityFromMouseMove = QVector2D();
lastMousePos = QPointF();
@@ -2082,7 +2082,7 @@ void tst_qquickwindow::requestActivate()
QString warning = QString::fromLatin1("Mouse event MousePress not accepted by receiving window");
QWARN(warning.toLatin1().data());
}
- me = QMouseEvent(QEvent::MouseButtonPress, pos, window1->mapToGlobal(pos), Qt::LeftButton, nullptr, Qt::NoModifier);
+ me = QMouseEvent(QEvent::MouseButtonPress, pos, window1->mapToGlobal(pos), Qt::LeftButton, {}, Qt::NoModifier);
QSpontaneKeyEvent::setSpontaneous(&me);
if (!qApp->notify(window1.data(), &me)) {
QString warning = QString::fromLatin1("Mouse event MouseRelease not accepted by receiving window");
diff --git a/tests/auto/quick/shared/viewtestutil.cpp b/tests/auto/quick/shared/viewtestutil.cpp
index 1680e850f7..4089e5ddae 100644
--- a/tests/auto/quick/shared/viewtestutil.cpp
+++ b/tests/auto/quick/shared/viewtestutil.cpp
@@ -73,13 +73,13 @@ void QQuickViewTestUtil::moveMouseAway(QQuickView *window)
void QQuickViewTestUtil::moveAndRelease(QQuickView *window, const QPoint &position)
{
QTest::mouseMove(window, position);
- QTest::mouseRelease(window, Qt::LeftButton, 0, position);
+ QTest::mouseRelease(window, Qt::LeftButton, {}, position);
}
void QQuickViewTestUtil::moveAndPress(QQuickView *window, const QPoint &position)
{
QTest::mouseMove(window, position);
- QTest::mousePress(window, Qt::LeftButton, 0, position);
+ QTest::mousePress(window, Qt::LeftButton, {}, position);
}
void QQuickViewTestUtil::flick(QQuickView *window, const QPoint &from, const QPoint &to, int duration)