diff options
author | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2024-05-08 08:14:41 +0300 |
---|---|---|
committer | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2024-05-08 08:14:41 +0300 |
commit | 5f4570b5164a828b20514b938957ce06b105ff3e (patch) | |
tree | 0114d737813cb121ba31cbe5c2f73db746cc10dc | |
parent | 6ab9856ef379fc3fe44d5fac03a83f679f398511 (diff) | |
parent | b299416894bcaf7965fd53c195636d84f0674255 (diff) |
Merge remote-tracking branch 'origin/tqtc/lts-5.15.14' into tqtc/lts-5.15-opensourcev5.15.14-lts-lgpl5.15
Change-Id: I1931a83a9be70494c53bb0a79b3bcb01f6c84608
-rw-r--r-- | .qmake.conf | 2 | ||||
-rw-r--r-- | src/qml/doc/src/qmllanguageref/syntax/imports.qdoc | 16 | ||||
-rw-r--r-- | src/qml/jit/qv4baselinejit.cpp | 4 | ||||
-rw-r--r-- | src/qmlmodels/qqmldelegatemodel.cpp | 23 | ||||
-rw-r--r-- | src/quick/items/qquickitem.cpp | 7 | ||||
-rw-r--r-- | tests/auto/qml/qml.pro | 1 | ||||
-rw-r--r-- | tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml | 50 | ||||
-rw-r--r-- | tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp | 23 | ||||
-rw-r--r-- | tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST | 1 | ||||
-rw-r--r-- | tests/auto/quick/qquickdroparea/BLACKLIST | 1 | ||||
-rw-r--r-- | tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml | 13 | ||||
-rw-r--r-- | tests/auto/quick/qquickitem2/tst_qquickitem.cpp | 12 | ||||
-rw-r--r-- | tests/auto/quick/qquicktext/BLACKLIST | 2 | ||||
-rw-r--r-- | tests/auto/quick/qquicktextedit/BLACKLIST | 1 | ||||
-rw-r--r-- | tests/auto/quickwidgets/qquickwidget/BLACKLIST | 1 |
15 files changed, 128 insertions, 29 deletions
diff --git a/.qmake.conf b/.qmake.conf index 65ef03633e..831517bb0e 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,4 +4,4 @@ CONFIG += warning_clean DEFINES += QT_NO_LINKED_LIST DEFINES += QT_NO_JAVA_STYLE_ITERATORS -MODULE_VERSION = 5.15.13 +MODULE_VERSION = 5.15.14 diff --git a/src/qml/doc/src/qmllanguageref/syntax/imports.qdoc b/src/qml/doc/src/qmllanguageref/syntax/imports.qdoc index fdba452271..866ddc6d60 100644 --- a/src/qml/doc/src/qmllanguageref/syntax/imports.qdoc +++ b/src/qml/doc/src/qmllanguageref/syntax/imports.qdoc @@ -36,12 +36,10 @@ resources and component directories are used within a QML document. The types which may be used within a document depends on which modules, resources and directories are imported by the document. -\section2 Import Types - There are three different types of imports. Each import type has a slightly different syntax, and different semantics apply to different import types. -\section3 Module (Namespace) Imports +\section2 Module (Namespace) Imports The most common type of import is a module import. Clients can import \l{qtqml-modules-identifiedmodules.html}{QML modules} which register QML object @@ -127,7 +125,7 @@ Rectangle { In this case, the engine will emit an error and refuse to load the file. -\section4 C++ Module Imports +\section3 C++ Module Imports Usually, C++ types are declared using the QML_ELEMENT and QML_NAMED_ELEMENT() macros and registered via the build system using QML_IMPORT_NAME and @@ -137,7 +135,7 @@ module that can be imported to access the types. This is most common in client applications which define their own QML object types in C++. -\section4 Importing into a Qualified Local Namespace +\section3 Importing into a Qualified Local Namespace The \c import statement may optionally use the \c as keyword to specify that the types should be imported into a particular document-local namespace. If a @@ -187,7 +185,7 @@ way that multiple modules can be imported into the global namespace. For example \snippet qml/imports/merged-named-imports.qml imports -\section3 Directory Imports +\section2 Directory Imports A directory which contains QML documents may also be imported directly in a QML document. This provides a simple way for QML types to be segmented into @@ -213,7 +211,7 @@ section about \l{Importing into a Qualified Local Namespace}. For more information about directory imports, please see the in-depth documentation about \l{qtqml-syntax-directoryimports.html}{directory imports}. -\section3 JavaScript Resource Imports +\section2 JavaScript Resource Imports JavaScript resources may be imported directly in a QML document. Every JavaScript resource must have an identifier by which it is accessed. @@ -226,7 +224,7 @@ import "<JavaScriptFile>" as <Identifier> Note that the \c <Identifier> must be unique within a QML document, unlike the local namespace qualifier which can be applied to module imports. -\section4 JavaScript Resources from Modules +\section3 JavaScript Resources from Modules Javascript files can be provided by modules, by adding identifier definitions to the \c qmldir file which specifies the module. @@ -269,7 +267,7 @@ Item { } \endqml -\section4 Further Information +\section3 Further Information For more information about JavaScript resources, please see the documentation about \l{qtqml-javascript-resources.html} diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp index 45150cfffd..5ad53faf95 100644 --- a/src/qml/jit/qv4baselinejit.cpp +++ b/src/qml/jit/qv4baselinejit.cpp @@ -540,6 +540,8 @@ void BaselineJIT::generate_ThrowException() as->passEngineAsArg(0); BASELINEJIT_GENERATE_RUNTIME_CALL(ThrowException, CallResultDestination::Ignore); as->gotoCatchException(); + + // LOAD_ACC(); <- not needed here since it would be unreachable. } void BaselineJIT::generate_GetException() { as->getException(); } @@ -547,9 +549,11 @@ void BaselineJIT::generate_SetException() { as->setException(); } void BaselineJIT::generate_CreateCallContext() { + STORE_ACC(); as->prepareCallWithArgCount(1); as->passCppFrameAsArg(0); BASELINEJIT_GENERATE_RUNTIME_CALL(PushCallContext, CallResultDestination::Ignore); + LOAD_ACC(); } void BaselineJIT::generate_PushCatchContext(int index, int name) { as->pushCatchContext(index, name); } diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp index 4fcff70de6..3b57edfc5d 100644 --- a/src/qmlmodels/qqmldelegatemodel.cpp +++ b/src/qmlmodels/qqmldelegatemodel.cpp @@ -1871,10 +1871,15 @@ void QQmlDelegateModelPrivate::emitChanges() for (int i = 1; i < m_groupCount; ++i) QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitModelUpdated(reset); - auto cacheCopy = m_cache; // deliberate; emitChanges may alter m_cache - for (QQmlDelegateModelItem *cacheItem : qAsConst(cacheCopy)) { - if (cacheItem->attached) - cacheItem->attached->emitChanges(); + // emitChanges may alter m_cache and delete items + QVarLengthArray<QPointer<QQmlDelegateModelAttached>> attachedObjects; + attachedObjects.reserve(m_cache.length()); + for (const QQmlDelegateModelItem *cacheItem : qAsConst(m_cache)) + attachedObjects.append(cacheItem->attached); + + for (const QPointer<QQmlDelegateModelAttached> &attached : qAsConst(attachedObjects)) { + if (attached && attached->m_cacheItem) + attached->emitChanges(); } } @@ -2663,20 +2668,24 @@ void QQmlDelegateModelAttached::emitChanges() m_previousGroups = m_cacheItem->groups; int indexChanges = 0; - for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) { + const int groupCount = m_cacheItem->metaType->groupCount; + for (int i = 1; i < groupCount; ++i) { if (m_previousIndex[i] != m_currentIndex[i]) { m_previousIndex[i] = m_currentIndex[i]; indexChanges |= (1 << i); } } + // Don't access m_cacheItem anymore once we've started sending signals. + // We don't own it and someone might delete it. + int notifierId = 0; const QMetaObject *meta = metaObject(); - for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) { + for (int i = 1; i < groupCount; ++i, ++notifierId) { if (groupChanges & (1 << i)) QMetaObject::activate(this, meta, notifierId, nullptr); } - for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) { + for (int i = 1; i < groupCount; ++i, ++notifierId) { if (indexChanges & (1 << i)) QMetaObject::activate(this, meta, notifierId, nullptr); } diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 33da9762d3..ec55fb2998 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -59,6 +59,7 @@ #include <QtCore/private/qnumeric_p.h> #include <QtGui/qpa/qplatformtheme.h> #include <QtCore/qloggingcategory.h> +#include <QtCore/private/qduplicatetracker_p.h> #include <private/qqmlglobal_p.h> #include <private/qqmlengine_p.h> @@ -2526,6 +2527,7 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo QQuickItem *current = item; qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: startItem:" << startItem; qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: firstFromItem:" << firstFromItem; + QDuplicateTracker<QQuickItem *> cycleDetector; do { qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: current:" << current; qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: from:" << from; @@ -2592,7 +2594,10 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo // traversed all of the chain (by compare the [current] item with [startItem]) // Since the [startItem] might be promoted to its parent if it is invisible, // we still have to check [current] item with original start item - if ((current == startItem || current == originalStartItem) && from == firstFromItem) { + // We might also run into a cycle before we reach firstFromItem again + // but note that we have to ignore current if we are meant to skip it + if (((current == startItem || current == originalStartItem) && from == firstFromItem) || + (!skip && cycleDetector.hasSeen(current))) { // wrapped around, avoid endless loops if (item == contentItem) { qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem"; diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro index 621e8bb437..104fb216c2 100644 --- a/tests/auto/qml/qml.pro +++ b/tests/auto/qml/qml.pro @@ -43,6 +43,7 @@ PRIVATETESTS += \ animation \ qqmlecmascript \ qqmlcontext \ + qqmldelegatemodel \ qqmlexpression \ qqmlglobal \ qqmllanguage \ diff --git a/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml b/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml new file mode 100644 index 0000000000..23874970e7 --- /dev/null +++ b/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml @@ -0,0 +1,50 @@ +import QtQuick 2.15 +import QtQml.Models 2.15 + +Item { + DelegateModel { + id: delegateModel + model: ListModel { + id: sourceModel + + ListElement { title: "foo" } + ListElement { title: "bar" } + + function clear() { + if (count > 0) + remove(0, count); + } + } + + groups: [ + DelegateModelGroup { name: "selectedItems" } + ] + + delegate: Text { + height: DelegateModel.inSelectedItems ? implicitHeight * 2 : implicitHeight + Component.onCompleted: { + if (index === 0) + DelegateModel.inSelectedItems = true; + } + } + + Component.onCompleted: { + items.create(0) + items.create(1) + } + } + + ListView { + anchors.fill: parent + model: delegateModel + } + + Timer { + running: true + interval: 10 + onTriggered: sourceModel.clear() + } + + property int count: delegateModel.items.count +} + diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp index 35f1e2c94d..f0afdb16ca 100644 --- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp +++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp @@ -47,6 +47,7 @@ private slots: void filterOnGroup_removeWhenCompleted(); void qtbug_86017(); void contextAccessedByHandler(); + void deleteRace(); }; class AbstractItemModel : public QAbstractItemModel @@ -139,17 +140,6 @@ void tst_QQmlDelegateModel::valueWithoutCallingObjectFirst() QCOMPARE(model->variantValue(index, role), expectedValue); } -void tst_QQmlDelegateModel::filterOnGroup_removeWhenCompleted() -{ - QQuickView view(testFileUrl("removeFromGroup.qml")); - QCOMPARE(view.status(), QQuickView::Ready); - view.show(); - QQuickItem *root = view.rootObject(); - QVERIFY(root); - QQmlDelegateModel *model = root->findChild<QQmlDelegateModel*>(); - QVERIFY(model); - QTest::qWaitFor([=]{ return model->count() == 2; } ); - void tst_QQmlDelegateModel::qtbug_86017() { QQmlEngine engine; @@ -186,6 +176,17 @@ void tst_QQmlDelegateModel::contextAccessedByHandler() QVERIFY(root->property("works").toBool()); } +void tst_QQmlDelegateModel::deleteRace() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("deleteRace.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + QTRY_COMPARE(o->property("count").toInt(), 2); + QTRY_COMPARE(o->property("count").toInt(), 0); +} + QTEST_MAIN(tst_QQmlDelegateModel) #include "tst_qqmldelegatemodel.moc" diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST b/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST index 9bb35c4770..2df6574c2e 100644 --- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST +++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/BLACKLIST @@ -1,3 +1,4 @@ [movingItemWithHoverHandler] macos # Can't move cursor (QTBUG-76312) +sles-15.4 # (QTBUG-111294) diff --git a/tests/auto/quick/qquickdroparea/BLACKLIST b/tests/auto/quick/qquickdroparea/BLACKLIST index 0967969b04..e5223c1c87 100644 --- a/tests/auto/quick/qquickdroparea/BLACKLIST +++ b/tests/auto/quick/qquickdroparea/BLACKLIST @@ -2,3 +2,4 @@ # QTBUG-99765 [containsDrag_internal] ubuntu-20.04 +sles-15.4 diff --git a/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml b/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml new file mode 100644 index 0000000000..889e480f3b --- /dev/null +++ b/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml @@ -0,0 +1,13 @@ +import QtQuick 2.6 + +Item { + visible: true + Item { + visible: false + Item { + objectName: "hiddenChild" + activeFocusOnTab: true + focus: true + } + } +} diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index c8f251dbe1..c8ef36ee68 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -67,6 +67,7 @@ private slots: void activeFocusOnTab10(); void activeFocusOnTab_infiniteLoop_data(); void activeFocusOnTab_infiniteLoop(); + void activeFocusOnTab_infiniteLoopControls(); void nextItemInFocusChain(); void nextItemInFocusChain2(); @@ -1057,6 +1058,17 @@ void tst_QQuickItem::activeFocusOnTab_infiniteLoop() QCOMPARE(item, window->rootObject()); } + +void tst_QQuickItem::activeFocusOnTab_infiniteLoopControls() +{ + auto source = testFileUrl("activeFocusOnTab_infiniteLoop3.qml"); + QScopedPointer<QQuickView>window(new QQuickView()); + window->setSource(source); + window->show(); + QVERIFY(window->errors().isEmpty()); + QTest::keyClick(window.get(), Qt::Key_Tab); // should not hang +} + void tst_QQuickItem::nextItemInFocusChain() { if (!qt_tab_all_widgets()) diff --git a/tests/auto/quick/qquicktext/BLACKLIST b/tests/auto/quick/qquicktext/BLACKLIST index f50276a4f1..85deb2288e 100644 --- a/tests/auto/quick/qquicktext/BLACKLIST +++ b/tests/auto/quick/qquicktext/BLACKLIST @@ -6,3 +6,5 @@ macos opensuse-42.1 [hAlignVisual] sles +[contentSize] +sles-15.4 # QTBUG-112360 diff --git a/tests/auto/quick/qquicktextedit/BLACKLIST b/tests/auto/quick/qquicktextedit/BLACKLIST index a5cbd1675e..272e70b5cf 100644 --- a/tests/auto/quick/qquicktextedit/BLACKLIST +++ b/tests/auto/quick/qquicktextedit/BLACKLIST @@ -11,4 +11,5 @@ sles # QTBUG-82052 [linkHover] macos ci +sles-15.4 diff --git a/tests/auto/quickwidgets/qquickwidget/BLACKLIST b/tests/auto/quickwidgets/qquickwidget/BLACKLIST index 095e9ee484..afc565eab4 100644 --- a/tests/auto/quickwidgets/qquickwidget/BLACKLIST +++ b/tests/auto/quickwidgets/qquickwidget/BLACKLIST @@ -3,3 +3,4 @@ opensuse-42.3 opensuse-leap [enterLeave] macos +sles-15.4 # QTBUG-64397 |