diff options
author | Tarja Sundqvist <[email protected]> | 2024-11-22 10:46:11 +0200 |
---|---|---|
committer | Tarja Sundqvist <[email protected]> | 2024-11-22 10:46:11 +0200 |
commit | 64364dbe06b46e5f355c3b2a6684a3eae4f54a7a (patch) | |
tree | b501b88601bbda604da2adac9307c47b6d3733b2 | |
parent | 6b64e58767c6dd32a29a261e3327fa88b5613621 (diff) | |
parent | 4d94cd012575956a7633fc19d87059f7a8e0dda2 (diff) |
Merge tag 'v6.2.11-lts' into tqtc/lts-6.2-opensource
Qt 6.2.11-lts release
Conflicts solved:
dependencies.yaml
Change-Id: I088fe99748b323fbdf49c3766c262eb2a05131d9
139 files changed, 2468 insertions, 252 deletions
diff --git a/.cmake.conf b/.cmake.conf index 31a36e3b07..842b347ced 100644 --- a/.cmake.conf +++ b/.cmake.conf @@ -1,2 +1,2 @@ -set(QT_REPO_MODULE_VERSION "6.2.10") +set(QT_REPO_MODULE_VERSION "6.2.11") set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "") diff --git a/.qmake.conf b/.qmake.conf index 4c0875fa17..7f5f2c33a7 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -5,4 +5,4 @@ DEFINES += QT_NO_JAVA_STYLE_ITERATORS QQC2_SOURCE_TREE = $$PWD -MODULE_VERSION = 6.2.10 +MODULE_VERSION = 6.2.11 diff --git a/examples/quick/embeddedinwidgets/reflect.frag b/examples/quick/embeddedinwidgets/reflect.frag index 04a81f86e5..e1d5dbf450 100644 --- a/examples/quick/embeddedinwidgets/reflect.frag +++ b/examples/quick/embeddedinwidgets/reflect.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #version 440 layout(location = 0) in vec2 qt_TexCoord0; diff --git a/examples/quick/rendercontrol/rendercontrol_d3d11/quad.frag b/examples/quick/rendercontrol/rendercontrol_d3d11/quad.frag index 09914ccdbe..a72c43db0f 100644 --- a/examples/quick/rendercontrol/rendercontrol_d3d11/quad.frag +++ b/examples/quick/rendercontrol/rendercontrol_d3d11/quad.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + struct PSIn { float2 coord : TEXCOORD0; diff --git a/examples/quick/scenegraph/custommaterial/shaders/mandelbrot.frag b/examples/quick/scenegraph/custommaterial/shaders/mandelbrot.frag index 0e5f63e7a8..77cc67e4b5 100644 --- a/examples/quick/scenegraph/custommaterial/shaders/mandelbrot.frag +++ b/examples/quick/scenegraph/custommaterial/shaders/mandelbrot.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + //! [1] #version 440 diff --git a/examples/quick/scenegraph/d3d11underqml/squircle.frag b/examples/quick/scenegraph/d3d11underqml/squircle.frag index a907c84e58..713b2d89f2 100644 --- a/examples/quick/scenegraph/d3d11underqml/squircle.frag +++ b/examples/quick/scenegraph/d3d11underqml/squircle.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + cbuffer buf : register(b0) { float ubuf_t : packoffset(c0); diff --git a/examples/quick/scenegraph/graph/shaders/line.frag b/examples/quick/scenegraph/graph/shaders/line.frag index 44b5b24c94..b9531cede6 100644 --- a/examples/quick/scenegraph/graph/shaders/line.frag +++ b/examples/quick/scenegraph/graph/shaders/line.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #version 440 layout(location = 0) in float vT; diff --git a/examples/quick/scenegraph/graph/shaders/noisy.frag b/examples/quick/scenegraph/graph/shaders/noisy.frag index 8cea9de02b..0b7cb1306b 100644 --- a/examples/quick/scenegraph/graph/shaders/noisy.frag +++ b/examples/quick/scenegraph/graph/shaders/noisy.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #version 440 layout(location = 0) in vec2 vTexCoord; diff --git a/examples/quick/scenegraph/metaltextureimport/squircle.frag b/examples/quick/scenegraph/metaltextureimport/squircle.frag index 15f34624fe..8303e97006 100644 --- a/examples/quick/scenegraph/metaltextureimport/squircle.frag +++ b/examples/quick/scenegraph/metaltextureimport/squircle.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #include <metal_stdlib> #include <simd/simd.h> diff --git a/examples/quick/scenegraph/metalunderqml/squircle.frag b/examples/quick/scenegraph/metalunderqml/squircle.frag index 15f34624fe..8303e97006 100644 --- a/examples/quick/scenegraph/metalunderqml/squircle.frag +++ b/examples/quick/scenegraph/metalunderqml/squircle.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #include <metal_stdlib> #include <simd/simd.h> diff --git a/examples/quick/scenegraph/shared/squircle_rhi.frag b/examples/quick/scenegraph/shared/squircle_rhi.frag index 8da62b93e6..835a6b2823 100644 --- a/examples/quick/scenegraph/shared/squircle_rhi.frag +++ b/examples/quick/scenegraph/shared/squircle_rhi.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #version 440 layout(location = 0) in vec2 coords; diff --git a/examples/quick/scenegraph/twotextureproviders/shaders/checker.frag b/examples/quick/scenegraph/twotextureproviders/shaders/checker.frag index 0932bc8c37..c684a2cedd 100644 --- a/examples/quick/scenegraph/twotextureproviders/shaders/checker.frag +++ b/examples/quick/scenegraph/twotextureproviders/shaders/checker.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #version 440 layout(location = 0) in vec2 qt_TexCoord0; diff --git a/examples/quick/scenegraph/twotextureproviders/shaders/xorblender.frag b/examples/quick/scenegraph/twotextureproviders/shaders/xorblender.frag index bc68160c1f..8587ae5316 100644 --- a/examples/quick/scenegraph/twotextureproviders/shaders/xorblender.frag +++ b/examples/quick/scenegraph/twotextureproviders/shaders/xorblender.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #version 440 layout(location = 0) in vec2 vTexCoord; diff --git a/examples/quick/shadereffects/content/shaders/blur.frag b/examples/quick/shadereffects/content/shaders/blur.frag index 0c914d4244..b73a213348 100644 --- a/examples/quick/shadereffects/content/shaders/blur.frag +++ b/examples/quick/shadereffects/content/shaders/blur.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #version 440 layout(location = 0) in vec2 qt_TexCoord0; diff --git a/examples/quick/shadereffects/content/shaders/colorize.frag b/examples/quick/shadereffects/content/shaders/colorize.frag index bc8067cc8c..eb50da9344 100644 --- a/examples/quick/shadereffects/content/shaders/colorize.frag +++ b/examples/quick/shadereffects/content/shaders/colorize.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #version 440 layout(location = 0) in vec2 qt_TexCoord0; diff --git a/examples/quick/shadereffects/content/shaders/outline.frag b/examples/quick/shadereffects/content/shaders/outline.frag index 26df69c5fe..11e9b74af6 100644 --- a/examples/quick/shadereffects/content/shaders/outline.frag +++ b/examples/quick/shadereffects/content/shaders/outline.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #version 440 layout(location = 0) in vec2 qt_TexCoord0; diff --git a/examples/quick/shadereffects/content/shaders/shadow.frag b/examples/quick/shadereffects/content/shaders/shadow.frag index 8247517b6d..f42fa6c0b0 100644 --- a/examples/quick/shadereffects/content/shaders/shadow.frag +++ b/examples/quick/shadereffects/content/shaders/shadow.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #version 440 layout(location = 0) in vec2 qt_TexCoord0; diff --git a/examples/quick/shadereffects/content/shaders/wobble.frag b/examples/quick/shadereffects/content/shaders/wobble.frag index a34481c2f2..a97f9d17f5 100644 --- a/examples/quick/shadereffects/content/shaders/wobble.frag +++ b/examples/quick/shadereffects/content/shaders/wobble.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + #version 440 layout(location = 0) in vec2 qt_TexCoord0; diff --git a/examples/quick/shapes/dashPattern.qml b/examples/quick/shapes/dashPattern.qml index f64f02c5d9..c427e35c38 100644 --- a/examples/quick/shapes/dashPattern.qml +++ b/examples/quick/shapes/dashPattern.qml @@ -56,45 +56,33 @@ Rectangle { width: 256 height: 256 Shape { - width: 200 - height: 150 - anchors.centerIn: parent + id: shape + anchors.fill: parent + ShapePath { - strokeWidth: 4 - strokeColor: "red" - fillGradient: RadialGradient { - centerX: 100; centerY: 100; centerRadius: 100 - SequentialAnimation on focalRadius { - loops: Animation.Infinite - NumberAnimation { from: 1; to: 20; duration: 2000 } - NumberAnimation { from: 20; to: 1; duration: 2000 } - } - SequentialAnimation on focalX { - loops: Animation.Infinite - NumberAnimation { from: 50; to: 150; duration: 3000 } - NumberAnimation { from: 150; to: 50; duration: 3000 } - } - SequentialAnimation on focalY { - loops: Animation.Infinite - NumberAnimation { from: 50; to: 150; duration: 1000 } - NumberAnimation { from: 150; to: 50; duration: 1000 } - } - GradientStop { position: 0; color: "#ffffff" } - GradientStop { position: 0.11; color: "#f9ffa0" } - GradientStop { position: 0.13; color: "#f9ff99" } - GradientStop { position: 0.14; color: "#f3ff86" } - GradientStop { position: 0.49; color: "#93b353" } - GradientStop { position: 0.87; color: "#264619" } - GradientStop { position: 0.96; color: "#0c1306" } - GradientStop { position: 1; color: "#000000" } - } - fillColor: "blue" // ignored with the gradient set + id: p + strokeWidth: 5 + strokeColor: "blue" strokeStyle: ShapePath.DashLine - dashPattern: [ 1, 4 ] - startX: 20; startY: 20 - PathLine { x: 180; y: 130 } - PathLine { x: 20; y: 130 } - PathLine { x: 20; y: 20 } + dashPattern: [ 1, 4, 4, 4 ] + fillColor: "lightBlue" + + property real xr: 70 + property real yr: 30 + startX: shape.width / 2 - xr + startY: shape.height / 2 - yr + PathArc { + x: shape.width / 2 + p.xr + y: shape.height / 2 + p.yr + radiusX: p.xr; radiusY: p.yr + useLargeArc: true + } + PathArc { + x: shape.width / 2 - p.xr + y: shape.height / 2 - p.yr + radiusX: p.xr; radiusY: p.yr + useLargeArc: true + } } } } diff --git a/examples/quick/shapes/linearGradient.qml b/examples/quick/shapes/linearGradient.qml index c427e35c38..9ac48187ff 100644 --- a/examples/quick/shapes/linearGradient.qml +++ b/examples/quick/shapes/linearGradient.qml @@ -56,32 +56,35 @@ Rectangle { width: 256 height: 256 Shape { - id: shape - anchors.fill: parent - + width: 200 + height: 150 + anchors.centerIn: parent ShapePath { - id: p - strokeWidth: 5 - strokeColor: "blue" - strokeStyle: ShapePath.DashLine - dashPattern: [ 1, 4, 4, 4 ] - fillColor: "lightBlue" - - property real xr: 70 - property real yr: 30 - startX: shape.width / 2 - xr - startY: shape.height / 2 - yr - PathArc { - x: shape.width / 2 + p.xr - y: shape.height / 2 + p.yr - radiusX: p.xr; radiusY: p.yr - useLargeArc: true + strokeWidth: 4 + strokeColor: "red" + fillGradient: LinearGradient { + x1: 20; y1: 20 + x2: 180; y2: 130 + GradientStop { position: 0; color: "blue" } + GradientStop { position: 0.2; color: "green" } + GradientStop { position: 0.4; color: "red" } + GradientStop { position: 0.6; color: "yellow" } + GradientStop { position: 1; color: "cyan" } } - PathArc { - x: shape.width / 2 - p.xr - y: shape.height / 2 - p.yr - radiusX: p.xr; radiusY: p.yr - useLargeArc: true + fillColor: "blue" // ignored with the gradient set + strokeStyle: ShapePath.DashLine + dashPattern: [ 1, 4 ] + startX: 20; startY: 20 + PathLine { x: 180; y: 130 } + PathLine { x: 20; y: 130 } + PathLine { x: 20; y: 20 } + } + transform: Rotation { origin.x: 100; origin.y: 50; axis { x: 0; y: 1; z: 0 } + SequentialAnimation on angle { + NumberAnimation { from: 0; to: 75; duration: 2000 } + NumberAnimation { from: 75; to: -75; duration: 4000 } + NumberAnimation { from: -75; to: 0; duration: 2000 } + loops: Animation.Infinite } } } diff --git a/examples/quick/shapes/radialGradient.qml b/examples/quick/shapes/radialGradient.qml index 9ac48187ff..f64f02c5d9 100644 --- a/examples/quick/shapes/radialGradient.qml +++ b/examples/quick/shapes/radialGradient.qml @@ -62,14 +62,31 @@ Rectangle { ShapePath { strokeWidth: 4 strokeColor: "red" - fillGradient: LinearGradient { - x1: 20; y1: 20 - x2: 180; y2: 130 - GradientStop { position: 0; color: "blue" } - GradientStop { position: 0.2; color: "green" } - GradientStop { position: 0.4; color: "red" } - GradientStop { position: 0.6; color: "yellow" } - GradientStop { position: 1; color: "cyan" } + fillGradient: RadialGradient { + centerX: 100; centerY: 100; centerRadius: 100 + SequentialAnimation on focalRadius { + loops: Animation.Infinite + NumberAnimation { from: 1; to: 20; duration: 2000 } + NumberAnimation { from: 20; to: 1; duration: 2000 } + } + SequentialAnimation on focalX { + loops: Animation.Infinite + NumberAnimation { from: 50; to: 150; duration: 3000 } + NumberAnimation { from: 150; to: 50; duration: 3000 } + } + SequentialAnimation on focalY { + loops: Animation.Infinite + NumberAnimation { from: 50; to: 150; duration: 1000 } + NumberAnimation { from: 150; to: 50; duration: 1000 } + } + GradientStop { position: 0; color: "#ffffff" } + GradientStop { position: 0.11; color: "#f9ffa0" } + GradientStop { position: 0.13; color: "#f9ff99" } + GradientStop { position: 0.14; color: "#f3ff86" } + GradientStop { position: 0.49; color: "#93b353" } + GradientStop { position: 0.87; color: "#264619" } + GradientStop { position: 0.96; color: "#0c1306" } + GradientStop { position: 1; color: "#000000" } } fillColor: "blue" // ignored with the gradient set strokeStyle: ShapePath.DashLine @@ -79,13 +96,5 @@ Rectangle { PathLine { x: 20; y: 130 } PathLine { x: 20; y: 20 } } - transform: Rotation { origin.x: 100; origin.y: 50; axis { x: 0; y: 1; z: 0 } - SequentialAnimation on angle { - NumberAnimation { from: 0; to: 75; duration: 2000 } - NumberAnimation { from: 75; to: -75; duration: 4000 } - NumberAnimation { from: -75; to: 0; duration: 2000 } - loops: Animation.Infinite - } - } } } diff --git a/examples/quick/shapes/shapegallery.qml b/examples/quick/shapes/shapegallery.qml index 79d438d492..3683f0a822 100644 --- a/examples/quick/shapes/shapegallery.qml +++ b/examples/quick/shapes/shapegallery.qml @@ -76,15 +76,15 @@ Rectangle { } ListElement { name: "Dash pattern" - shapeUrl: "linearGradient.qml" + shapeUrl: "dashPattern.qml" } ListElement { name: "Linear gradient" - shapeUrl: "radialGradient.qml" + shapeUrl: "linearGradient.qml" } ListElement { name: "Radial gradient" - shapeUrl: "dashPattern.qml" + shapeUrl: "radialGradient.qml" } ListElement { name: "Fill rules" diff --git a/src/particles/qquickparticlesystem.cpp b/src/particles/qquickparticlesystem.cpp index 5806d7914c..5744c61849 100644 --- a/src/particles/qquickparticlesystem.cpp +++ b/src/particles/qquickparticlesystem.cpp @@ -767,10 +767,9 @@ void QQuickParticleSystem::reset() timeInt = 0; //Clear guarded pointers which have been deleted - int cleared = 0; - cleared += m_emitters.removeAll(nullptr); - cleared += m_painters.removeAll(nullptr); - cleared += m_affectors.removeAll(nullptr); + m_emitters.removeAll(nullptr); + m_painters.removeAll(nullptr); + m_affectors.removeAll(nullptr); bySysIdx.resize(0); initGroups();//Also clears all logical particles diff --git a/src/particles/shaders_ng/imageparticle.frag b/src/particles/shaders_ng/imageparticle.frag index 90b79e6ea9..074771f4fd 100644 --- a/src/particles/shaders_ng/imageparticle.frag +++ b/src/particles/shaders_ng/imageparticle.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 #if defined(TABLE) diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp index ae50225035..9c83f8c1fd 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp @@ -224,9 +224,10 @@ bool QV4DataCollector::collectScope(QJsonObject *dict, int frameNr, int scopeNr) QV4::ScopedValue v(scope); QV4::Heap::InternalClass *ic = ctxt->internalClass(); for (uint i = 0; i < ic->size; ++i) { - QString name = ic->keyAt(i); - names.append(name); - v = static_cast<QV4::Heap::CallContext *>(ctxt->d())->locals[i]; + QV4::ScopedValue stringOrSymbol(scope, ic->keyAt(i)); + QV4::ScopedString propName(scope, stringOrSymbol->toString(scope.engine)); + names.append(propName->toQString()); + v = ctxt->getProperty(propName); collectedRefs.append(addValueRef(v)); } diff --git a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp index 85b6bac203..ca8f3e3145 100644 --- a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp @@ -493,9 +493,10 @@ void NativeDebugger::handleVariables(QJsonObject *response, const QJsonObject &a QV4::Heap::InternalClass *ic = callContext->internalClass(); QV4::ScopedValue v(scope); for (uint i = 0; i < ic->size; ++i) { - QString name = ic->keyAt(i); - v = callContext->d()->locals[i]; - collector.collect(&output, QString(), name, v); + QV4::ScopedValue stringOrSymbol(scope, ic->keyAt(i)); + QV4::ScopedString propName(scope, stringOrSymbol->toString(scope.engine)); + v = callContext->getProperty(propName); + collector.collect(&output, QString(), propName->toQString(), v); } } diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h index 8b2d5066c6..9453120eb6 100644 --- a/src/qml/common/qv4compileddata_p.h +++ b/src/qml/common/qv4compileddata_p.h @@ -1322,6 +1322,28 @@ struct TypeReferenceMap : QHash<int, TypeReference> return *insert(nameIndex, loc); } + template <typename Iterator> + void collectFromFunctions(Iterator it, Iterator end) + { + for (; it != end; ++it) { + auto formal = it->formalsBegin(); + auto formalEnd = it->formalsEnd(); + for ( ; formal != formalEnd; ++formal) { + if (!formal->type.indexIsBuiltinType()) { + TypeReference &r + = this->add(formal->type.typeNameIndexOrBuiltinType(), it->location); + r.errorWhenNotFound = true; + } + } + + if (!it->returnType.indexIsBuiltinType()) { + TypeReference &r + = this->add(it->returnType.typeNameIndexOrBuiltinType(), it->location); + r.errorWhenNotFound = true; + } + } + } + template <typename CompiledObject> void collectFromObject(const CompiledObject *obj) { @@ -1353,13 +1375,6 @@ struct TypeReferenceMap : QHash<int, TypeReference> this->add(ic->nameIndex, ic->location); } } - - template <typename Iterator> - void collectFromObjects(Iterator it, Iterator end) - { - for (; it != end; ++it) - collectFromObject(*it); - } }; using DependentTypesHasher = std::function<QByteArray()>; diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 9739c936da..814a5e8c65 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -109,10 +109,14 @@ bool Parameter::initType(QV4::CompiledData::ParameterType *paramType, const QV4: const QString typeName = stringGenerator->stringForIndex(typeNameIndex); auto builtinType = stringToBuiltinType(typeName); if (builtinType == QV4::CompiledData::BuiltinType::InvalidBuiltin) { - if (typeName.isEmpty() || !typeName.at(0).isUpper()) { + if (typeName.isEmpty() || typeName == QLatin1String("void")) { + paramType->set(true, quint32(builtinType)); + return false; + } else if (!typeName.at(0).isUpper()) { paramType->set(false, 0); return false; } + Q_ASSERT(quint32(typeNameIndex) < (1u << 31)); paramType->set(false, typeNameIndex); } else { @@ -1805,7 +1809,6 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen nextOffset += signalTableSize; quint32_le *enumOffsetTable = reinterpret_cast<quint32_le*>(objectPtr + objectToWrite->offsetToEnums); - quint32 enumTableSize = 0; char *enumPtr = objectPtr + nextOffset; for (const Enum *e = o->firstEnum(); e; e = e->next) { *enumOffsetTable++ = enumPtr - objectPtr; @@ -1820,7 +1823,6 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen *enumValueToWrite = *enumValue; int size = QV4::CompiledData::Enum::calculateSize(e->enumValues->count); - enumTableSize += size; enumPtr += size; } diff --git a/src/qml/jsapi/qjsmanagedvalue.cpp b/src/qml/jsapi/qjsmanagedvalue.cpp index ce43b958cf..85406c21b2 100644 --- a/src/qml/jsapi/qjsmanagedvalue.cpp +++ b/src/qml/jsapi/qjsmanagedvalue.cpp @@ -1123,8 +1123,11 @@ QStringList QJSManagedValue::jsMetaMembers() const const int size = heapClass->size; QStringList result; result.reserve(size); - for (int i = 0; i < size; ++i) - result.append(heapClass->keyAt(i)); + QV4::Scope scope(c->engine()); + for (int i = 0; i < size; ++i) { + QV4::ScopedValue key(scope, heapClass->keyAt(i)); + result.append(key->toQString()); + } return result; } diff --git a/src/qml/jsruntime/qv4compilationunitmapper_unix.cpp b/src/qml/jsruntime/qv4compilationunitmapper_unix.cpp index a9ab2f5ccb..b66e6b9467 100644 --- a/src/qml/jsruntime/qv4compilationunitmapper_unix.cpp +++ b/src/qml/jsruntime/qv4compilationunitmapper_unix.cpp @@ -79,6 +79,16 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co // Data structure and qt version matched, so now we can access the rest of the file safely. length = static_cast<size_t>(lseek(fd, 0, SEEK_END)); + /* Error out early on file corruption. We assume we can read header.unitSize bytes + later (even before verifying the checksum), potentially causing out-of-bound + reads + Also, no need to wait until checksum verification if we know beforehand + that the cached unit is bogus + */ + if (length != header.unitSize) { + *errorString = QStringLiteral("Potential file corruption, file too small"); + return nullptr; + } void *ptr = mmap(nullptr, length, PROT_READ, MAP_SHARED, fd, /*offset*/0); if (ptr == MAP_FAILED) { diff --git a/src/qml/jsruntime/qv4compilationunitmapper_win.cpp b/src/qml/jsruntime/qv4compilationunitmapper_win.cpp index b4f0a6ff4d..de950ece05 100644 --- a/src/qml/jsruntime/qv4compilationunitmapper_win.cpp +++ b/src/qml/jsruntime/qv4compilationunitmapper_win.cpp @@ -86,6 +86,23 @@ CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, co // Data structure and qt version matched, so now we can access the rest of the file safely. + /* Error out early on file corruption. We assume we can read header.unitSize bytes + later (even before verifying the checksum), potentially causing out-of-bound + reads + Also, no need to wait until checksum verification if we know beforehand + that the cached unit is bogus + */ + LARGE_INTEGER fileSize; + if (!GetFileSizeEx(handle, &fileSize)) { + *errorString = QStringLiteral("Could not determine file size"); + return nullptr; + } + if (header.unitSize != fileSize.QuadPart) { + *errorString = QStringLiteral("Potential file corruption, file too small"); + return nullptr; + } + + HANDLE fileMappingHandle = CreateFileMapping(handle, 0, PAGE_READONLY, 0, 0, 0); if (!fileMappingHandle) { *errorString = qt_error_string(GetLastError()); diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 282046f3fa..c3df66f67e 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -334,9 +334,14 @@ ReturnedValue ExecutionContext::getProperty(String *name) case Heap::ExecutionContext::Type_CallContext: { Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx); - uint index = c->internalClass->indexOfValueOrGetter(id); - if (index < UINT_MAX) + const uint index = c->internalClass->indexOfValueOrGetter(id); + if (index < c->locals.alloc) return c->locals[index].asReturnedValue(); + + // TODO: We should look up the module imports here, but those are part of the CU: + // imports[index - c->locals.size]; + // See QTBUG-118478 + Q_FALLTHROUGH(); } case Heap::ExecutionContext::Type_WithContext: @@ -384,9 +389,14 @@ ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base) case Heap::ExecutionContext::Type_CallContext: { Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx); - uint index = c->internalClass->indexOfValueOrGetter(id); - if (index < UINT_MAX) + const uint index = c->internalClass->indexOfValueOrGetter(id); + if (index < c->locals.alloc) return c->locals[index].asReturnedValue(); + + // TODO: We should look up the module imports here, but those are part of the CU: + // imports[index - c->locals.size]; + // See QTBUG-118478 + Q_FALLTHROUGH(); } case Heap::ExecutionContext::Type_GlobalContext: { diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 0927687578..b303dd497a 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -2503,6 +2503,13 @@ bool ExecutionEngine::metaTypeFromJS(const Value &value, QMetaType metaType, voi return true; } } + + if (metaType == QMetaType::fromType<QQmlListProperty<QObject>>()) { + if (const QV4::QmlListWrapper *wrapper = value.as<QV4::QmlListWrapper>()) { + *reinterpret_cast<QQmlListProperty<QObject> *>(data) = wrapper->d()->property(); + return true; + } + } } { diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp index 7fe3862172..ba10d29d51 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit.cpp +++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp @@ -517,6 +517,15 @@ int ExecutableCompilationUnit::totalObjectCount() const { return inlineComponentData[icRoot].totalObjectCount; } +ResolvedTypeReference *ExecutableCompilationUnit::resolvedType(QMetaType type) const +{ + for (ResolvedTypeReference *ref : std::as_const(resolvedTypes)) { + if (ref->type().typeId() == type) + return ref; + } + return nullptr; +} + int ExecutableCompilationUnit::totalParserStatusCount() const { if (icRoot == -1) return m_totalParserStatusCount; diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h index 9ceec1fbf7..38d35baf3f 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit_p.h +++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h @@ -175,6 +175,7 @@ public: QVector<QQmlRefPointer<QQmlScriptData>> dependentScripts; ResolvedTypeReferenceMap resolvedTypes; ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); } + ResolvedTypeReference *resolvedType(QMetaType type) const; bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const; diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index eabb220c50..fdaa8cbaa4 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -329,9 +329,15 @@ void InternalClass::destroy() Base::destroy(); } -QString InternalClass::keyAt(uint index) const -{ - return nameMap.at(index).toQString(); +ReturnedValue InternalClass::keyAt(uint index) const +{ + PropertyKey key = nameMap.at(index); + if (!key.isValid()) + return Encode::undefined(); + if (key.isArrayIndex()) + return Encode(key.asArrayIndex()); + Q_ASSERT(key.isStringOrSymbol()); + return key.asStringOrSymbol()->asReturnedValue(); } void InternalClass::changeMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry) diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h index 37dbeded6f..a80ec2e957 100644 --- a/src/qml/jsruntime/qv4internalclass_p.h +++ b/src/qml/jsruntime/qv4internalclass_p.h @@ -343,7 +343,7 @@ struct InternalClass : Base { void init(InternalClass *other); void destroy(); - Q_QML_PRIVATE_EXPORT QString keyAt(uint index) const; + Q_QML_PRIVATE_EXPORT ReturnedValue keyAt(uint index) const; Q_REQUIRED_RESULT InternalClass *nonExtensible(); static void addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry); diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h index 301dad38fd..382f6c684a 100644 --- a/src/qml/jsruntime/qv4lookup_p.h +++ b/src/qml/jsruntime/qv4lookup_p.h @@ -230,10 +230,6 @@ struct Q_QML_PRIVATE_EXPORT Lookup { markDef.h2->mark(stack); } - void clear() { - memset(&markDef, 0, sizeof(markDef)); - } - void releasePropertyCache() { if (getter == getterQObject diff --git a/src/qml/jsruntime/qv4module.cpp b/src/qml/jsruntime/qv4module.cpp index 26bef9cd37..548dd7be25 100644 --- a/src/qml/jsruntime/qv4module.cpp +++ b/src/qml/jsruntime/qv4module.cpp @@ -258,9 +258,12 @@ OwnPropertyKeyIterator *Module::virtualOwnPropertyKeys(const Object *o, Value *t if (module->d()->unit->isESModule()) { names = module->d()->unit->exportedNames(); } else { - Heap::InternalClass *scopeClass = module->d()->scope->internalClass; - for (uint i = 0; i < scopeClass->size; ++i) - names << scopeClass->keyAt(i); + QV4::Scope scope(module->engine()); + QV4::Scoped<InternalClass> scopeClass(scope, module->d()->scope->internalClass); + for (uint i = 0, end = scopeClass->d()->size; i < end; ++i) { + QV4::ScopedValue key(scope, scopeClass->d()->keyAt(i)); + names << key->toQString(); + } } return new ModuleNamespaceIterator(names); diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index 1b737ee308..c5ec43bbb7 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -1059,7 +1059,7 @@ void AOTCompiledContext::storeNameSloppy(uint nameIndex, void *value, QMetaType // the property cache we store a value into the property. QV4::Lookup l; - l.clear(); + memset(&l, 0, sizeof(QV4::Lookup)); l.nameIndex = nameIndex; ObjectPropertyResult storeResult = ObjectPropertyResult::NeedsInit; switch (initObjectLookup(this, &l, qmlScopeObject, QMetaType())) { diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index fc629bc060..b544852953 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -901,10 +901,13 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper && !(bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver) && !_valueTypeProperty; - if (_ddata->hasBindingBit(bindingProperty->coreIndex()) && allowedToRemoveBinding) { - QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex())); - } else if (bindingProperty->isBindable() && allowedToRemoveBinding) { - removePendingBinding(_bindingTarget, bindingProperty->coreIndex()); + if (allowedToRemoveBinding) { + if (bindingProperty->isBindable()) { + removePendingBinding(_bindingTarget, bindingProperty->coreIndex()); + } else { + QQmlPropertyPrivate::removeBinding( + _bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex())); + } } if (bindingType == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) { @@ -950,6 +953,9 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper qmlBinding = QQmlPropertyBinding::create(bindingProperty, runtimeFunction, _scopeObject, context, currentQmlContext(), _bindingTarget, index); } sharedState.data()->allQPropertyBindings.push_back(DeferredQPropertyBinding {_bindingTarget, bindingProperty->coreIndex(), qmlBinding }); + + QQmlData *data = QQmlData::get(_bindingTarget, true); + data->setBindingBit(_bindingTarget, bindingProperty->coreIndex()); } else { // When writing bindings to grouped properties implemented as value types, // such as point.x: { someExpression; }, then the binding is installed on @@ -1467,17 +1473,27 @@ bool QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt) while (!sharedState->allQPropertyBindings.isEmpty()) { auto& [target, index, qmlBinding] = sharedState->allQPropertyBindings.first(); + + QQmlData *data = QQmlData::get(target); + if (!data || !data->hasBindingBit(index)) { + // The target property has been overwritten since we stashed the binding. + sharedState->allQPropertyBindings.pop_front(); + continue; + } + QUntypedBindable bindable; void *argv[] = { &bindable }; // allow interception target->metaObject()->metacall(target, QMetaObject::BindableProperty, index, argv); const bool success = bindable.setBinding(qmlBinding); + const auto bindingPrivateRefCount = QPropertyBindingPrivate::get(qmlBinding)->ref; + // Only pop_front after setting the binding as the bindings are refcounted. sharedState->allQPropertyBindings.pop_front(); // If the binding was actually not set, it's deleted now. - if (success) { + if (success && bindingPrivateRefCount > 1) { if (auto priv = QPropertyBindingPrivate::get(qmlBinding); priv->hasCustomVTable()) { auto qmlBindingPriv = static_cast<QQmlPropertyBinding *>(priv); auto jsExpression = qmlBindingPriv->jsExpression(); diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h index c415b5f33a..3ce665c24f 100644 --- a/src/qml/qml/qqmlpropertycachecreator_p.h +++ b/src/qml/qml/qqmlpropertycachecreator_p.h @@ -932,53 +932,74 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor QQmlPropertyData *targetProperty = targetCache->property(coreIndex); Q_ASSERT(targetProperty); + const QMetaType targetPropType = targetProperty->propType(); + + const auto resolveType = [](QMetaType targetPropType) { + if (targetPropType.flags() & QMetaType::IsEnumeration) + return QMetaType::fromType<int>(); + else + return targetPropType; + }; + + const auto populateWithPropertyData = [&](const QQmlPropertyData *property) { + *type = resolveType(property->propType()); + writable = property->isWritable(); + resettable = property->isResettable(); + bindable = property->isBindable(); + + // Copy type flags + propertyFlags->copyPropertyTypeFlags(property->flags()); + if (property->isVarProperty()) + propertyFlags->type = QQmlPropertyData::Flags::QVariantType; + }; + // for deep aliases, valueTypeIndex is always set - if (!QQmlMetaType::isValueType(targetProperty->propType()) && valueTypeIndex != -1) { + if (!QQmlMetaType::isValueType(targetPropType) && valueTypeIndex != -1) { // deep alias property - *type = targetProperty->propType(); - targetCache = enginePriv->propertyCacheForType(type->id()); - Q_ASSERT(targetCache); - targetProperty = targetCache->property(valueTypeIndex); - if (targetProperty == nullptr) { - return qQmlCompileError(alias.referenceLocation, - QQmlPropertyCacheCreatorBase::tr("Invalid alias target")); + QQmlRefPointer<QQmlPropertyCache> typeCache + = enginePriv->propertyCacheForType(targetPropType.id()); + + if (!typeCache) { + // See if it's a half-resolved composite type + if (const QV4::ResolvedTypeReference *typeRef + = objectContainer->resolvedType(targetPropType)) { + typeCache = typeRef->typePropertyCache(); + } } - *type = targetProperty->propType(); - writable = targetProperty->isWritable(); - resettable = targetProperty->isResettable(); - bindable = targetProperty->isBindable(); + const QQmlPropertyData *typeProperty = typeCache + ? typeCache->property(valueTypeIndex) + : nullptr; + if (typeProperty == nullptr) { + return qQmlCompileError( + alias.referenceLocation, + QQmlPropertyCacheCreatorBase::tr("Invalid alias target")); + } + populateWithPropertyData(typeProperty); } else { // value type or primitive type or enum - *type = targetProperty->propType(); - - writable = targetProperty->isWritable(); - resettable = targetProperty->isResettable(); - bindable = targetProperty->isBindable(); + populateWithPropertyData(targetProperty); if (valueTypeIndex != -1) { - const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForValueType(*type); - if (valueTypeMetaObject->property(valueTypeIndex).isEnumType()) - *type = QMetaType::fromType<int>(); - else - *type = valueTypeMetaObject->property(valueTypeIndex).metaType(); - } else { - if (targetProperty->isEnum()) { - *type = QMetaType::fromType<int>(); - } else { - // Copy type flags - propertyFlags->copyPropertyTypeFlags(targetProperty->flags()); - - if (targetProperty->isVarProperty()) - propertyFlags->type = QQmlPropertyData::Flags::QVariantType; - } + const QMetaObject *valueTypeMetaObject + = QQmlMetaType::metaObjectForValueType(*type); + const QMetaProperty valueTypeMetaProperty + = valueTypeMetaObject->property(valueTypeIndex); + *type = resolveType(valueTypeMetaProperty.metaType()); + + // We can only write or reset the value type property if we can write + // the value type itself. + resettable = writable && valueTypeMetaProperty.isResettable(); + writable = writable && valueTypeMetaProperty.isWritable(); + + bindable = valueTypeMetaProperty.isBindable(); } } } - propertyFlags->setIsWritable(!(alias.hasFlag(QV4::CompiledData::Alias::IsReadOnly)) - && writable); + propertyFlags->setIsWritable( + writable && !alias.hasFlag(QV4::CompiledData::Alias::IsReadOnly)); propertyFlags->setIsResettable(resettable); propertyFlags->setIsBindable(bindable); return QQmlError(); diff --git a/src/qml/qml/qqmltypecompiler_p.h b/src/qml/qml/qqmltypecompiler_p.h index 1a100828f8..5b92b8de4a 100644 --- a/src/qml/qml/qqmltypecompiler_p.h +++ b/src/qml/qml/qqmltypecompiler_p.h @@ -132,6 +132,15 @@ public: return resolvedTypes->value(id); } + QV4::ResolvedTypeReference *resolvedType(QMetaType type) const + { + for (QV4::ResolvedTypeReference *ref : std::as_const(*resolvedTypes)) { + if (ref->type().typeId() == type) + return ref; + } + return nullptr; + } + CompositeMetaTypeIds typeIdsForComponent(int objectId = 0) const; private: diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp index fe9729cf75..a244bdd0ba 100644 --- a/src/qml/qml/qqmltypedata.cpp +++ b/src/qml/qml/qqmltypedata.cpp @@ -160,6 +160,9 @@ bool QQmlTypeData::tryLoadFromDiskCache() for (int i = 0, count = m_compiledData->objectCount(); i < count; ++i) { auto object = m_compiledData->objectAt(i); m_typeReferences.collectFromObject(object); + m_typeReferences.collectFromFunctions( + m_compiledData->objectFunctionsBegin(object), + m_compiledData->objectFunctionsEnd(object)); const auto inlineComponentTable = object->inlineComponentTable(); for (auto i = 0; i != object->nInlineComponents; ++i) { ics.push_back(inlineComponentTable[i]); @@ -660,7 +663,13 @@ void QQmlTypeData::continueLoadFromIR() } } - m_typeReferences.collectFromObjects(m_document->objects.constBegin(), m_document->objects.constEnd()); + for (auto it = m_document->objects.constBegin(), end = m_document->objects.constEnd(); + it != end; ++it) { + const QmlIR::Object *object = *it; + m_typeReferences.collectFromObject(object); + m_typeReferences.collectFromFunctions(object->functionsBegin(), object->functionsEnd()); + } + m_importCache.setBaseUrl(finalUrl(), finalUrlString()); // For remote URLs, we don't delay the loading of the implicit import diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 93736b0002..ce245ea6ce 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -91,8 +91,25 @@ const QMetaObject *QQmlTypeWrapper::metaObject() const if (!type.isValid()) return nullptr; - if (type.isSingleton()) - return type.metaObject(); + if (type.isSingleton()) { + auto metaObjectCandidate = type.metaObject(); + // if the candidate is the same as te baseMetaObject, we know that + // we don't have an extended singleton; in that case the + // actual instance might be subclass of type instead of type itself + // so we need to query the actual object for it's meta-object + if (metaObjectCandidate == type.baseMetaObject()) { + QQmlEnginePrivate *qmlEngine = QQmlEnginePrivate::get(engine()->qmlEngine()); + auto object = qmlEngine->singletonInstance<QObject *>(type); + if (object) + return object->metaObject(); + } + /* if we instead have an extended singleton, the dynamic proxy + meta-object must alreday be set up correctly + ### TODO: it isn't, as QQmlTypePrivate::init has no way to + query the object + */ + return metaObjectCandidate; + } return type.attachedPropertiesType(QQmlEnginePrivate::get(engine()->qmlEngine())); } diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index b6f68536ca..053058341a 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -925,15 +925,20 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * int coreIndex = encodedIndex.coreIndex(); const int valueTypePropertyIndex = encodedIndex.valueTypeIndex(); - // Remove binding (if any) on write - if(c == QMetaObject::WriteProperty) { - int flags = *reinterpret_cast<int*>(a[3]); - if (flags & QQmlPropertyData::RemoveBindingOnAliasWrite) { - QQmlData *targetData = QQmlData::get(target); - if (targetData && targetData->hasBindingBit(coreIndex)) - QQmlPropertyPrivate::removeBinding(target, encodedIndex); + const auto removePendingBinding + = [c, a](QObject *target, int coreIndex, QQmlPropertyIndex encodedIndex) { + // Remove binding (if any) on write + if (c == QMetaObject::WriteProperty) { + int flags = *reinterpret_cast<int*>(a[3]); + if (flags & QQmlPropertyData::RemoveBindingOnAliasWrite) { + QQmlData *targetData = QQmlData::get(target); + if (targetData && targetData->hasBindingBit(coreIndex)) { + QQmlPropertyPrivate::removeBinding(target, encodedIndex); + targetData->clearBindingBit(coreIndex); + } + } } - } + }; if (valueTypePropertyIndex != -1) { if (!targetDData->propertyCache) @@ -943,6 +948,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance( ctxt->engine(), pd->propType()); if (valueType) { + removePendingBinding(target, coreIndex, encodedIndex); valueType->read(target, coreIndex); int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a); @@ -954,10 +960,14 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * // deep alias void *argv[1] = { &target }; QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex, argv); + removePendingBinding( + target, valueTypePropertyIndex, + QQmlPropertyIndex(valueTypePropertyIndex)); return QMetaObject::metacall(target, c, valueTypePropertyIndex, a); } } else { + removePendingBinding(target, coreIndex, encodedIndex); return QMetaObject::metacall(target, c, coreIndex, a); } diff --git a/src/qmltest/SignalSpy.qml b/src/qmltest/SignalSpy.qml index 7257e4f3f3..641f8642c6 100644 --- a/src/qmltest/SignalSpy.qml +++ b/src/qmltest/SignalSpy.qml @@ -81,6 +81,16 @@ Item { id: spy visible: false + Component.onDestruction: { + // We are potentially destroyed before the target object, + // and since only the sender (target) being destroyed destroys a connection + // in QML, and not the receiver (us/"spy"), we need to manually disconnect. + // When QTBUG-118166 is implemented, we can remove this. + let signalFunc = target ? target[signalName] : null + if (signalFunc) + signalFunc.disconnect(spy.qtest_activated) + } + TestUtil { id: util } diff --git a/src/qmltest/TestCase.qml b/src/qmltest/TestCase.qml index 5a2cd1d5c4..2b817ad7dd 100644 --- a/src/qmltest/TestCase.qml +++ b/src/qmltest/TestCase.qml @@ -260,6 +260,105 @@ import "testlogger.js" as TestLogger of \l Component, the \l createTemporaryObject() function can be used. \sa {QtTest::SignalSpy}{SignalSpy}, {Qt Quick Test} + + \section1 Separating tests from application logic + + In most cases, you would want to separate your tests from the application + logic by splitting them into different projects and linking them. + + For example, you could have the following project structure: + + \badcode + . + | — CMakeLists.txt + | — src + | | — main.cpp + | — qml + | | — main.qml + | — modules + | | — MyModule + | | — MyButton.qml + | | — CMakeLists.txt + | — tests + | — UnitQMLTests + | — tst_testqml.qml + | — tests_main.cpp + | — tests_setup.cpp + | — tests_setup.h + \endcode + + Now, to test \c modules/MyModule/MyButton.qml, create a library for + \c MyModule in \c modules/MyModule/CMakeLists.txt and link it to your + test project, \c tests/UnitQMLTests/CMakeLists.txt: + + \if defined(onlinedocs) + \tab {build-qt-app}{tab-cmake-add-library}{modules/MyModule/CMakeLists.txt}{checked} + \tab {build-qt-app}{tab-cmake-link-against-library}{tests/UnitQMLTests/CMakeLists.txt}{} + \tab {build-qt-app}{tab-tests_main}{tests/UnitQMLTests/tests_main.cpp}{} + \tab {build-qt-app}{tab-tests-setup-cpp}{tests/UnitQMLTests/tests_setup.cpp}{} + \tab {build-qt-app}{tab-tests-setup-h}{tests/UnitQMLTests/tests_setup.h}{} + \tabcontent {tab-cmake-add-library} + \else + \section1 Add library + \endif + \dots + \snippet modules_MyModule_CMakeLists.txt add library + \dots + \if defined(onlinedocs) + \endtabcontent + \tabcontent {tab-cmake-link-against-library} + \else + \section1 Link against library + \endif + \dots + \snippet tests_UnitQMLTests_CMakeLists.txt link against library + \dots + \if defined(onlinedocs) + \endtabcontent + \tabcontent {tab-tests_main} + \else + \section1 main.cpp + \endif + \snippet tests_main.cpp main + \if defined(onlinedocs) + \endtabcontent + \tabcontent {tab-tests-setup-cpp} + \else + \section1 setup c++ + \endif + \snippet tests_setup.cpp setup + \if defined(onlinedocs) + \endtabcontent + \tabcontent {tab-tests-setup-h} + \else + \section1 setup header + \endif + \snippet tests_setup.h setup + \if defined(onlinedocs) + \endtabcontent + \endif + + Then, in \c tests/UnitQMLTests/tst_testqml.qml, you can import + \c modules/MyModule/MyButton.qml: + + \if defined(onlinedocs) + \tab {test-qml}{tab-qml-import}{tests/UnitQMLTests/tst_testqml.qml}{checked} + \tab {test-qml}{tab-qml-my-button}{modules/MyModule/MyButton.qml}{} + \tabcontent {tab-qml-import} + \else + \section1 Import QML + \endif + \snippet tests_UnitQMLTests_tst_testqml.qml import + \if defined(onlinedocs) + \endtabcontent + \tabcontent {tab-qml-my-button} + \else + \section1 Define QML button + \endif + \snippet modules_MyModule_MyButton.qml define + \if defined(onlinedocs) + \endtabcontent + \endif */ diff --git a/src/qmltest/doc/snippets/modules_MyModule_CMakeLists.txt b/src/qmltest/doc/snippets/modules_MyModule_CMakeLists.txt new file mode 100644 index 0000000000..37ac70aaa2 --- /dev/null +++ b/src/qmltest/doc/snippets/modules_MyModule_CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.20) + +set(MODULE_NAME "MyModule") +project(${MODULE_NAME} LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) +set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick) + +file(GLOB QML_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.qml) +source_group("Qml Files" FILES ${QML_SOURCES}) + +//! [add library] +qt_add_library(MyModule STATIC) + +qt6_add_qml_module(MyModule + URI MyModule + VERSION 1.0 + QML_FILES ${QML_SOURCES} +) +//! [add library] + +set_target_properties(MyModule PROPERTIES + MACOSX_BUNDLE TRUE + WIN32_EXECUTABLE FALSE +) + +target_link_libraries(MyModule PRIVATE + Qt::Core + Qt::Gui + Qt::Qml + Qt::Quick +) + +target_include_directories(MyModule PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/qmltest/doc/snippets/modules_MyModule_MyButton.qml b/src/qmltest/doc/snippets/modules_MyModule_MyButton.qml new file mode 100644 index 0000000000..5d7dd9c7dd --- /dev/null +++ b/src/qmltest/doc/snippets/modules_MyModule_MyButton.qml @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2023 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +//! [define] +import QtQuick +import QtQuick.Controls + +Button { + width: 50 + height: 50 + onClicked: width = 100 +} +//! [define] diff --git a/src/qmltest/doc/snippets/tests_UnitQMLTests_CMakeLists.txt b/src/qmltest/doc/snippets/tests_UnitQMLTests_CMakeLists.txt new file mode 100644 index 0000000000..ba444c2cd6 --- /dev/null +++ b/src/qmltest/doc/snippets/tests_UnitQMLTests_CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.2) + +project(TestQML LANGUAGES CXX) + +enable_testing() + +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS QuickTest Qml) +find_package(Qt6 REQUIRED COMPONENTS QuickTest Qml) + +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +# no need to copy around qml test files for shadow builds - just set the respective define +add_definitions(-DQUICK_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}") + +//! [link against library] +add_executable(TestQML tests_main.cpp + tests_setup.cpp tests_setup.h) + +add_test(NAME TestQML COMMAND TestQML) + +target_link_libraries( + TestQML + PRIVATE Qt6::QuickTest + PRIVATE Qt6::Qml + PRIVATE MyModule + PRIVATE MyModuleplugin +) +//! [link against library] diff --git a/src/qmltest/doc/snippets/tests_UnitQMLTests_tst_testqml.qml b/src/qmltest/doc/snippets/tests_UnitQMLTests_tst_testqml.qml new file mode 100644 index 0000000000..432d20d762 --- /dev/null +++ b/src/qmltest/doc/snippets/tests_UnitQMLTests_tst_testqml.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2023 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation 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] +import QtQuick +import QtQuick.Controls + +import QtTest +import MyModule + +Item { + width: 800 + height: 600 + + MyButton { + id: myButton + anchors.centerIn: parent + } + + TestCase { + name: "MyButton" + when: windowShown + + function test_clickToExpand() { + const widthBeforeClick = myButton.width; + mouseClick(myButton); + const widthAfterClick = myButton.width; + verify(widthBeforeClick < widthAfterClick); + } + } +} +//! [import] diff --git a/src/qmltest/doc/snippets/tests_main.cpp b/src/qmltest/doc/snippets/tests_main.cpp new file mode 100644 index 0000000000..983f932acd --- /dev/null +++ b/src/qmltest/doc/snippets/tests_main.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2023 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +//! [main] +#include <QtQuickTest/quicktest.h> +#include "tests_setup.h" + +QUICK_TEST_MAIN_WITH_SETUP(TestQML, Setup) +//! [main] diff --git a/src/qmltest/doc/snippets/tests_setup.cpp b/src/qmltest/doc/snippets/tests_setup.cpp new file mode 100644 index 0000000000..f7914dda87 --- /dev/null +++ b/src/qmltest/doc/snippets/tests_setup.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2023 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +//! [setup] +#include "tests_setup.h" + +void Setup::applicationAvailable() +{ + // custom code that doesn't require QQmlEngine +} + +void Setup::qmlEngineAvailable(QQmlEngine *engine) +{ + // add import paths + engine->addImportPath("../../"); +} + +void Setup::cleanupTestCase() +{ + // custom code to clean up before destruction starts +} +//! [setup] diff --git a/src/qmltest/doc/snippets/tests_setup.h b/src/qmltest/doc/snippets/tests_setup.h new file mode 100644 index 0000000000..f5baa04eeb --- /dev/null +++ b/src/qmltest/doc/snippets/tests_setup.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2023 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation 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$ +** +****************************************************************************/ + +//! [setup] +#ifndef SETUP_H +#define SETUP_H + +#include <QObject> +#include <QQmlEngine> + +class Setup : public QObject +{ + Q_OBJECT +public: + Setup() = default; + +public slots: + void applicationAvailable(); + void qmlEngineAvailable(QQmlEngine *engine); + void cleanupTestCase(); +}; + +#endif // SETUP_H +//! [setup] diff --git a/src/quick/doc/snippets/qml/pathview/pathview.qml b/src/quick/doc/snippets/qml/pathview/pathview.qml index 58d19b1a0c..0c3b96bb26 100644 --- a/src/quick/doc/snippets/qml/pathview/pathview.qml +++ b/src/quick/doc/snippets/qml/pathview/pathview.qml @@ -59,15 +59,20 @@ Rectangle { id: delegate Column { id: wrapper + + required property url icon + required property string name + opacity: PathView.isCurrentItem ? 1 : 0.5 + Image { anchors.horizontalCenter: nameText.horizontalCenter width: 64; height: 64 - source: icon + source: wrapper.icon } Text { id: nameText - text: name + text: wrapper.name font.pointSize: 16 } } diff --git a/src/quick/handlers/qquickpointerdevicehandler.cpp b/src/quick/handlers/qquickpointerdevicehandler.cpp index 69080b2027..a016ba5f12 100644 --- a/src/quick/handlers/qquickpointerdevicehandler.cpp +++ b/src/quick/handlers/qquickpointerdevicehandler.cpp @@ -306,7 +306,7 @@ bool QQuickPointerDeviceHandler::wantsPointerEvent(QPointerEvent *event) if (d->acceptedModifiers != Qt::KeyboardModifierMask && event->modifiers() != d->acceptedModifiers) return false; // Some handlers (HoverHandler, PinchHandler) set acceptedButtons to Qt::NoButton to indicate that button state is irrelevant. - if (event->pointingDevice()->pointerType() != QPointingDevice::PointerType::Finger && + if (event->pointingDevice()->type() != QPointingDevice::DeviceType::TouchScreen && acceptedButtons() != Qt::NoButton && event->type() != QEvent::Wheel && (static_cast<QSinglePointEvent *>(event)->buttons() & acceptedButtons()) == 0 && (static_cast<QSinglePointEvent *>(event)->button() & acceptedButtons()) == 0) diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp index 3abb366676..2b907d3805 100644 --- a/src/quick/handlers/qquicktaphandler.cpp +++ b/src/quick/handlers/qquicktaphandler.cpp @@ -121,15 +121,16 @@ bool QQuickTapHandler::wantsEventPoint(const QPointerEvent *event, const QEventP ret = parentContains(point); break; case QEventPoint::Updated: + ret = point.id() == this->point().id(); switch (m_gesturePolicy) { case DragThreshold: - ret = !overThreshold && parentContains(point); + ret = ret && !overThreshold && parentContains(point); break; case WithinBounds: - ret = parentContains(point); + ret = ret && parentContains(point); break; case ReleaseWithinBounds: - ret = point.id() == this->point().id(); + // no change to ret: depends only whether it's the already-tracking point ID break; } break; diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index 1f5c55cffe..b1733b1791 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -197,9 +197,7 @@ qreal QQuickLoaderPrivate::getImplicitHeight() const \section2 Loader Sizing Behavior - If the source component is not an Item type, Loader does not - apply any special sizing rules. When used to load visual types, - Loader applies the following sizing rules: + When used to load visual types, Loader applies the following sizing rules: \list \li If an explicit size is not specified for the Loader, the Loader @@ -226,6 +224,8 @@ qreal QQuickLoaderPrivate::getImplicitHeight() const \li The red rectangle will be 50x50, centered in the root item. \endtable + If the source component is not an Item type, Loader does not apply any + special sizing rules. \section2 Receiving Signals from Loaded Objects diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index 8687de8f43..d4b6e4c963 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -687,7 +687,7 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event, RemapEventPoints emit released(_releasedTouchPoints); if (moved) emit updated(_movedTouchPoints); - if (started) + if (started && !_pressedTouchPoints.isEmpty()) emit pressed(_pressedTouchPoints); if (ended || moved || started) emit touchUpdated(_touchPoints.values()); } @@ -732,12 +732,15 @@ void QQuickMultiPointTouchArea::addTouchPoint(const QEventPoint *p) void QQuickMultiPointTouchArea::addTouchPoint(const QMouseEvent *e) { QQuickTouchPoint *dtp = nullptr; - for (QQuickTouchPoint *tp : qAsConst(_touchPrototypes)) + for (QQuickTouchPoint *tp : qAsConst(_touchPrototypes)) { if (!tp->inUse()) { tp->setInUse(true); dtp = tp; break; + } else if (_mouseTouchPoint == tp) { + return; // do not allow more than one touchpoint to react to the mouse (QTBUG-83662) } + } if (dtp == nullptr) dtp = new QQuickTouchPoint(false); diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index 9f259166df..f8f56557ae 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -1593,21 +1593,22 @@ void QQuickTableViewPrivate::forceLayout() const QSize actualTableSize = calculateTableSize(); if (tableSize != actualTableSize) { - // This can happen if the app is calling forceLayout while - // the model is updated, but before we're notified about it. - rebuildOptions = RebuildOption::All; - } else { - // Resizing a column (or row) can result in the table going from being - // e.g completely inside the viewport to go outside. And in the latter - // case, the user needs to be able to scroll the viewport, also if - // flags such as Flickable.StopAtBounds is in use. So we need to - // update contentWidth/Height to support that case. - rebuildOptions = RebuildOption::LayoutOnly - | RebuildOption::CalculateNewContentWidth - | RebuildOption::CalculateNewContentHeight - | checkForVisibilityChanges(); + // The table size will have changed if forceLayout is called after + // the row count in the model has changed, but before we received + // a rowsInsertedCallback about it (and vice versa for columns). + rebuildOptions |= RebuildOption::ViewportOnly; } + // Resizing a column (or row) can result in the table going from being + // e.g completely inside the viewport to go outside. And in the latter + // case, the user needs to be able to scroll the viewport, also if + // flags such as Flickable.StopAtBounds is in use. So we need to + // update contentWidth/Height to support that case. + rebuildOptions |= RebuildOption::LayoutOnly + | RebuildOption::CalculateNewContentWidth + | RebuildOption::CalculateNewContentHeight + | checkForVisibilityChanges(); + scheduleRebuildTable(rebuildOptions); auto rootView = rootSyncView(); @@ -3232,9 +3233,6 @@ QVariant QQuickTableViewPrivate::modelImpl() const void QQuickTableViewPrivate::setModelImpl(const QVariant &newModel) { - if (newModel == assignedModel) - return; - assignedModel = newModel; scheduleRebuildTable(QQuickTableViewPrivate::RebuildOption::All); emit q_func()->modelChanged(); @@ -3242,7 +3240,7 @@ void QQuickTableViewPrivate::setModelImpl(const QVariant &newModel) void QQuickTableViewPrivate::syncModel() { - if (modelVariant == assignedModel) + if (compareModel(modelVariant, assignedModel)) return; if (model) { @@ -3498,6 +3496,13 @@ void QQuickTableViewPrivate::modelResetCallback() scheduleRebuildTable(RebuildOption::All); } +bool QQuickTableViewPrivate::compareModel(const QVariant& model1, const QVariant& model2) const +{ + return (model1 == model2 || + (model1.userType() == qMetaTypeId<QJSValue>() && model2.userType() == qMetaTypeId<QJSValue>() && + model1.value<QJSValue>().strictlyEquals(model2.value<QJSValue>()))); +} + void QQuickTableViewPrivate::scheduleRebuildIfFastFlick() { Q_Q(QQuickTableView); @@ -3727,6 +3732,9 @@ QVariant QQuickTableView::model() const void QQuickTableView::setModel(const QVariant &newModel) { + if (d_func()->compareModel(newModel, d_func()->assignedModel)) + return; + return d_func()->setModelImpl(newModel); } diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h index 9893cd97e7..3f969ab195 100644 --- a/src/quick/items/qquicktableview_p_p.h +++ b/src/quick/items/qquicktableview_p_p.h @@ -249,7 +249,7 @@ public: // When the applications assignes a new model or delegate to the view, we keep them // around until we're ready to take them into use (syncWithPendingChanges). QVariant assignedModel = QVariant(int(0)); - QQmlComponent *assignedDelegate = nullptr; + QQmlGuard<QQmlComponent> assignedDelegate; // loadedRows/Columns describes the rows and columns that are currently loaded (from top left // row/column to bottom right row/column). loadedTableOuterRect describes the actual @@ -477,6 +477,7 @@ public: void columnsRemovedCallback(const QModelIndex &parent, int begin, int end); void layoutChangedCallback(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint); void modelResetCallback(); + bool compareModel(const QVariant& model1, const QVariant& model2) const; void scheduleRebuildIfFastFlick(); void setLocalViewportX(qreal contentX); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 597cd300df..a08f46a1b4 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -3305,6 +3305,11 @@ void QQuickWindow::endExternalCommands() The (x,y) position is relative to the \l Screen if there is only one, or to the virtual desktop (arrangement of multiple screens). + \note Not all windowing systems support setting or querying top level + window positions. On such a system, programmatically moving windows + may not have any effect, and artificial values may be returned for + the current positions, such as \c QPoint(0, 0). + \qml Window { x: 100; y: 100; width: 100; height: 100 } \endqml diff --git a/src/quick/scenegraph/shaders_ng/24bittextmask.frag b/src/quick/scenegraph/shaders_ng/24bittextmask.frag index ed8da4cd30..49023666ce 100644 --- a/src/quick/scenegraph/shaders_ng/24bittextmask.frag +++ b/src/quick/scenegraph/shaders_ng/24bittextmask.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/32bitcolortext.frag b/src/quick/scenegraph/shaders_ng/32bitcolortext.frag index 4198a4d339..000adb619e 100644 --- a/src/quick/scenegraph/shaders_ng/32bitcolortext.frag +++ b/src/quick/scenegraph/shaders_ng/32bitcolortext.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/8bittextmask.frag b/src/quick/scenegraph/shaders_ng/8bittextmask.frag index a06743876d..9507728803 100644 --- a/src/quick/scenegraph/shaders_ng/8bittextmask.frag +++ b/src/quick/scenegraph/shaders_ng/8bittextmask.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/8bittextmask_a.frag b/src/quick/scenegraph/shaders_ng/8bittextmask_a.frag index f725cbc5e7..9c0f36b81f 100644 --- a/src/quick/scenegraph/shaders_ng/8bittextmask_a.frag +++ b/src/quick/scenegraph/shaders_ng/8bittextmask_a.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext.frag b/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext.frag index b1551d8ef4..9e89d17219 100644 --- a/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext.frag +++ b/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_a.frag b/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_a.frag index 7c6bd9a493..4fe30b69ee 100644 --- a/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_a.frag +++ b/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_a.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_a_fwidth.frag b/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_a_fwidth.frag index 30ec465791..4dc7432e44 100644 --- a/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_a_fwidth.frag +++ b/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_a_fwidth.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_fwidth.frag b/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_fwidth.frag index 511bffb09a..44aea6b979 100644 --- a/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_fwidth.frag +++ b/src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_fwidth.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext.frag b/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext.frag index aa3390094b..320c19973b 100644 --- a/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext.frag +++ b/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_a.frag b/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_a.frag index ab3a5f63ff..0ddd1b40d1 100644 --- a/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_a.frag +++ b/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_a.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_a_fwidth.frag b/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_a_fwidth.frag index 8f528fea1e..8b124213a4 100644 --- a/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_a_fwidth.frag +++ b/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_a_fwidth.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_fwidth.frag b/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_fwidth.frag index a71cc1d9b0..40f519636e 100644 --- a/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_fwidth.frag +++ b/src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_fwidth.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/distancefieldtext.frag b/src/quick/scenegraph/shaders_ng/distancefieldtext.frag index d594207567..a86f68c8cb 100644 --- a/src/quick/scenegraph/shaders_ng/distancefieldtext.frag +++ b/src/quick/scenegraph/shaders_ng/distancefieldtext.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/distancefieldtext_a.frag b/src/quick/scenegraph/shaders_ng/distancefieldtext_a.frag index bb807d86d8..449647561f 100644 --- a/src/quick/scenegraph/shaders_ng/distancefieldtext_a.frag +++ b/src/quick/scenegraph/shaders_ng/distancefieldtext_a.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/distancefieldtext_a_fwidth.frag b/src/quick/scenegraph/shaders_ng/distancefieldtext_a_fwidth.frag index 1aa1175b57..534ec9208c 100644 --- a/src/quick/scenegraph/shaders_ng/distancefieldtext_a_fwidth.frag +++ b/src/quick/scenegraph/shaders_ng/distancefieldtext_a_fwidth.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/distancefieldtext_fwidth.frag b/src/quick/scenegraph/shaders_ng/distancefieldtext_fwidth.frag index a698c19550..04886d6b12 100644 --- a/src/quick/scenegraph/shaders_ng/distancefieldtext_fwidth.frag +++ b/src/quick/scenegraph/shaders_ng/distancefieldtext_fwidth.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/flatcolor.frag b/src/quick/scenegraph/shaders_ng/flatcolor.frag index 3a677b7c93..cac8f1fb17 100644 --- a/src/quick/scenegraph/shaders_ng/flatcolor.frag +++ b/src/quick/scenegraph/shaders_ng/flatcolor.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) out vec4 fragColor; diff --git a/src/quick/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag b/src/quick/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag index 723227a04d..19dce21aa4 100644 --- a/src/quick/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag +++ b/src/quick/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext_a.frag b/src/quick/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext_a.frag index a9d56f6380..0cfe63edbf 100644 --- a/src/quick/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext_a.frag +++ b/src/quick/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext_a.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag b/src/quick/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag index 08b2ce5187..343e93f54f 100644 --- a/src/quick/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag +++ b/src/quick/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec3 sampleNearLeft; diff --git a/src/quick/scenegraph/shaders_ng/loqsubpixeldistancefieldtext_a.frag b/src/quick/scenegraph/shaders_ng/loqsubpixeldistancefieldtext_a.frag index ef9407491b..e5aef90fda 100644 --- a/src/quick/scenegraph/shaders_ng/loqsubpixeldistancefieldtext_a.frag +++ b/src/quick/scenegraph/shaders_ng/loqsubpixeldistancefieldtext_a.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec3 sampleNearLeft; diff --git a/src/quick/scenegraph/shaders_ng/opaquetexture.frag b/src/quick/scenegraph/shaders_ng/opaquetexture.frag index 2cd2175f87..18dd7e0fcb 100644 --- a/src/quick/scenegraph/shaders_ng/opaquetexture.frag +++ b/src/quick/scenegraph/shaders_ng/opaquetexture.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 qt_TexCoord; diff --git a/src/quick/scenegraph/shaders_ng/outlinedtext.frag b/src/quick/scenegraph/shaders_ng/outlinedtext.frag index e2f82d3845..6a5e1aa28b 100644 --- a/src/quick/scenegraph/shaders_ng/outlinedtext.frag +++ b/src/quick/scenegraph/shaders_ng/outlinedtext.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/outlinedtext_a.frag b/src/quick/scenegraph/shaders_ng/outlinedtext_a.frag index 274d891a3c..853f08e8ee 100644 --- a/src/quick/scenegraph/shaders_ng/outlinedtext_a.frag +++ b/src/quick/scenegraph/shaders_ng/outlinedtext_a.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/shadereffect.frag b/src/quick/scenegraph/shaders_ng/shadereffect.frag index bde493f6ce..ef4bbe78f3 100644 --- a/src/quick/scenegraph/shaders_ng/shadereffect.frag +++ b/src/quick/scenegraph/shaders_ng/shadereffect.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 qt_TexCoord0; diff --git a/src/quick/scenegraph/shaders_ng/smoothcolor.frag b/src/quick/scenegraph/shaders_ng/smoothcolor.frag index ede283be0c..314a387922 100644 --- a/src/quick/scenegraph/shaders_ng/smoothcolor.frag +++ b/src/quick/scenegraph/shaders_ng/smoothcolor.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec4 color; diff --git a/src/quick/scenegraph/shaders_ng/smoothtexture.frag b/src/quick/scenegraph/shaders_ng/smoothtexture.frag index b06764ad95..a7ddc57535 100644 --- a/src/quick/scenegraph/shaders_ng/smoothtexture.frag +++ b/src/quick/scenegraph/shaders_ng/smoothtexture.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 texCoord; diff --git a/src/quick/scenegraph/shaders_ng/sprite.frag b/src/quick/scenegraph/shaders_ng/sprite.frag index 338f5e957e..846958c71c 100644 --- a/src/quick/scenegraph/shaders_ng/sprite.frag +++ b/src/quick/scenegraph/shaders_ng/sprite.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec4 fTexS; diff --git a/src/quick/scenegraph/shaders_ng/stencilclip.frag b/src/quick/scenegraph/shaders_ng/stencilclip.frag index 3f6222389d..ec4d3a05b1 100644 --- a/src/quick/scenegraph/shaders_ng/stencilclip.frag +++ b/src/quick/scenegraph/shaders_ng/stencilclip.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) out vec4 fragColor; diff --git a/src/quick/scenegraph/shaders_ng/styledtext.frag b/src/quick/scenegraph/shaders_ng/styledtext.frag index 2e380dfeae..df14c09aed 100644 --- a/src/quick/scenegraph/shaders_ng/styledtext.frag +++ b/src/quick/scenegraph/shaders_ng/styledtext.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/styledtext_a.frag b/src/quick/scenegraph/shaders_ng/styledtext_a.frag index 62e162c851..eda1062f2d 100644 --- a/src/quick/scenegraph/shaders_ng/styledtext_a.frag +++ b/src/quick/scenegraph/shaders_ng/styledtext_a.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/textmask.frag b/src/quick/scenegraph/shaders_ng/textmask.frag index ed8da4cd30..49023666ce 100644 --- a/src/quick/scenegraph/shaders_ng/textmask.frag +++ b/src/quick/scenegraph/shaders_ng/textmask.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 sampleCoord; diff --git a/src/quick/scenegraph/shaders_ng/texture.frag b/src/quick/scenegraph/shaders_ng/texture.frag index bd22f817e0..d4be87ec29 100644 --- a/src/quick/scenegraph/shaders_ng/texture.frag +++ b/src/quick/scenegraph/shaders_ng/texture.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 qt_TexCoord; diff --git a/src/quick/scenegraph/shaders_ng/vertexcolor.frag b/src/quick/scenegraph/shaders_ng/vertexcolor.frag index ede283be0c..314a387922 100644 --- a/src/quick/scenegraph/shaders_ng/vertexcolor.frag +++ b/src/quick/scenegraph/shaders_ng/vertexcolor.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec4 color; diff --git a/src/quick/scenegraph/shaders_ng/visualization.frag b/src/quick/scenegraph/shaders_ng/visualization.frag index 29f718fe5d..378afc2088 100644 --- a/src/quick/scenegraph/shaders_ng/visualization.frag +++ b/src/quick/scenegraph/shaders_ng/visualization.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 pos; diff --git a/src/quick/util/qquickdeliveryagent.cpp b/src/quick/util/qquickdeliveryagent.cpp index a1f3fc64fd..7a6905b5de 100644 --- a/src/quick/util/qquickdeliveryagent.cpp +++ b/src/quick/util/qquickdeliveryagent.cpp @@ -1712,17 +1712,19 @@ void QQuickDeliveryAgentPrivate::onGrabChanged(QObject *grabber, QPointingDevice } if (currentEventDeliveryAgent == q && event && event->device()) { - auto epd = QPointingDevicePrivate::get(const_cast<QPointingDevice*>(event->pointingDevice()))->queryPointById(point.id()); - Q_ASSERT(epd); switch (transition) { case QPointingDevice::GrabPassive: { + auto epd = QPointingDevicePrivate::get(const_cast<QPointingDevice*>(event->pointingDevice()))->queryPointById(point.id()); + Q_ASSERT(epd); QPointingDevicePrivate::setPassiveGrabberContext(epd, grabber, q); qCDebug(lcPtr) << "remembering that" << q << "handles point" << point.id() << "after" << transition; } break; - case QPointingDevice::GrabExclusive: + case QPointingDevice::GrabExclusive: { + auto epd = QPointingDevicePrivate::get(const_cast<QPointingDevice*>(event->pointingDevice()))->queryPointById(point.id()); + Q_ASSERT(epd); epd->exclusiveGrabberContext = q; qCDebug(lcPtr) << "remembering that" << q << "handles point" << point.id() << "after" << transition; - break; + } break; case QPointingDevice::CancelGrabExclusive: case QPointingDevice::UngrabExclusive: // taken care of in QPointingDevicePrivate::setExclusiveGrabber(,,nullptr), removeExclusiveGrabber() diff --git a/src/quickcontrols2/basic/Menu.qml b/src/quickcontrols2/basic/Menu.qml index 475e58ccb8..bee89f94bb 100644 --- a/src/quickcontrols2/basic/Menu.qml +++ b/src/quickcontrols2/basic/Menu.qml @@ -54,9 +54,7 @@ T.Menu { contentItem: ListView { implicitHeight: contentHeight model: control.contentModel - interactive: Window.window - ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height - : false + interactive: contentHeight + control.topPadding + control.bottomPadding > control.height clip: true currentIndex: control.currentIndex diff --git a/src/quickcontrols2/fusion/Menu.qml b/src/quickcontrols2/fusion/Menu.qml index 7808850ce4..d56860d43e 100644 --- a/src/quickcontrols2/fusion/Menu.qml +++ b/src/quickcontrols2/fusion/Menu.qml @@ -58,9 +58,7 @@ T.Menu { contentItem: ListView { implicitHeight: contentHeight model: control.contentModel - interactive: Window.window - ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height - : false + interactive: contentHeight + control.topPadding + control.bottomPadding > control.height clip: true currentIndex: control.currentIndex diff --git a/src/quickcontrols2/imagine/Menu.qml b/src/quickcontrols2/imagine/Menu.qml index 346c649021..ec73df6afd 100644 --- a/src/quickcontrols2/imagine/Menu.qml +++ b/src/quickcontrols2/imagine/Menu.qml @@ -68,9 +68,7 @@ T.Menu { contentItem: ListView { implicitHeight: contentHeight model: control.contentModel - interactive: Window.window - ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height - : false + interactive: contentHeight + control.topPadding + control.bottomPadding > control.height clip: true currentIndex: control.currentIndex diff --git a/src/quickcontrols2/material/Menu.qml b/src/quickcontrols2/material/Menu.qml index b7e80c92ef..df11e0ebf0 100644 --- a/src/quickcontrols2/material/Menu.qml +++ b/src/quickcontrols2/material/Menu.qml @@ -73,9 +73,7 @@ T.Menu { implicitHeight: contentHeight model: control.contentModel - interactive: Window.window - ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height - : false + interactive: contentHeight + control.topPadding + control.bottomPadding > control.height clip: true currentIndex: control.currentIndex diff --git a/src/quickcontrols2/universal/Menu.qml b/src/quickcontrols2/universal/Menu.qml index c4723f32aa..5d5a1a5650 100644 --- a/src/quickcontrols2/universal/Menu.qml +++ b/src/quickcontrols2/universal/Menu.qml @@ -55,9 +55,7 @@ T.Menu { contentItem: ListView { implicitHeight: contentHeight model: control.contentModel - interactive: Window.window - ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height - : false + interactive: contentHeight + control.topPadding + control.bottomPadding > control.height clip: true currentIndex: control.currentIndex diff --git a/src/quickshapes/shaders_ng/conicalgradient.frag b/src/quickshapes/shaders_ng/conicalgradient.frag index 0b1e01bae2..99592e14e4 100644 --- a/src/quickshapes/shaders_ng/conicalgradient.frag +++ b/src/quickshapes/shaders_ng/conicalgradient.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 coord; diff --git a/src/quickshapes/shaders_ng/lineargradient.frag b/src/quickshapes/shaders_ng/lineargradient.frag index 16894fc764..26fa540154 100644 --- a/src/quickshapes/shaders_ng/lineargradient.frag +++ b/src/quickshapes/shaders_ng/lineargradient.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in float gradTabIndex; diff --git a/src/quickshapes/shaders_ng/radialgradient.frag b/src/quickshapes/shaders_ng/radialgradient.frag index 411e589295..743cc2a8cb 100644 --- a/src/quickshapes/shaders_ng/radialgradient.frag +++ b/src/quickshapes/shaders_ng/radialgradient.frag @@ -1,3 +1,6 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #version 440 layout(location = 0) in vec2 coord; diff --git a/src/quicktemplates2/qquickstackview.cpp b/src/quicktemplates2/qquickstackview.cpp index 5b859adba1..77b674a22a 100644 --- a/src/quicktemplates2/qquickstackview.cpp +++ b/src/quicktemplates2/qquickstackview.cpp @@ -550,7 +550,8 @@ QQuickItem *QQuickStackView::find(const QJSValue &callback, LoadBehavior behavio \value StackView.ReplaceTransition An operation with replace transitions (since QtQuick.Controls 2.1). \value StackView.PopTransition An operation with pop transitions (since QtQuick.Controls 2.1). - If no operation is provided, \c PushTransition will be used. + If no operation is provided, \c Immediate will be used if the stack is + empty, and \c PushTransition otherwise. \note Items that already exist in the stack are not pushed. @@ -792,7 +793,8 @@ void QQuickStackView::pop(QQmlV4Function *args) \value StackView.ReplaceTransition An operation with replace transitions (since QtQuick.Controls 2.1). \value StackView.PopTransition An operation with pop transitions (since QtQuick.Controls 2.1). - If no operation is provided, \c ReplaceTransition will be used. + If no operation is provided, \c Immediate will be used if the stack is + empty, and \c ReplaceTransition otherwise. The following example illustrates the use of push and pop transitions with replace(). diff --git a/tests/auto/qml/debugger/qv4debugger/data/breakPointInJSModule.qml b/tests/auto/qml/debugger/qv4debugger/data/breakPointInJSModule.qml new file mode 100644 index 0000000000..2582a23ec5 --- /dev/null +++ b/tests/auto/qml/debugger/qv4debugger/data/breakPointInJSModule.qml @@ -0,0 +1,4 @@ +import QtQml 2.15 +import "module1.js" as Module1 + +QtObject {} diff --git a/tests/auto/qml/debugger/qv4debugger/data/module1.js b/tests/auto/qml/debugger/qv4debugger/data/module1.js new file mode 100644 index 0000000000..9ce1f1e6b1 --- /dev/null +++ b/tests/auto/qml/debugger/qv4debugger/data/module1.js @@ -0,0 +1,5 @@ +.pragma library + +.import "module2.mjs" as Module2 + +Module2.crashMe(); diff --git a/tests/auto/qml/debugger/qv4debugger/data/module2.mjs b/tests/auto/qml/debugger/qv4debugger/data/module2.mjs new file mode 100644 index 0000000000..80f82af953 --- /dev/null +++ b/tests/auto/qml/debugger/qv4debugger/data/module2.mjs @@ -0,0 +1,7 @@ +import * as Module3 from "module3.mjs" +import * as Module4 from "module4.mjs" + +export function crashMe() +{ + console.log("Hello world!"); +} diff --git a/tests/auto/qml/debugger/qv4debugger/data/module3.mjs b/tests/auto/qml/debugger/qv4debugger/data/module3.mjs new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/auto/qml/debugger/qv4debugger/data/module3.mjs diff --git a/tests/auto/qml/debugger/qv4debugger/data/module4.mjs b/tests/auto/qml/debugger/qv4debugger/data/module4.mjs new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/auto/qml/debugger/qv4debugger/data/module4.mjs diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp index b9b2fd6b69..331d978dd7 100644 --- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp @@ -241,10 +241,14 @@ public: QJsonArray scopes = frameObj.value(QLatin1String("scopes")).toArray(); int nscopes = scopes.size(); int s = 0; - for (s = 0; s < nscopes; ++s) { - QJsonObject o = scopes.at(s).toObject(); - if (o.value(QLatin1String("type")).toInt(-2) == 1) // CallContext - break; + if (m_targetScope != -1) { + s = m_targetScope; + } else { + for (s = 0; s < nscopes; ++s) { + QJsonObject o = scopes.at(s).toObject(); + if (o.value(QLatin1String("type")).toInt(-2) == 1) // CallContext + break; + } } if (s == nscopes) return; @@ -274,6 +278,7 @@ public: bool m_wasPaused; QV4Debugger::PauseReason m_pauseReason; bool m_captureContextInfo; + int m_targetScope = -1; QList<QV4Debugger::ExecutionState> m_statesWhenPaused; QList<TestBreakPoint> m_breakPointsToAddWhenPaused; QVector<QV4::StackFrame> m_stackTrace; @@ -347,6 +352,9 @@ private slots: void readThis(); void signalParameters(); void debuggerNoCrash(); + + void breakPointInJSModule(); + private: QV4Debugger *debugger() const { @@ -992,6 +1000,35 @@ void tst_qv4debugger::debuggerNoCrash() debugThread->wait(); } +void tst_qv4debugger::breakPointInJSModule() +{ + QQmlEngine engine; + QV4::ExecutionEngine *v4 = engine.handle(); + QPointer<QV4Debugger> v4Debugger = new QV4Debugger(v4); + v4->setDebugger(v4Debugger.data()); + + QScopedPointer<QThread> debugThread(new QThread); + debugThread->start(); + QScopedPointer<TestAgent> debuggerAgent(new TestAgent(v4)); + debuggerAgent->addDebugger(v4Debugger); + debuggerAgent->moveToThread(debugThread.data()); + + QQmlComponent component(&engine, testFileUrl("breakPointInJSModule.qml")); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + + debuggerAgent->m_captureContextInfo = true; + debuggerAgent->m_targetScope = 1; + v4Debugger->addBreakPoint("module2.mjs", 6); + + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + + QVERIFY(!debuggerAgent->m_capturedScope.isEmpty()); + + debugThread->quit(); + debugThread->wait(); +} + tst_qv4debugger::tst_qv4debugger() : QQmlDataTest(QT_QMLTEST_DATADIR) { } QTEST_MAIN(tst_qv4debugger) diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 81ac086294..7883ca721d 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -43,6 +43,7 @@ #include <QScopeGuard> #include <QUrl> #include <QModelIndex> +#include <QtQml/qqmllist.h> #ifdef Q_CC_MSVC #define NO_INLINE __declspec(noinline) @@ -1658,6 +1659,13 @@ void tst_QJSEngine::valueConversion_basic() QCOMPARE(eng.fromScriptValue<QChar>(eng.toScriptValue(c)), c); } + { + QList<QObject *> list = {this}; + QQmlListProperty<QObject> prop(this, &list); + QJSValue jsVal = eng.toScriptValue(prop); + QCOMPARE(eng.fromScriptValue<QQmlListProperty<QObject>>(jsVal), prop); + } + QVERIFY(eng.toScriptValue(static_cast<void *>(nullptr)).isNull()); } diff --git a/tests/auto/qml/qmlcachegen/data/truncateTest.qml b/tests/auto/qml/qmlcachegen/data/truncateTest.qml new file mode 100644 index 0000000000..fee768cf77 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/data/truncateTest.qml @@ -0,0 +1,764 @@ +import QtQuick 2.15 +import QtQuick.Layouts 2.15 + +Item { + width: 400 + height: 400 + + component Button : Item { + property string text + property Item background + } + + ColumnLayout { + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + Button { + text: "A Special Button" + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color: "red" + border.color: "#26282a" + border.width: 1 + radius: 4 + } + } + + } +} diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index a2639bc532..f235bbe557 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -86,6 +86,8 @@ private slots: void inlineComponent(); void posthocRequired(); + void gracefullyHandleTruncatedCacheFile(); + void scriptStringCachegenInteraction(); void saveableUnitPointer(); }; @@ -782,6 +784,23 @@ void tst_qmlcachegen::posthocRequired() QVERIFY(component.errorString().contains(QStringLiteral("Required property x was not initialized"))); } +void tst_qmlcachegen::gracefullyHandleTruncatedCacheFile() +{ +#if defined(QTEST_CROSS_COMPILED) + QSKIP("Cannot call qmlcachegen on cross-compiled target."); +#endif + + bool ok = generateCache(testFile("truncateTest.qml")); + QVERIFY(ok); + const QString qmlcFile = testFile("truncateTest.qmlc"); + QVERIFY(QFile::exists(qmlcFile)); + QFile::resize(qmlcFile, QFileInfo(qmlcFile).size() / 2); + QQmlEngine engine; + CleanlyLoadingComponent component(&engine, testFileUrl("truncateTest.qml")); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); +} + void tst_qmlcachegen::scriptStringCachegenInteraction() { #if defined(QTEST_CROSS_COMPILED) diff --git a/tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml b/tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml new file mode 100644 index 0000000000..9d2ee433fd --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml @@ -0,0 +1,6 @@ +import Qt.test +import QtQml + +QtObject { + Component.onCompleted: SingletonInheritanceTest.trackPage("test", {x: 42}) +} diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp index cd83702d3a..803e09a2e9 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.cpp +++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp @@ -561,6 +561,8 @@ void registerTypes() qmlRegisterType<Receiver>("Qt.test", 1,0, "Receiver"); qmlRegisterType<Sender>("Qt.test", 1,0, "Sender"); qmlRegisterTypesAndRevisions<ReadOnlyBindable>("Qt.test", 1); + + qmlRegisterTypesAndRevisions<SingletonRegistrationWrapper>("Qt.test", 1); } #include "testtypes.moc" diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index a3df73972e..622d7c44c8 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -1892,6 +1892,42 @@ public: QBindable<int> bindableX() const { return &_xProp; } }; +class SingletonBase : public QObject { + Q_OBJECT + +public: + Q_INVOKABLE virtual void trackPage(const QString&) {} + Q_INVOKABLE virtual void trackPage(const QString&, const QVariantMap&) {} + + bool m_okay = false; +}; + +class SingletonImpl : public SingletonBase { + Q_OBJECT + +public: + Q_INVOKABLE virtual void trackPage(const QString&) override {} + Q_INVOKABLE virtual void trackPage(const QString&, const QVariantMap&) override + { + m_okay = true; + } +}; + +class SingletonRegistrationWrapper { + Q_GADGET + QML_FOREIGN(SingletonBase) + QML_NAMED_ELEMENT(SingletonInheritanceTest) + QML_SINGLETON + +public: + static SingletonBase* create(QQmlEngine*, QJSEngine*) { + return new SingletonImpl(); + } + +private: + SingletonRegistrationWrapper() = default; +}; + void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index e976ec46a3..c30c4de825 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -437,6 +437,8 @@ private slots: void doNotCrashOnReadOnlyBindable(); + + void methodCallOnDerivedSingleton(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); static void verifyContextLifetime(const QQmlRefPointer<QQmlContextData> &ctxt); @@ -10146,6 +10148,20 @@ void tst_qqmlecmascript::doNotCrashOnReadOnlyBindable() QCOMPARE(o->property("x").toInt(), 7); } + +void tst_qqmlecmascript::methodCallOnDerivedSingleton() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFile("methodCallOnDerivedSingleton.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(o); + int singletonTypeId = qmlTypeId("Qt.test", 1, 0, "SingletonInheritanceTest"); + auto singleton = engine.singletonInstance<SingletonBase *>(singletonTypeId); + QVERIFY(singleton); + QVERIFY(singleton->m_okay); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" diff --git a/tests/auto/qml/qqmlengine/data/bindingInstallUseAfterFree.qml b/tests/auto/qml/qqmlengine/data/bindingInstallUseAfterFree.qml new file mode 100644 index 0000000000..596ab10ee7 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/bindingInstallUseAfterFree.qml @@ -0,0 +1,19 @@ +import QtQuick + +Item { + visible: false + + property int test: 1 + + Component { + id: comp + Item { + width: { width = test * 100 } + } + } + + Loader { + sourceComponent: comp + width: 100 + } +} diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index d2ec48ffb4..953bce9603 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -92,6 +92,7 @@ private slots: void attachedObjectAsObject(); void listPropertyAsQJSValue(); void stringToColor(); + void bindingInstallUseAfterFree(); public slots: QObject *createAQObjectForOwnershipTest () @@ -1436,6 +1437,15 @@ void tst_qqmlengine::stringToColor() QCOMPARE(color, variant); } +void tst_qqmlengine::bindingInstallUseAfterFree() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("bindingInstallUseAfterFree.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + std::unique_ptr<QObject> o{ c.create() }; + QVERIFY(o); +} + QTEST_MAIN(tst_qqmlengine) #include "tst_qqmlengine.moc" diff --git a/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml b/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml new file mode 100644 index 0000000000..bde2ad9813 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml @@ -0,0 +1,28 @@ +import QtQml + +QtObject { + id: root + objectName: "theRoot" + + component ObjectWithColor: QtObject { + property string color + property var varvar + } + + property ObjectWithColor border: ObjectWithColor { + id: border + objectName: root.objectName + color: root.trueBorderColor + varvar: root.trueBorderVarvar + } + + readonly property rect readonlyRect: Qt.rect(12, 13, 14, 15) + + property alias borderObjectName: border.objectName + property alias borderColor: border.color + property alias borderVarvar: border.varvar + property alias readonlyRectX: root.readonlyRect.x + + property string trueBorderColor: "green" + property var trueBorderVarvar: 1234 +} diff --git a/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle1.qml b/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle1.qml new file mode 100644 index 0000000000..6186faa00b --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle1.qml @@ -0,0 +1,15 @@ +import QtQml + +QtObject { + id: self + property QtObject b + property Component c + function a() : TypeAnnotationCycle2 { return c.createObject() as TypeAnnotationCycle2 } + + Component.onCompleted: { + c = Qt.createComponent("TypeAnnotationCycle2.qml"); + let v = a(); + v.addTypeAnnotationCycle1(self as TypeAnnotationCycle1); + b = v.b; + } +} diff --git a/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle2.qml b/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle2.qml new file mode 100644 index 0000000000..9e3ffa86d2 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle2.qml @@ -0,0 +1,6 @@ +import QtQml + +QtObject { + property QtObject b + function addTypeAnnotationCycle1(c: TypeAnnotationCycle1) { b = c; } +} diff --git a/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml b/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml new file mode 100644 index 0000000000..50eaa7c3e2 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml @@ -0,0 +1,9 @@ +import QtQml + +DeepAliasOnIC { + borderObjectName: "theLeaf" + borderColor: "black" + borderVarvar: "mauve" +} + + diff --git a/tests/auto/qml/qqmllanguage/data/deepAliasOnReadonly.qml b/tests/auto/qml/qqmllanguage/data/deepAliasOnReadonly.qml new file mode 100644 index 0000000000..f5ae62406b --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/deepAliasOnReadonly.qml @@ -0,0 +1,5 @@ +import QtQml + +DeepAliasOnIC { + readonlyRectX: 55 +} diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 0d26772c6c..41fb24a76c 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -390,6 +390,9 @@ private slots: void callMethodOfAttachedDerived(); + void typeAnnotationCycle(); + void deepAliasOnICOrReadonly(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -6692,6 +6695,45 @@ void tst_qqmllanguage::callMethodOfAttachedDerived() QCOMPARE(o->property("v").toInt(), 99); } +void tst_qqmllanguage::typeAnnotationCycle() +{ + QQmlEngine engine; + + const QUrl url = testFileUrl("TypeAnnotationCycle1.qml"); + const QUrl url2 = testFileUrl("TypeAnnotationCycle2.qml"); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable( + QLatin1String("Cyclic dependency detected between \"%1\" and \"%2\"") + .arg(url.toString(), url2.toString()))); + + QQmlComponent c(&engine, url); + QVERIFY(!c.isReady()); +} + +void tst_qqmllanguage::deepAliasOnICOrReadonly() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("deepAliasOnICUser.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + QCOMPARE(o->property("borderColor").toString(), QLatin1String("black")); + QCOMPARE(o->property("borderObjectName").toString(), QLatin1String("theLeaf")); + + const QVariant var = o->property("borderVarvar"); + QCOMPARE(var.metaType(), QMetaType::fromType<QString>()); + QCOMPARE(var.toString(), QLatin1String("mauve")); + + QQmlComponent c2(&engine, testFileUrl("deepAliasOnReadonly.qml")); + QVERIFY(c2.isError()); + QVERIFY(c2.errorString().contains( + QLatin1String( + "Invalid property assignment: \"readonlyRectX\" is a read-only property"))); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickableWithParentTapHandler.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickableWithParentTapHandler.qml new file mode 100644 index 0000000000..2660952f16 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/pinchOnFlickableWithParentTapHandler.qml @@ -0,0 +1,24 @@ +import QtQuick + +Rectangle { + width: 320 + height: 320 + + TapHandler { + onTapped: color = "tomato" + } + + Flickable { + anchors.fill: parent + contentWidth: content.width + contentHeight: content.height + Rectangle { + id: content + objectName: "pinchable" + width: 150 + height: 150 + color: "wheat" + PinchHandler {} + } + } +} diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp index 0bf6b3fdcc..b7f49834d1 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp +++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp @@ -36,6 +36,7 @@ #include <QtQuick/private/qquickitemview_p.h> #include <QtQuick/private/qquickpointerhandler_p.h> #include <QtQuick/private/qquickdraghandler_p.h> +#include <QtQuick/private/qquickpinchhandler_p.h> #include <QtQuick/private/qquicktaphandler_p.h> #include <QtQuick/private/qquicktableview_p.h> #include <qpa/qwindowsysteminterface.h> @@ -81,10 +82,14 @@ private slots: void touchAndDragHandlerOnFlickable_data(); void touchAndDragHandlerOnFlickable(); void pinchHandlerOnFlickable(); + void nativeGesturePinchOnFlickableWithParentTapHandler_data(); + void nativeGesturePinchOnFlickableWithParentTapHandler(); private: void createView(QScopedPointer<QQuickView> &window, const char *fileName); QPointingDevice *touchDevice; + QScopedPointer<QPointingDevice> touchpad = QScopedPointer<QPointingDevice>( + QTest::createTouchDevice(QInputDevice::DeviceType::TouchPad)); }; void tst_FlickableInterop::createView(QScopedPointer<QQuickView> &window, const char *fileName) @@ -879,6 +884,119 @@ void tst_FlickableInterop::pinchHandlerOnFlickable() QCOMPARE(flickMoveSpy.count(), 0); // Flickable never moved } +void tst_FlickableInterop::nativeGesturePinchOnFlickableWithParentTapHandler_data() +{ + QTest::addColumn<const QPointingDevice*>("device"); + QTest::addColumn<Qt::MouseButton>("button"); + QTest::addColumn<Qt::NativeGestureType>("gesture"); + QTest::addColumn<qreal>("value"); + QTest::addColumn<qreal>("expectedPropertyValue"); + + const QPointingDevice *constTouchPad = touchpad.data(); + + // expectedPropertyValue is 10 in newer Qt versions, but in 6.2 QQuickPinchHandler::onActiveChanged() resets the first rotation + QTest::newRow("touchpad: left and rotate") << constTouchPad << Qt::LeftButton << Qt::RotateNativeGesture << 5.0 << 5.0; + QTest::newRow("touchpad: right and rotate") << constTouchPad << Qt::RightButton << Qt::RotateNativeGesture << 5.0 << 5.0; + + // whereas zoom is cumulative as expected + QTest::newRow("touchpad: left and scale") << constTouchPad << Qt::LeftButton << Qt::ZoomNativeGesture << 0.1 << 1.21; + QTest::newRow("touchpad: right and scale") << constTouchPad << Qt::RightButton << Qt::ZoomNativeGesture << 0.1 << 1.21; + + const auto *mouse = QPointingDevice::primaryPointingDevice(); + if (mouse->type() == QInputDevice::DeviceType::Mouse) { + QTest::newRow("mouse: left and rotate") << mouse << Qt::LeftButton << Qt::RotateNativeGesture << 5.0 << 10.0; + QTest::newRow("mouse: right and rotate") << mouse << Qt::RightButton << Qt::RotateNativeGesture << 5.0 << 10.0; + QTest::newRow("mouse: left and scale") << mouse << Qt::LeftButton << Qt::ZoomNativeGesture << 0.1 << 1.21; + QTest::newRow("mouse: right and scale") << mouse << Qt::RightButton << Qt::ZoomNativeGesture << 0.1 << 1.21; + } else { + qCWarning(lcPointerTests) << "skipping mouse tests: primary device is not a mouse" << mouse; + } +} + +void tst_FlickableInterop::nativeGesturePinchOnFlickableWithParentTapHandler() +{ + QFETCH(const QPointingDevice*, device); + QFETCH(Qt::MouseButton, button); + QFETCH(Qt::NativeGestureType, gesture); + QFETCH(qreal, value); + QFETCH(qreal, expectedPropertyValue); + + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl("pinchOnFlickableWithParentTapHandler.qml"))); + QQuickFlickable *flickable = window.rootObject()->findChild<QQuickFlickable*>(); + QVERIFY(flickable); + QQuickPointerHandler *pinchHandler = flickable->findChild<QQuickPinchHandler*>(); + QVERIFY(pinchHandler); + QQuickItem *pinchable = pinchHandler->target(); + QVERIFY(pinchable); + QQuickTapHandler *tapHandler = window.rootObject()->findChild<QQuickTapHandler*>(); + QVERIFY(tapHandler); + const bool expectTap = button & tapHandler->acceptedButtons(); + + QSignalSpy flickMoveSpy(flickable, &QQuickFlickable::movementStarted); + QSignalSpy grabChangedSpy(touchDevice, &QPointingDevice::grabChanged); + QSignalSpy tapActiveSpy(tapHandler, &QQuickTapHandler::activeChanged); + QSignalSpy tapSpy(tapHandler, &QQuickTapHandler::tapped); + + QObject *grabber = nullptr; + connect(device, &QPointingDevice::grabChanged, + [&grabber](QObject *g, QPointingDevice::GrabTransition transition, const QPointerEvent *, const QEventPoint &) { + if (transition == QPointingDevice::GrabTransition::GrabExclusive) + grabber = g; + }); + + const QPoint pinchPos(75, 75); + const QPoint outsidePos(200, 200); + + // move to position + QTest::mouseMove(&window, pinchPos); + + // pinch via native gesture + ulong ts = 502; // after the mouse move, which is at time 501 in practice + QWindowSystemInterface::handleGestureEvent(&window, ts++, touchpad.get(), + Qt::BeginNativeGesture, pinchPos, pinchPos); + if (lcPointerTests().isDebugEnabled()) QTest::qWait(500); + for (int i = 0; i < 2; ++i) { + QWindowSystemInterface::handleGestureEventWithRealValue(&window, ts++, touchpad.get(), + gesture, value, pinchPos, pinchPos); + } + if (gesture == Qt::RotateNativeGesture) + QTRY_COMPARE(pinchHandler->parentItem()->rotation(), expectedPropertyValue); + else if (gesture == Qt::ZoomNativeGesture) + QTRY_COMPARE(pinchHandler->parentItem()->scale(), expectedPropertyValue); + QVERIFY(pinchHandler->active()); + QCOMPARE(grabChangedSpy.count(), 0); + QCOMPARE(grabber, nullptr); + if (lcPointerTests().isDebugEnabled()) QTest::qWait(500); + QWindowSystemInterface::handleGestureEvent(&window, ts++, touchpad.get(), + Qt::EndNativeGesture, pinchPos, pinchPos); + + // tap in square: TapHandler detects tap iff acceptedButtons permits + // TODO delay; unfortunately this also begins at timestamp 502 because we don't have testlib + // functions to send gesture events, and QQuickTest::pointerPress() doesn't take a delay value + QQuickTest::pointerPress(device, &window, 0, pinchPos, button); + QCOMPARE(tapHandler->point().id(), expectTap ? 0 : -1); + QQuickTest::pointerRelease(device, &window, 0, pinchPos, button); + if (lcPointerTests().isDebugEnabled()) QTest::qWait(500); + QCOMPARE(tapSpy.size(), expectTap); + QCOMPARE(tapActiveSpy.size(), 0); + QCOMPARE(tapHandler->point().id(), -1); // does not keep tracking after release + + // move outside: nothing should happen; + // but QTBUG-108896 happened because TapHandler was setting pointInfo to track this moving point + QQuickTest::pointerMove(device, &window, 0, outsidePos); + QCOMPARE(tapHandler->point().id(), -1); // does not track after mouse move + + // tap outside: nothing happens + tapSpy.clear(); + tapActiveSpy.clear(); + QQuickTest::pointerPress(device, &window, 0, outsidePos, button); + QQuickTest::pointerRelease(device, &window, 0, outsidePos, button); + if (lcPointerTests().isDebugEnabled()) QTest::qWait(500); + QCOMPARE(tapSpy.size(), 0); + QCOMPARE(tapActiveSpy.size(), 0); +} + QTEST_MAIN(tst_FlickableInterop) #include "tst_flickableinterop.moc" diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/nestedPinchArea.qml b/tests/auto/quick/qquickmultipointtoucharea/data/nestedPinchArea.qml new file mode 100644 index 0000000000..0e51804b30 --- /dev/null +++ b/tests/auto/quick/qquickmultipointtoucharea/data/nestedPinchArea.qml @@ -0,0 +1,44 @@ +import QtQuick 2.15 + +MultiPointTouchArea { + width: 240 + height: 320 + mouseEnabled: true + property int pressedCount: 0 + property int updatedCount: 0 + property int releasedCount: 0 + + onPressed: (points) => { pressedCount = points.length } + onUpdated: (points) => { updatedCount = points.length } + onReleased: (points) => { releasedCount = points.length } + + touchPoints: [ + TouchPoint { + id: point1 + objectName: "point1" + }, + TouchPoint { + id: point2 + objectName: "point2" + } + ] + + PinchArea { + anchors.fill: parent + } + + Rectangle { + width: 30; height: 30 + color: "green" + x: point1.x + y: point1.y + } + + Rectangle { + id: rectangle + width: 30; height: 30 + color: "yellow" + x: point2.x + y: point2.y + } +} diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp index 3e6a7fce16..f85fba45d6 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp +++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp @@ -74,6 +74,7 @@ private slots: void cancel(); void stationaryTouchWithChangingPressure(); void touchFiltering(); + void nestedPinchAreaMouse(); private: QQuickView *createAndShowView(const QString &file); @@ -1385,6 +1386,49 @@ void tst_QQuickMultiPointTouchArea::touchFiltering() // QTBUG-74028 QCOMPARE(mptaSpy.count(), 1); } +void tst_QQuickMultiPointTouchArea::nestedPinchAreaMouse() // QTBUG-83662 +{ + QScopedPointer<QQuickView> window(createAndShowView("nestedPinchArea.qml")); + QQuickMultiPointTouchArea *mpta = qobject_cast<QQuickMultiPointTouchArea *>(window->rootObject()); + QVERIFY(mpta); + QQuickTouchPoint *point1 = mpta->findChild<QQuickTouchPoint*>("point1"); + QCOMPARE(point1->pressed(), false); + QQuickTouchPoint *point2 = mpta->findChild<QQuickTouchPoint*>("point2"); + QCOMPARE(point2->pressed(), false); + QSignalSpy pressedSpy(mpta, &QQuickMultiPointTouchArea::pressed); + QSignalSpy updatedSpy(mpta, &QQuickMultiPointTouchArea::updated); + QSignalSpy releasedSpy(mpta, &QQuickMultiPointTouchArea::released); + QPoint p1(20, 20); + QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, p1); + QCOMPARE(point1->pressed(), true); + QCOMPARE(point2->pressed(), false); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(mpta->property("pressedCount").toInt(), 1); + QCOMPARE(updatedSpy.count(), 0); + QCOMPARE(mpta->property("updatedCount").toInt(), 0); + QCOMPARE(releasedSpy.count(), 0); + QCOMPARE(mpta->property("releasedCount").toInt(), 0); + p1 += QPoint(0, 15); + QTest::mouseMove(window.data(), p1); + QCOMPARE(point1->pressed(), true); + QCOMPARE(point2->pressed(), false); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(mpta->property("pressedCount").toInt(), 1); + QCOMPARE(updatedSpy.count(), 1); + QCOMPARE(mpta->property("updatedCount").toInt(), 1); + QCOMPARE(releasedSpy.count(), 0); + QCOMPARE(mpta->property("releasedCount").toInt(), 0); + QTest::mouseRelease(window.data(), Qt::LeftButton, Qt::NoModifier, p1); + QCOMPARE(point1->pressed(), false); + QCOMPARE(point2->pressed(), false); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(mpta->property("pressedCount").toInt(), 1); + QCOMPARE(updatedSpy.count(), 1); + QCOMPARE(mpta->property("updatedCount").toInt(), 1); + QCOMPARE(releasedSpy.count(), 1); + QCOMPARE(mpta->property("releasedCount").toInt(), 1); +} + QTEST_MAIN(tst_QQuickMultiPointTouchArea) #include "tst_qquickmultipointtoucharea.moc" diff --git a/tests/auto/quick/qquicktableview/data/deletedDelegate.qml b/tests/auto/quick/qquicktableview/data/deletedDelegate.qml new file mode 100644 index 0000000000..ec3161bbac --- /dev/null +++ b/tests/auto/quick/qquicktableview/data/deletedDelegate.qml @@ -0,0 +1,25 @@ +import QtQuick 2.15 + +Item { + width: 800 + height: 600 + + Component { + id: dyn + Item { + property Component comp: Item {} + } + } + + TableView { + id: tv + anchors.fill: parent + objectName: "tableview" + } + + Component.onCompleted: { + let o = dyn.createObject(); + tv.delegate = o.comp; + o.destroy(); + } +} diff --git a/tests/auto/quick/qquicktableview/data/resetJsModelData.qml b/tests/auto/quick/qquicktableview/data/resetJsModelData.qml new file mode 100644 index 0000000000..def5346147 --- /dev/null +++ b/tests/auto/quick/qquicktableview/data/resetJsModelData.qml @@ -0,0 +1,19 @@ +import QtQuick + +Item { + width: 100 + height: 300 + + property alias tableView: tableView + + TableView { + id: tableView + anchors.fill: parent + property int modelUpdated: 0 + onModelChanged: { ++modelUpdated } + delegate: Item { + implicitHeight: 10 + implicitWidth: 10 + } + } +} diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp index 97dae95fce..ec568a21e4 100644 --- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp +++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp @@ -122,7 +122,7 @@ private slots: void isColumnLoadedAndIsRowLoaded(); void checkForceLayoutFunction(); void checkForceLayoutEndUpDoingALayout(); - void checkForceLayoutDuringModelChange(); + void checkForceLayoutInbetweenAddingRowsToModel(); void checkForceLayoutWhenAllItemsAreHidden(); void checkContentWidthAndHeight(); void checkContentWidthAndHeightForSmallTables(); @@ -213,6 +213,8 @@ private slots: void testSelectableStartPosEndPosOutsideView(); void testSelectableScrollTowardsPos(); void resettingRolesRespected(); + void deletedDelegate(); + void checkRebuildJsModel(); }; tst_QQuickTableView::tst_QQuickTableView() @@ -681,10 +683,11 @@ void tst_QQuickTableView::checkForceLayoutEndUpDoingALayout() QCOMPARE(tableView->contentHeight(), (9 * (newDelegateSize + rowSpacing)) - rowSpacing); } -void tst_QQuickTableView::checkForceLayoutDuringModelChange() +void tst_QQuickTableView::checkForceLayoutInbetweenAddingRowsToModel() { - // Check that TableView doesn't assert if we call - // forceLayout() in the middle of a model change. + // Check that TableView doesn't assert if we call forceLayout() while waiting + // for a callback from the model that the row count has changed. Also make sure + // that we don't move the contentItem while doing so. LOAD_TABLEVIEW("plaintableview.qml"); const int initialRowCount = 10; @@ -699,9 +702,13 @@ void tst_QQuickTableView::checkForceLayoutDuringModelChange() WAIT_UNTIL_POLISHED; + const int contentY = 10; + tableView->setContentY(contentY); QCOMPARE(tableView->rows(), initialRowCount); + QCOMPARE(tableView->contentY(), contentY); model.addRow(0); QCOMPARE(tableView->rows(), initialRowCount + 1); + QCOMPARE(tableView->contentY(), contentY); } void tst_QQuickTableView::checkForceLayoutWhenAllItemsAreHidden() @@ -3989,6 +3996,45 @@ void tst_QQuickTableView::resettingRolesRespected() QTRY_VERIFY(tableView->property("success").toBool()); } +void tst_QQuickTableView::deletedDelegate() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("deletedDelegate.qml")); + std::unique_ptr<QObject> root(component.create()); + QVERIFY(root); + auto tv = root->findChild<QQuickTableView *>("tableview"); + QVERIFY(tv); + // we need one event loop iteration for the deferred delete to trigger + // thus the QTRY_VERIFY + QTRY_COMPARE(tv->delegate(), nullptr); +} + +void tst_QQuickTableView::checkRebuildJsModel() +{ + LOAD_TABLEVIEW("resetJsModelData.qml"); // gives us 'tableView' variable + + // Generate javascript model + const int size = 5; + const char* modelUpdated = "modelUpdated"; + + QJSEngine jsEngine; + QJSValue jsArray; + jsArray = jsEngine.newArray(size); + for (int i = 0; i < size; ++i) + jsArray.setProperty(i, QRandomGenerator::global()->generate()); + + QVariant jsModel = QVariant::fromValue(jsArray); + tableView->setModel(jsModel); + WAIT_UNTIL_POLISHED; + + // Model change would be triggered for the first time + QCOMPARE(tableView->property(modelUpdated).toInt(), 1); + + // Set the same model once again and check if model changes + tableView->setModel(jsModel); + QCOMPARE(tableView->property(modelUpdated).toInt(), 1); +} + QTEST_MAIN(tst_QQuickTableView) #include "tst_qquicktableview.moc" diff --git a/tests/auto/quickcontrols2/qquickmenu/data/scrollableWithFixedHeight.qml b/tests/auto/quickcontrols2/qquickmenu/data/scrollableWithFixedHeight.qml new file mode 100644 index 0000000000..1156d30aef --- /dev/null +++ b/tests/auto/quickcontrols2/qquickmenu/data/scrollableWithFixedHeight.qml @@ -0,0 +1,27 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls +import QtQuick.Window + +Window { + width: 300 + height: 300 + + property alias menu: menu + + Menu { + id: menu + anchors.centerIn: parent + height: 100 + visible: true + Repeater { + model: 10 + delegate: MenuItem { + objectName: text + text: (index + 1) + } + } + } +} diff --git a/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp b/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp index 0176c2db35..4b1628038d 100644 --- a/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp +++ b/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp @@ -1778,6 +1778,7 @@ void tst_QQuickMenu::scrollable_data() QTest::addRow("Window") << QString::fromLatin1("windowScrollable.qml"); QTest::addRow("ApplicationWindow") << QString::fromLatin1("applicationWindowScrollable.qml"); QTest::addRow("WithPadding") << QString::fromLatin1("scrollableWithPadding.qml"); + QTest::addRow("FixedHeight") << QString::fromLatin1("scrollableWithFixedHeight.qml"); } void tst_QQuickMenu::scrollable() diff --git a/tests/auto/quickcontrols2/sanity/tst_sanity.cpp b/tests/auto/quickcontrols2/sanity/tst_sanity.cpp index c29a191cd9..dc1a4b3836 100644 --- a/tests/auto/quickcontrols2/sanity/tst_sanity.cpp +++ b/tests/auto/quickcontrols2/sanity/tst_sanity.cpp @@ -458,11 +458,6 @@ void tst_Sanity::attachedObjects_data() QTest::newRow("Basic/HorizontalHeaderView.qml") << ignoredNames << StringPairSet {}; QTest::newRow("Basic/ItemDelegate.qml") << ignoredNames << StringPairSet {}; QTest::newRow("Basic/Label.qml") << ignoredNames << StringPairSet {}; - QTest::newRow("Basic/Menu.qml") << ignoredNames << StringPairSet { - { "QQuickOverlayAttached", "Menu_QMLTYPE" }, - { "QQuickScrollIndicatorAttached", "QQuickListView" }, - { "QQuickWindowAttached", "QQuickListView" } - }; QTest::newRow("Basic/MenuBar.qml") << ignoredNames << StringPairSet {}; QTest::newRow("Basic/MenuBarItem.qml") << ignoredNames << StringPairSet {}; QTest::newRow("Basic/MenuItem.qml") << ignoredNames << StringPairSet {}; @@ -513,11 +508,6 @@ void tst_Sanity::attachedObjects_data() QTest::newRow("Fusion/HorizontalHeaderView.qml") << ignoredNames << StringPairSet {}; QTest::newRow("Fusion/ItemDelegate.qml") << ignoredNames << StringPairSet {}; QTest::newRow("Fusion/Label.qml") << ignoredNames << StringPairSet {}; - QTest::newRow("Fusion/Menu.qml") << ignoredNames << StringPairSet { - { "QQuickOverlayAttached", "Menu_QMLTYPE" }, - { "QQuickScrollIndicatorAttached", "QQuickListView" }, - { "QQuickWindowAttached", "QQuickListView" } - }; QTest::newRow("Fusion/MenuBar.qml") << ignoredNames << StringPairSet {}; QTest::newRow("Fusion/MenuBarItem.qml") << ignoredNames << StringPairSet {}; QTest::newRow("Fusion/MenuItem.qml") << ignoredNames << StringPairSet {}; @@ -573,13 +563,6 @@ void tst_Sanity::attachedObjects_data() QTest::newRow("Material/HorizontalHeaderView.qml") << ignoredNames << StringPairSet {}; QTest::newRow("Material/ItemDelegate.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "ItemDelegate_QMLTYPE" }}; QTest::newRow("Material/Label.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "Label_QMLTYPE" }}; - QTest::newRow("Material/Menu.qml") << ignoredNames << StringPairSet { - { "QQuickOverlayAttached", "Menu_QMLTYPE" }, - { "QQuickMaterialStyle", "Menu_QMLTYPE" }, - { "QQuickScrollIndicatorAttached", "QQuickListView" }, - { "QQuickWindowAttached", "QQuickListView" }, - { "QQuickMaterialStyle", "ScrollIndicator_QMLTYPE" } - }; QTest::newRow("Material/MenuBar.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "MenuBar_QMLTYPE" }}; QTest::newRow("Material/MenuBarItem.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "MenuBarItem_QMLTYPE" }}; QTest::newRow("Material/MenuItem.qml") << ignoredNames << StringPairSet {{ "QQuickMaterialStyle", "MenuItem_QMLTYPE" }}; @@ -646,13 +629,6 @@ void tst_Sanity::attachedObjects_data() QTest::newRow("Universal/HorizontalHeaderView.qml") << ignoredNames << StringPairSet {}; QTest::newRow("Universal/ItemDelegate.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "ItemDelegate_QMLTYPE" }}; QTest::newRow("Universal/Label.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "Label_QMLTYPE" }}; - QTest::newRow("Universal/Menu.qml") << ignoredNames << StringPairSet { - { "QQuickOverlayAttached", "Menu_QMLTYPE" }, - { "QQuickUniversalStyle", "Menu_QMLTYPE" }, - { "QQuickScrollIndicatorAttached", "QQuickListView" }, - { "QQuickWindowAttached", "QQuickListView" }, - { "QQuickUniversalStyle", "ScrollIndicator_QMLTYPE" } - }; QTest::newRow("Universal/MenuBar.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "MenuBar_QMLTYPE" }}; QTest::newRow("Universal/MenuBarItem.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "MenuBarItem_QMLTYPE" }}; QTest::newRow("Universal/MenuItem.qml") << ignoredNames << StringPairSet {{ "QQuickUniversalStyle", "MenuItem_QMLTYPE" }}; |