aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-06-28 13:28:09 +0200
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-06-28 13:28:10 +0200
commit63398defdbec12979b61120f690e984af0496c37 (patch)
treeab7a29ea0040d46c47004fed3c211a831bc48e9c
parentcff8d9f1d2d309cd9417bb93386a1443ed1892c3 (diff)
parent692b2da77427259a3589cf8a1311075863f2f5ec (diff)
Merge remote-tracking branch 'origin/5.12' into 5.13
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp10
-rw-r--r--src/qml/qml/qqmlmetatype.cpp29
-rw-r--r--src/qml/qml/qqmlprivate.h1
-rw-r--r--src/quick/items/qquickitemview.cpp28
-rw-r--r--src/quick/items/qquickitemview_p_p.h2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/getThis.qml60
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp12
-rw-r--r--tests/auto/qml/qqmlenginecleanup/CustomModuleImport/CustomModule.pro13
-rw-r--r--tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml41
-rw-r--r--tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp60
-rw-r--r--tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.qrc5
-rw-r--r--tests/auto/qml/qqmlenginecleanup/CustomModuleImport/qmldir3
-rw-r--r--tests/auto/qml/qqmlenginecleanup/qqmlenginecleanup.pro11
-rw-r--r--tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp18
-rw-r--r--tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.pro9
-rw-r--r--tests/auto/quick/qquickanimations/data/fastFlickingBug.qml114
-rw-r--r--tests/auto/quick/qquickanimations/qquickanimations.pro1
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp30
-rw-r--r--tests/auto/quick/qquicklistview/data/footer2.qml33
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp16
-rw-r--r--tools/qmlcachegen/generateloader.cpp7
-rw-r--r--tools/qmlscene/main.cpp44
22 files changed, 504 insertions, 43 deletions
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 6aa0130188..969d44ecf6 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -539,7 +539,6 @@ ReturnedValue QQmlContextWrapper::lookupIdObject(Lookup *l, ExecutionEngine *eng
ReturnedValue QQmlContextWrapper::lookupScopeObjectProperty(Lookup *l, ExecutionEngine *engine, Value *base)
{
- Q_UNUSED(base)
Scope scope(engine);
Scoped<QmlContext> qmlContext(scope, engine->qmlContext());
if (!qmlContext)
@@ -560,12 +559,15 @@ ReturnedValue QQmlContextWrapper::lookupScopeObjectProperty(Lookup *l, Execution
};
ScopedValue obj(scope, QV4::QObjectWrapper::wrap(engine, scopeObject));
+
+ if (base)
+ *base = obj;
+
return QObjectWrapper::lookupGetterImpl(l, engine, obj, /*useOriginalProperty*/ true, revertLookup);
}
ReturnedValue QQmlContextWrapper::lookupContextObjectProperty(Lookup *l, ExecutionEngine *engine, Value *base)
{
- Q_UNUSED(base)
Scope scope(engine);
Scoped<QmlContext> qmlContext(scope, engine->qmlContext());
if (!qmlContext)
@@ -590,6 +592,10 @@ ReturnedValue QQmlContextWrapper::lookupContextObjectProperty(Lookup *l, Executi
};
ScopedValue obj(scope, QV4::QObjectWrapper::wrap(engine, contextObject));
+
+ if (base)
+ *base = obj;
+
return QObjectWrapper::lookupGetterImpl(l, engine, obj, /*useOriginalProperty*/ true, revertLookup);
}
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 29b19b433f..0f8a850584 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -1641,7 +1641,14 @@ void qmlClearTypeRegistrations() // Declared in qqml.h
#endif
}
-static int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
+static void unregisterAutoParentFunction(const QQmlPrivate::AutoParentFunction &function)
+{
+ QMutexLocker lock(metaTypeDataLock());
+ QQmlMetaTypeData *data = metaTypeData();
+ data->parentFunctions.removeOne(function);
+}
+
+static int registerAutoParentFunction(const QQmlPrivate::RegisterAutoParent &autoparent)
{
QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
@@ -1950,6 +1957,26 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data)
return dtype.index();
}
+void QQmlPrivate::qmlunregister(RegistrationType type, quintptr data)
+{
+ switch (type) {
+ case AutoParentRegistration:
+ unregisterAutoParentFunction(reinterpret_cast<AutoParentFunction>(data));
+ break;
+ case QmlUnitCacheHookRegistration:
+ QQmlMetaType::removeCachedUnitLookupFunction(
+ reinterpret_cast<QmlUnitCacheLookupFunction>(data));
+ break;
+ case TypeRegistration:
+ case InterfaceRegistration:
+ case SingletonRegistration:
+ case CompositeRegistration:
+ case CompositeSingletonRegistration:
+ qmlUnregisterType(data);
+ break;
+ }
+}
+
//From qqml.h
bool qmlProtectModule(const char *uri, int majVersion)
{
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h
index ae84803648..8a45de9f76 100644
--- a/src/qml/qml/qqmlprivate.h
+++ b/src/qml/qml/qqmlprivate.h
@@ -318,6 +318,7 @@ namespace QQmlPrivate
};
int Q_QML_EXPORT qmlregister(RegistrationType, void *);
+ void Q_QML_EXPORT qmlunregister(RegistrationType, quintptr);
}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index c20f778a8f..95f1229b92 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -1724,8 +1724,14 @@ void QQuickItemViewPrivate::refill()
void QQuickItemViewPrivate::refill(qreal from, qreal to)
{
Q_Q(QQuickItemView);
- if (!isValid() || !q->isComponentComplete())
+ if (!model || !model->isValid() || !q->isComponentComplete())
return;
+ if (!model->count()) {
+ updateHeader();
+ updateFooter();
+ updateViewport();
+ return;
+ }
do {
bufferPause.stop();
@@ -1881,15 +1887,21 @@ void QQuickItemViewPrivate::layout()
prepareVisibleItemTransitions();
- for (QList<FxViewItem*>::Iterator it = releasePendingTransition.begin();
- it != releasePendingTransition.end(); ) {
- FxViewItem *item = *it;
- if (prepareNonVisibleItemTransition(item, viewBounds)) {
- ++it;
- } else {
- releaseItem(item);
+ for (auto it = releasePendingTransition.begin(); it != releasePendingTransition.end(); ) {
+ auto old_count = releasePendingTransition.count();
+ auto success = prepareNonVisibleItemTransition(*it, viewBounds);
+ // prepareNonVisibleItemTransition() may invalidate iterators while in fast flicking
+ // invisible animating items are kicked in or out the viewPort
+ // use old_count to test if the abrupt erasure occurs
+ if (old_count > releasePendingTransition.count()) {
+ continue;
+ }
+ if (!success) {
+ releaseItem(*it);
it = releasePendingTransition.erase(it);
+ continue;
}
+ ++it;
}
for (int i=0; i<visibleItems.count(); i++)
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
index 170027de87..89c0de704b 100644
--- a/src/quick/items/qquickitemview_p_p.h
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -287,7 +287,7 @@ public:
: item(i), moveKey(k) {}
};
QQuickItemViewTransitioner *transitioner;
- QList<FxViewItem *> releasePendingTransition;
+ QVector<FxViewItem *> releasePendingTransition;
mutable qreal minExtent;
mutable qreal maxExtent;
diff --git a/tests/auto/qml/qqmlecmascript/data/getThis.qml b/tests/auto/qml/qqmlecmascript/data/getThis.qml
new file mode 100644
index 0000000000..cd617ee3c0
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/getThis.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQml 2.12
+
+QtObject {
+ id: root
+ property QtObject self;
+
+ property Timer timer: Timer {
+ running: true
+ interval: 1
+ onTriggered: {
+ root.assignThis();
+ root.self = null;
+ root.assignThis();
+ }
+ }
+
+ function getThis() {
+ return this;
+ }
+
+ function assignThis() {
+ self = getThis();
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 43cf8192a5..59dc5debb9 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -370,6 +370,7 @@ private slots:
void undefinedPropertiesInObjectWrapper();
void hugeRegexpQuantifiers();
void singletonTypeWrapperLookup();
+ void getThisObject();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -9036,6 +9037,17 @@ void tst_qqmlecmascript::singletonTypeWrapperLookup()
QCOMPARE(test->property("secondLookup").toInt(), singleton2->testVar);
}
+void tst_qqmlecmascript::getThisObject()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("getThis.qml"));
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> test(component.create());
+ QVERIFY(!test.isNull());
+
+ QTRY_COMPARE(qvariant_cast<QObject *>(test->property("self")), test.data());
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/CustomModule.pro b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/CustomModule.pro
new file mode 100644
index 0000000000..3366ddc165
--- /dev/null
+++ b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/CustomModule.pro
@@ -0,0 +1,13 @@
+TEMPLATE = lib
+TARGET = CustomModule
+QT += quick qml
+
+CONFIG += qtquickcompiler
+SOURCES += moduleplugin.cpp
+RESOURCES += moduleplugin.qrc
+
+DESTDIR = ../CustomModule
+
+IMPORT_FILES = qmldir
+
+include (../../../shared/imports.pri)
diff --git a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml
new file mode 100644
index 0000000000..ed154e3aa9
--- /dev/null
+++ b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQml 2.12
+
+QtObject {
+ objectName: "moduleType"
+}
diff --git a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp
new file mode 100644
index 0000000000..048250c730
--- /dev/null
+++ b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtQml/qqmlextensionplugin.h>
+#include <QtQml/qqmlengine.h>
+
+QT_BEGIN_NAMESPACE
+
+class ModulePlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+
+public:
+ ModulePlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) {}
+ void registerTypes(const char *uri) override;
+};
+
+void ModulePlugin::registerTypes(const char *uri)
+{
+ qmlRegisterModule(uri, 1, 0);
+ qmlRegisterType(QUrl("qrc:/ModuleType.qml"), uri, 1, 0, "ModuleType");
+}
+
+QT_END_NAMESPACE
+
+#include "moduleplugin.moc"
diff --git a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.qrc b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.qrc
new file mode 100644
index 0000000000..c8f7dea691
--- /dev/null
+++ b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>ModuleType.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/qmldir b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/qmldir
new file mode 100644
index 0000000000..f421ba44dc
--- /dev/null
+++ b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/qmldir
@@ -0,0 +1,3 @@
+module CustomModule
+plugin CustomModule
+classname ModulePlugin
diff --git a/tests/auto/qml/qqmlenginecleanup/qqmlenginecleanup.pro b/tests/auto/qml/qqmlenginecleanup/qqmlenginecleanup.pro
index 90508609a8..34c49a5c0e 100644
--- a/tests/auto/qml/qqmlenginecleanup/qqmlenginecleanup.pro
+++ b/tests/auto/qml/qqmlenginecleanup/qqmlenginecleanup.pro
@@ -1,9 +1,2 @@
-CONFIG += testcase
-TARGET = tst_qqmlenginecleanup
-macx:CONFIG -= app_bundle
-
-include (../../shared/util.pri)
-
-SOURCES += tst_qqmlenginecleanup.cpp
-
-QT += testlib qml qml-private
+TEMPLATE = subdirs
+SUBDIRS += tst_qqmlenginecleanup.pro CustomModuleImport/CustomModule.pro
diff --git a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp
index b9cede6d13..690db30838 100644
--- a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp
+++ b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp
@@ -44,6 +44,7 @@ public:
private slots:
void test_qmlClearTypeRegistrations();
void test_valueTypeProviderModule(); // QTBUG-43004
+ void test_customModuleCleanup();
};
// A wrapper around QQmlComponent to ensure the temporary reference counts
@@ -168,6 +169,23 @@ void tst_qqmlenginecleanup::test_valueTypeProviderModule()
QVERIFY(noDangling);
}
+void tst_qqmlenginecleanup::test_customModuleCleanup()
+{
+ for (int i = 0; i < 5; ++i) {
+ qmlClearTypeRegistrations();
+
+ QQmlEngine engine;
+ engine.addImportPath(QT_TESTCASE_BUILDDIR);
+
+ QQmlComponent component(&engine);
+ component.setData("import CustomModule 1.0\nModuleType {}", QUrl());
+ QCOMPARE(component.status(), QQmlComponent::Ready);
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ }
+}
+
QTEST_MAIN(tst_qqmlenginecleanup)
#include "tst_qqmlenginecleanup.moc"
diff --git a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.pro b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.pro
new file mode 100644
index 0000000000..90508609a8
--- /dev/null
+++ b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+TARGET = tst_qqmlenginecleanup
+macx:CONFIG -= app_bundle
+
+include (../../shared/util.pri)
+
+SOURCES += tst_qqmlenginecleanup.cpp
+
+QT += testlib qml qml-private
diff --git a/tests/auto/quick/qquickanimations/data/fastFlickingBug.qml b/tests/auto/quick/qquickanimations/data/fastFlickingBug.qml
new file mode 100644
index 0000000000..b2649a801b
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/fastFlickingBug.qml
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore 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.11
+import QtQuick.Window 2.11
+
+Window {
+ id: root
+ property alias timer : timer
+ property alias listView : listView
+ property alias theModel: theModel
+ property variant ops: [{'op': 'add', 'count': 30}, {'op': 'add', 'count': 60}, {'op': 'rem', 'count': 40}, {'op': 'rem', 'count': 10}, {'op': 'rem', 'count': 39},
+ {'op': 'add', 'count': 30}, {'op': 'add', 'count': 60}, {'op': 'rem', 'count': 40}, {'op': 'rem', 'count': 10}, {'op': 'rem', 'count': 39},
+ {'op': 'add', 'count': 30}, {'op': 'add', 'count': 60}, {'op': 'rem', 'count': 40}, {'op': 'rem', 'count': 10}, {'op': 'rem', 'count': 39},
+ {'op': 'add', 'count': 30}, {'op': 'add', 'count': 60}, {'op': 'rem', 'count': 40}, {'op': 'rem', 'count': 10}, {'op': 'rem', 'count': 39},
+ {'op': 'add', 'count': 30}, {'op': 'add', 'count': 60}, {'op': 'rem', 'count': 40}, {'op': 'rem', 'count': 10}, {'op': 'rem', 'count': 39},
+ {'op': 'add', 'count': 30}, {'op': 'add', 'count': 60}, {'op': 'rem', 'count': 40}, {'op': 'rem', 'count': 10}, {'op': 'rem', 'count': 39},
+ {'op': 'add', 'count': 30}, {'op': 'add', 'count': 60}, {'op': 'rem', 'count': 40}, {'op': 'rem', 'count': 10}, {'op': 'rem', 'count': 39}]
+ property int opIndex : 0
+ width: 400
+ height: 600
+
+ ListModel {
+ id: theModel
+ }
+
+ Timer {
+ id: timer
+ interval: 100
+ running: false
+ repeat: true
+ onTriggered: {
+ if (opIndex >= ops.length) {
+ timer.stop()
+ return
+ }
+ let op = ops[opIndex]
+ for (var i = 0; i < op.count; ++i) {
+ if (op.op === "add")
+ theModel.append({"name": "opIndex " + opIndex})
+ else
+ theModel.remove(0, 1);
+ }
+ opIndex = opIndex + 1
+ }
+ }
+
+ ListView {
+ id: listView
+ anchors.fill: parent
+ spacing: 4
+ model: theModel
+ header: Text {
+ text: "YAnimator"
+ }
+ add: Transition {
+ NumberAnimation { property: "scale"; from: 0; to: 1; duration: 200 }
+ NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 200 }
+ }
+ displaced: Transition {
+ YAnimator { duration: 500 }
+ NumberAnimation { property: "opacity"; to: 1.0; duration: 1000 }
+ NumberAnimation { property: "scale"; to: 1.0; duration: 1000 }
+ }
+ remove: Transition {
+ NumberAnimation { property: "opacity"; to: 0; duration: 200 }
+ NumberAnimation { property: "scale"; to: 0; duration: 200 }
+ }
+ delegate: Rectangle {
+ width: 200
+ height: 20
+ color:"red"
+ Text {
+ anchors.centerIn: parent
+ text: name
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimations/qquickanimations.pro b/tests/auto/quick/qquickanimations/qquickanimations.pro
index cf9c87a305..1c5494a24a 100644
--- a/tests/auto/quick/qquickanimations/qquickanimations.pro
+++ b/tests/auto/quick/qquickanimations/qquickanimations.pro
@@ -27,6 +27,7 @@ OTHER_FILES += \
data/dotproperty.qml \
data/Double.qml \
data/doubleRegistrationBug.qml \
+ data/fastFlickingBug.qml \
data/looping.qml \
data/mixedtype1.qml \
data/mixedtype2.qml \
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index 181d40e9ce..17dfa4a3d7 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -40,6 +40,7 @@
#include <QtQuick/private/qquickanimatorjob_p.h>
#include <QtQuick/private/qquickpathinterpolator_p.h>
#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qquicklistview_p.h>
#include <QEasingCurve>
#include <limits.h>
@@ -110,6 +111,7 @@ private slots:
void finished();
void replacingTransitions();
void animationJobSelfDestruction();
+ void fastFlickingBug();
};
#define QTIMED_COMPARE(lhs, rhs) do { \
@@ -1744,6 +1746,34 @@ void tst_qquickanimations::animationJobSelfDestruction()
QTest::qWait(1000);
}
+void tst_qquickanimations::fastFlickingBug()
+{
+ // Don't crash
+ QQmlEngine engine;
+ engine.clearComponentCache();
+ QQmlComponent c(&engine, testFileUrl("fastFlickingBug.qml"));
+ QScopedPointer<QQuickWindow> win(qobject_cast<QQuickWindow*>(c.create()));
+ if (!c.errors().isEmpty())
+ qDebug() << c.errorString();
+ QVERIFY(win);
+ win->setTitle(QTest::currentTestFunction());
+ win->show();
+ QVERIFY(QTest::qWaitForWindowExposed(win.data()));
+ auto timer = win->property("timer").value<QQmlTimer*>();
+ QVERIFY(timer);
+ QCOMPARE(timer->isRunning(), false);
+ auto listView = win->property("listView").value<QQuickFlickable*>();
+ QVERIFY(listView);
+ timer->start();
+ // flick listView up and down quickly in the middle of a slow transition
+ for (int sign = 1; timer->isRunning(); sign *= -1) {
+ listView->flick(0, sign * 4000);
+ qApp->processEvents();
+ QTest::qWait(53);
+ qApp->processEvents();
+ }
+}
+
QTEST_MAIN(tst_qquickanimations)
#include "tst_qquickanimations.moc"
diff --git a/tests/auto/quick/qquicklistview/data/footer2.qml b/tests/auto/quick/qquicklistview/data/footer2.qml
new file mode 100644
index 0000000000..bba74d89f7
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/footer2.qml
@@ -0,0 +1,33 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 240
+ height: 320
+
+ Timer {
+ running: true
+ repeat: false
+ interval: 100
+ onTriggered: {
+ list.model -= 3;
+ }
+ }
+
+ ListView {
+ id: list
+ objectName: "list"
+ anchors.fill: parent
+ model: 3
+ delegate: Rectangle {
+ color: "red"
+ width: 240
+ height: 10
+ }
+ footer: Rectangle {
+ color: "blue"
+ width: 240
+ height: 10
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 2ea8a477a8..39df10b9d9 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -153,6 +153,7 @@ private slots:
void headerChangesViewport();
void footer();
void footer_data();
+ void footer2();
void extents();
void extents_data();
void resetModel_headerFooter();
@@ -4139,6 +4140,21 @@ void tst_QQuickListView::footer_data()
<< QPointF(0, -(30 * 20) - 10);
}
+void tst_QQuickListView::footer2() // QTBUG-31677
+{
+ QQuickView *window = getView();
+ window->setSource(testFileUrl("footer2.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+ QTRY_VERIFY(listview != nullptr);
+
+ QQuickItem *footer = listview->footerItem();
+ QVERIFY(footer != nullptr);
+ QTRY_COMPARE(footer->y(), 0.0);
+}
+
class LVAccessor : public QQuickListView
{
public:
diff --git a/tools/qmlcachegen/generateloader.cpp b/tools/qmlcachegen/generateloader.cpp
index 5b8fc34455..4fbbb27afb 100644
--- a/tools/qmlcachegen/generateloader.cpp
+++ b/tools/qmlcachegen/generateloader.cpp
@@ -365,6 +365,7 @@ bool generateLoader(const QStringList &compiledFiles, const QStringList &sortedR
stream << "struct Registry {\n";
stream << " Registry();\n";
+ stream << " ~Registry();\n";
stream << " QHash<QString, const QQmlPrivate::CachedQmlUnit*> resourcePathToCachedUnit;\n";
stream << " static const QQmlPrivate::CachedQmlUnit *lookupCachedUnit(const QUrl &url);\n";
stream << "};\n\n";
@@ -387,7 +388,11 @@ bool generateLoader(const QStringList &compiledFiles, const QStringList &sortedR
if (!resourceRegisterCall.isEmpty())
stream << resourceRegisterCall;
- stream << "}\n";
+ stream << "}\n\n";
+ stream << "Registry::~Registry() {\n";
+ stream << " QQmlPrivate::qmlunregister(QQmlPrivate::QmlUnitCacheHookRegistration, quintptr(&lookupCachedUnit));\n";
+ stream << "}\n\n";
+
stream << "const QQmlPrivate::CachedQmlUnit *Registry::lookupCachedUnit(const QUrl &url) {\n";
stream << " if (url.scheme() != QLatin1String(\"qrc\"))\n";
stream << " return nullptr;\n";
diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp
index d64272d417..af50acaa5a 100644
--- a/tools/qmlscene/main.cpp
+++ b/tools/qmlscene/main.cpp
@@ -477,6 +477,12 @@ int main(int argc, char ** argv)
options.applicationAttributes.append(Qt::AA_EnableHighDpiScaling);
} else if (!qstrcmp(arg, "--no-scaling")) {
options.applicationAttributes.append(Qt::AA_DisableHighDpiScaling);
+ } else if (!qstrcmp(arg, "--transparent")) {
+ options.transparent = true;
+ } else if (!qstrcmp(arg, "--multisample")) {
+ options.multisample = true;
+ } else if (!qstrcmp(arg, "--core-profile")) {
+ options.coreProfile = true;
} else if (!qstrcmp(arg, "--apptype")) {
if (++i >= argc)
usage();
@@ -485,6 +491,23 @@ int main(int argc, char ** argv)
}
}
+ if (qEnvironmentVariableIsSet("QMLSCENE_CORE_PROFILE"))
+ options.coreProfile = true;
+
+ // Set default surface format before creating the window
+ QSurfaceFormat surfaceFormat;
+ surfaceFormat.setStencilBufferSize(8);
+ surfaceFormat.setDepthBufferSize(24);
+ if (options.multisample)
+ surfaceFormat.setSamples(16);
+ if (options.transparent)
+ surfaceFormat.setAlphaBufferSize(8);
+ if (options.coreProfile) {
+ surfaceFormat.setVersion(4, 1);
+ surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
+ }
+ QSurfaceFormat::setDefaultFormat(surfaceFormat);
+
for (Qt::ApplicationAttribute a : qAsConst(options.applicationAttributes))
QCoreApplication::setAttribute(a);
QScopedPointer<QGuiApplication> app;
@@ -499,9 +522,6 @@ int main(int argc, char ** argv)
QCoreApplication::setOrganizationDomain(QStringLiteral("qt-project.org"));
QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
- if (qEnvironmentVariableIsSet("QMLSCENE_CORE_PROFILE"))
- options.coreProfile = true;
-
const QStringList arguments = QCoreApplication::arguments();
for (int i = 1, size = arguments.size(); i < size; ++i) {
if (!arguments.at(i).startsWith(QLatin1Char('-'))) {
@@ -512,8 +532,6 @@ int main(int argc, char ** argv)
options.maximized = true;
else if (lowerArgument == QLatin1String("--fullscreen"))
options.fullscreen = true;
- else if (lowerArgument == QLatin1String("--transparent"))
- options.transparent = true;
else if (lowerArgument == QLatin1String("--clip"))
options.clip = true;
else if (lowerArgument == QLatin1String("--no-version-detection"))
@@ -526,10 +544,6 @@ int main(int argc, char ** argv)
options.translationFile = QLatin1String(argv[++i]);
else if (lowerArgument == QLatin1String("--resize-to-root"))
options.resizeViewToRootItem = true;
- else if (lowerArgument == QLatin1String("--multisample"))
- options.multisample = true;
- else if (lowerArgument == QLatin1String("--core-profile"))
- options.coreProfile = true;
else if (lowerArgument == QLatin1String("--verbose"))
options.verbose = true;
else if (lowerArgument == QLatin1String("-i") && i + 1 < size)
@@ -623,18 +637,6 @@ int main(int argc, char ** argv)
return -1;
}
- // Set default surface format before creating the window
- QSurfaceFormat surfaceFormat;
- if (options.multisample)
- surfaceFormat.setSamples(16);
- if (options.transparent)
- surfaceFormat.setAlphaBufferSize(8);
- if (options.coreProfile) {
- surfaceFormat.setVersion(4, 1);
- surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
- }
- QSurfaceFormat::setDefaultFormat(surfaceFormat);
-
QScopedPointer<QQuickWindow> window(qobject_cast<QQuickWindow *>(topLevel));
if (window) {
engine.setIncubationController(window->incubationController());