From c4788c54c20ab80ab37e768180aed8badc424cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Fri, 16 Dec 2022 09:57:13 +0000 Subject: Revert "Blacklist 1 tests in tst_qquickflickable on macos" This reverts commit c6d8d037828701622d5664b5141e1ffe18065097. Reason for revert: CI Insignificant Platforms Monitor Bot erroneously thought that setContentPositionWhileDragging() was failing: (see https://bugreports.qt.io/browse/QTBUG-106278) Change-Id: I24c644c24b9cddcd348a87a2c486dc5d7c126ce8 Reviewed-by: Heikki Halmet --- tests/auto/quick/qquickflickable/BLACKLIST | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 tests/auto/quick/qquickflickable/BLACKLIST diff --git a/tests/auto/quick/qquickflickable/BLACKLIST b/tests/auto/quick/qquickflickable/BLACKLIST deleted file mode 100644 index 636aef4904..0000000000 --- a/tests/auto/quick/qquickflickable/BLACKLIST +++ /dev/null @@ -1,3 +0,0 @@ -# See qtbase/src/testlib/qtestblacklist.cpp for format -[setContentPositionWhileDragging] -ci macos # QTBUG-106278 -- cgit v1.2.3 From f31d58049257b4853f6a0213be22f1956661e9de Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 19 Dec 2022 10:05:33 +0100 Subject: Fix missing glyphs when using NativeRendering When we look up glyphs with subpixel positions in the glyph cache, we use the calculated subpixel position (from a set of predefined subpixel positions) as key. In some very rare cases, we could end up with different subpixel positions when looking up an on-screen position than when we entered it into the cache, due to numerical differences when doing the calculation. The reason for this was that when entering the glyph into the cache, we used the 16.6 fixed point representation, whereas when looking up, we used the unmodified float. In some cases, the converted fixed point approximation might snap to a different predefined subpixel position than the floating point equivalent. To avoid this, we reuse the converted fixed point positions when looking up the glyphs in the cache. [ChangeLog][Text] Fixed an issue where text using NativeRendering would sometimes be missing glyphs. Fixes: QTBUG-108713 Change-Id: Iecc264eb3d27e875c24257eaefcfb18a1a5fb5be Reviewed-by: Qt CI Bot Reviewed-by: Lars Knoll (cherry picked from commit 4bad329985b75090c68a70cceee7edadc172d7ab) Reviewed-by: Qt Cherry-pick Bot --- src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp index 61d542fbcb..8d76aa56a2 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp @@ -842,9 +842,11 @@ void QSGTextMaskMaterial::populate(const QPointF &p, bool supportsSubPixelPositions = fontD->fontEngine->supportsSubPixelPositions(); for (int i=0; ifontEngine->subPixelPositionForX(QFixed::fromReal(glyphPosition.x() * glyphCacheScaleX)); + subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(fixedPointPosition.x.toReal() * glyphCacheScaleX)); QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphIndexes.at(i), subPixelPosition); const QTextureGlyphCache::Coord &c = cache->coords.value(glyph); -- cgit v1.2.3 From e6b374463336a5a257565da7e3233ecdf04f2de4 Mon Sep 17 00:00:00 2001 From: Oliver Eftevaag Date: Fri, 9 Dec 2022 18:40:54 +0100 Subject: Flickable: prevent fixup() from being called while dragging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A previous patch 5647527a8cde84b51fff66fc482f02435770b3dd causes a regression. The purpose of the patch, that caused this regression, was to update the pressPos variables, in cases where the contentItem's geometry was modified externally, while a user were dragging the contentItem around. The mistake that was made, was how width and height changes were handled. We had previously added logic in setContentWidth() and setContentHeight() that would call fixup() (with immediate fixupMode) to ensure that the contentItem would immediately be repositioned inside the flickable's viewport, if the contentItem was being dragged. It turns out that setContentWidth() and setContentHeight() are being called from QQuickItemViewPrivate::updateViewport(), which happens quite often, while dragging. This would make fixup() and dragging constantly interfere with each other, since they'd not always agree on a specific position for the contentItem. This patch reverts the changes made to setContentWidth() and setContentHeight(), since it turns out that those changes weren't necessary after all. QQuickFlickablePrivate::itemGeometryChanged() only calls viewportMoved() on x and y changes anyways. Done-with: Jan Arve Sæther Done-with: Santhosh Kumar Selvaraj Fixes: QTBUG-109140 Change-Id: I0bddf8685d3afc1ae04b2c092212d3c1bd742c3b Reviewed-by: Paul Wicking (cherry picked from commit b307bf3c4f63c6e04874a972c747f18e18ddc199) Reviewed-by: Qt Cherry-pick Bot --- src/quick/items/qquickflickable.cpp | 8 ++------ src/quick/items/qquickflickable_p_p.h | 1 + tests/auto/quick/qquickflickable/tst_qquickflickable.cpp | 8 +++++++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index ea39edff18..c7efdc47fb 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -2120,11 +2120,9 @@ void QQuickFlickable::setContentWidth(qreal w) d->contentItem->setWidth(w); d->hData.markExtentsDirty(); // Make sure that we're entirely in view. - if ((!d->pressed && !d->hData.moving && !d->vData.moving) || d->hData.dragging) { - d->hData.contentPositionChangedExternallyDuringDrag = d->hData.dragging; + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QQuickFlickablePrivate::Immediate; d->fixupX(); - d->hData.contentPositionChangedExternallyDuringDrag = false; } else if (!d->pressed && d->hData.fixingUp) { d->fixupMode = QQuickFlickablePrivate::ExtentChanged; d->fixupX(); @@ -2151,11 +2149,9 @@ void QQuickFlickable::setContentHeight(qreal h) d->contentItem->setHeight(h); d->vData.markExtentsDirty(); // Make sure that we're entirely in view. - if ((!d->pressed && !d->hData.moving && !d->vData.moving) || d->vData.dragging) { - d->vData.contentPositionChangedExternallyDuringDrag = d->vData.dragging; + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QQuickFlickablePrivate::Immediate; d->fixupY(); - d->vData.contentPositionChangedExternallyDuringDrag = false; } else if (!d->pressed && d->vData.fixingUp) { d->fixupMode = QQuickFlickablePrivate::ExtentChanged; d->fixupY(); diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h index 0b990739fb..6bff809b79 100644 --- a/src/quick/items/qquickflickable_p_p.h +++ b/src/quick/items/qquickflickable_p_p.h @@ -120,6 +120,7 @@ public: dragStartOffset = 0; fixingUp = false; inOvershoot = false; + contentPositionChangedExternallyDuringDrag = false; } void markExtentsDirty() { diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index d092cd0170..62f7c67dd4 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -2642,7 +2642,12 @@ void tst_qquickflickable::setContentPositionWhileDragging() // QTBUG-104966 } else if (newExtent >= 0) { // ...or reduce the content size be be less than current (contentX, contentY) position // This forces the content item to move. - expectedContentPos = moveDelta; + // contentY: 150 + // 320 - 150 = 170 pixels down to bottom + // Now reduce contentHeight to 200 + // since we are at the bottom, and the flickable is 100 pixels tall, contentY must land + // at newExtent - 100. + if (isHorizontal) { flickable->setContentWidth(newExtent); } else { @@ -2652,6 +2657,7 @@ void tst_qquickflickable::setContentPositionWhileDragging() // QTBUG-104966 // We therefore cannot scroll/flick it further down. Drag it up towards the top instead // (by moving mouse down). pos += moveDelta; + expectedContentPos = unitDelta * (newExtent - (isHorizontal ? flickable->width() : flickable->height())); } QTest::mouseMove(window.data(), pos); -- cgit v1.2.3 From 6caa94691ffb5e295fac1cc10c5b2ac19a4376bd Mon Sep 17 00:00:00 2001 From: Tarja Sundqvist Date: Thu, 22 Dec 2022 11:11:02 +0200 Subject: Bump version to 5.15.13 Change-Id: Ie7e4af9ab3784029a720bf30f5723cde12dead75 Reviewed-by: Tarja Sundqvist --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index 703f7df915..65ef03633e 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,4 +4,4 @@ CONFIG += warning_clean DEFINES += QT_NO_LINKED_LIST DEFINES += QT_NO_JAVA_STYLE_ITERATORS -MODULE_VERSION = 5.15.12 +MODULE_VERSION = 5.15.13 -- cgit v1.2.3 From 0cee1a4942764f2a7829606c43681d845817d01b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 30 Nov 2021 14:39:48 +0100 Subject: Qml: Don't crash when as-casting to type with errors Such types don't have a compilation unit, but we still know their names. Fixes: QTBUG-98792 Change-Id: I2db8dea3a5a02ec1492f7f7a054fd3ad4c6ad69a Reviewed-by: Fabian Kosmale Reviewed-by: Mitch Curtis (cherry picked from commit e0cd201e91ae64b9c03e0128cd17656b00611fbb) --- src/qml/qml/qqmltypewrapper.cpp | 6 ++++-- tests/auto/qml/qqmllanguage/data/Broken.qml | 5 +++++ tests/auto/qml/qqmllanguage/data/asBroken.qml | 6 ++++++ tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 20 ++++++++++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 tests/auto/qml/qqmllanguage/data/Broken.qml create mode 100644 tests/auto/qml/qqmllanguage/data/asBroken.qml diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 6bf9455e17..00c28f90c7 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -419,8 +419,10 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const return Encode(false); QQmlRefPointer td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl()); - ExecutableCompilationUnit *cu = td->compilationUnit(); - myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId); + if (ExecutableCompilationUnit *cu = td->compilationUnit()) + myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId); + else + return Encode(false); // It seems myQmlType has some errors, so we could not compile it. } else { myQmlType = qenginepriv->metaObjectForType(myTypeId); } diff --git a/tests/auto/qml/qqmllanguage/data/Broken.qml b/tests/auto/qml/qqmllanguage/data/Broken.qml new file mode 100644 index 0000000000..e1b61f31f4 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/Broken.qml @@ -0,0 +1,5 @@ +import QtQml + +QtObject { + notThere: 5 +} diff --git a/tests/auto/qml/qqmllanguage/data/asBroken.qml b/tests/auto/qml/qqmllanguage/data/asBroken.qml new file mode 100644 index 0000000000..bd88d14c76 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/asBroken.qml @@ -0,0 +1,6 @@ +import QtQml 2.15 + +QtObject { + id: self + property var selfAsBroken: self as Broken +} diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index ac6634290a..92d0069ce4 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -343,6 +343,8 @@ private slots: void bindingAliasToComponentUrl(); void badGroupedProperty(); + void objectAsBroken(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -5951,6 +5953,24 @@ void tst_qqmllanguage::badGroupedProperty() .arg(url.toString())); } +void tst_qqmllanguage::objectAsBroken() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("asBroken.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer o(c.create()); + QVERIFY(!o.isNull()); + QVariant selfAsBroken = o->property("selfAsBroken"); + QVERIFY(selfAsBroken.isValid()); + + // 5.15 doesn't enforce type annotation. So the "as" cast succeeds even though + // the target type cannot be resolved. + QCOMPARE(selfAsBroken.value(), o.data()); + + QQmlComponent b(&engine, testFileUrl("Broken.qml")); + QVERIFY(b.isError()); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" -- cgit v1.2.3 From 72e8afdd9b5a1b06eb6d2e34057fe3dc0ce9c2f4 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 17 Dec 2022 17:45:41 +0100 Subject: QQmlPropertyCache: don't depend on locale for toupper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The C toupper/tolower functions are locale-dependent. Given the right locale (Türkiye, e.g.), toupper(i) is either - İ (LATIN CAPITAL LETTER I WITH DOT ABOVE; if representable) or - i (unchanged; if it isn't) Both results are wrong for the present use-case. Use the new QtMiscUtils::toAsciiUpper() function instead. Amends d481f2ff518df1e44103d1850e7d52bd69260c34. Task-number: QTBUG-109235 Change-Id: Ib66593fc7eff3edc0cc16291ca3eae8bdf0dd8ed Reviewed-by: Fabian Kosmale (cherry picked from commit 179200d2a3fa0df28fbf3790f8ff1ee47d0926c0) Reviewed-by: Qt Cherry-pick Bot --- src/qml/qml/qqmlpropertycache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 11e967105c..fc43b63509 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -51,8 +51,8 @@ #include #include +#include -#include // for toupper #include #include @@ -571,7 +571,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, QVarLengthArray str(length+3); str[0] = 'o'; str[1] = 'n'; - str[2] = toupper(rawName[0]); + str[2] = QtMiscUtils::toAsciiUpper(rawName[0]); if (length > 1) memcpy(&str[3], &rawName[1], length - 1); str[length + 2] = '\0'; -- cgit v1.2.3 From 8fdcbd60e4d520fbfd4683cb6fe2350144ef2ca9 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 11 Jan 2023 12:28:02 +0100 Subject: Fix Shape stroke color when changing alpha from 0 to non-0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The handling of the stroke color lacks the extra checks that are performed when setting the fill color. Switching from "transparent" to another color involves setting not just the color-dirty flag but also the geometry-dirty since alpha == 0 may skip operations such as triangulating, meaning the work has to be performed later when once again switching to an alpha > 0 color. Change-Id: Ibd6d762cfcb07ca8b9c852553c979bcb4ee9fa21 Fixes: QTBUG-109882 Reviewed-by: Christian Strømme (cherry picked from commit 650e7d47f8e333761df86e60c290e885106b26c6) Reviewed-by: Qt Cherry-pick Bot --- src/quickshapes/qquickshapegenericrenderer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/quickshapes/qquickshapegenericrenderer.cpp b/src/quickshapes/qquickshapegenericrenderer.cpp index 8d2097f95b..6e87784bfc 100644 --- a/src/quickshapes/qquickshapegenericrenderer.cpp +++ b/src/quickshapes/qquickshapegenericrenderer.cpp @@ -188,8 +188,12 @@ void QQuickShapeGenericRenderer::setPath(int index, const QQuickPath *path) void QQuickShapeGenericRenderer::setStrokeColor(int index, const QColor &color) { ShapePathData &d(m_sp[index]); + const bool wasTransparent = d.strokeColor.a == 0; d.strokeColor = colorToColor4ub(color); + const bool isTransparent = d.strokeColor.a == 0; d.syncDirty |= DirtyColor; + if (wasTransparent && !isTransparent) + d.syncDirty |= DirtyStrokeGeom; } void QQuickShapeGenericRenderer::setStrokeWidth(int index, qreal w) -- cgit v1.2.3 From 633cf1faf580cf8984c7c6f4a623c8821cb5044b Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 20 Jan 2023 07:01:51 +0100 Subject: Test262Runner: fix -Wunused-but-set-variable The 'int line' variable is shadowed a few lines below by the 'QByteArray line' one, even in the initial commit, so it can never have been used, except for the increment in the first line of the loop's bodies. Remove the variable, fix the warning. Found by Clang 15: test262runner.cpp:380:9: warning: variable 'line' set but not used [-Wunused-but-set-variable] int line = 0; ^ Amends d9c4a527241e0ef3a30e990c518197b0ba345b50. Change-Id: I2139aa4552d1ff2ddbb5737e2a1b26650d6519e7 Reviewed-by: Ulf Hermann (cherry picked from commit 9d04888c9cb8a89f17279da6ed9b9f65a49a94b0) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp index 9fe2de5368..2b6145030b 100644 --- a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp +++ b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp @@ -393,9 +393,7 @@ void Test262Runner::loadTestExpectations() return; } - int line = 0; while (!file.atEnd()) { - ++line; QByteArray line = file.readLine().trimmed(); if (line.startsWith('#') || line.isEmpty()) continue; @@ -440,9 +438,7 @@ void Test262Runner::updateTestExpectations() QTemporaryFile updatedExpectations; updatedExpectations.open(); - int line = 0; while (!file.atEnd()) { - ++line; QByteArray originalLine = file.readLine(); QByteArray line = originalLine.trimmed(); if (line.startsWith('#') || line.isEmpty()) { -- cgit v1.2.3 From 778659c100996947e70ffd7a67ec2bcf748c5082 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Thu, 19 Jan 2023 10:56:50 +0100 Subject: QJSEngine: Fix potential JS stack overflow cauased by spread operator createSpreadArguments could in theory allocate a (nearly) unbounded number of QV4::Values. Avoid this by checking whether we approach jsStackTop. This fixes CVE-2022-43591. Change-Id: I01aecb979da47b7261688c9f185dc33a50a579a5 Reviewed-by: Ulf Hermann (cherry picked from commit 6511aa4344c1d47ede8546540fe70bdff8523545) --- src/qml/jsruntime/qv4runtime.cpp | 5 +++++ tests/auto/qml/qjsengine/tst_qjsengine.cpp | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index cbca86e90c..7e6156f55a 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1530,6 +1530,11 @@ static CallArgs createSpreadArguments(Scope &scope, Value *argv, int argc) if (done->booleanValue()) break; ++argCount; + constexpr auto safetyMargin = 100; // leave some space on the stack for actual work with the elements + if (qint64(scope.engine->jsStackLimit - scope.engine->jsStackTop) < safetyMargin) { + scope.engine->throwRangeError(QLatin1String("Too many elements in array to use it with the spread operator")); + return { nullptr, 0 }; + } v = scope.alloc(); } } diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 363070d7f8..f1c34e6142 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -271,6 +271,8 @@ private slots: void uiLanguage(); void forOfAndGc(); + void spreadNoOverflow(); + public: Q_INVOKABLE QJSValue throwingCppMethod1(); Q_INVOKABLE void throwingCppMethod2(); @@ -5339,6 +5341,16 @@ void tst_QJSEngine::forOfAndGc() QTRY_VERIFY(o->property("count").toInt() > 32768); } +void tst_QJSEngine::spreadNoOverflow() +{ + QJSEngine engine; + + const QString program = QString::fromLatin1("var a = [] ;a.length = 555840;Math.max(...a)"); + const QJSValue result = engine.evaluate(program); + QVERIFY(result.isError()); + QCOMPARE(result.errorType(), QJSValue::RangeError); +} + QTEST_MAIN(tst_QJSEngine) #include "tst_qjsengine.moc" -- cgit v1.2.3 From 6dc7fa90efa592dc555008b0e8d666c72801f31d Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 26 Jan 2023 10:58:32 +0100 Subject: StateMachine: Don't crash if no signal is passed to SignalTransition Rather, just reset the transition. Adapted from commit af4c8da54bbf057f3a8d7cf8a8e4146d35aad7f6 in qtscxml. Fixes: QTBUG-110286 Change-Id: I49a7588f771c4caa73e85334487d9d9c0260a7ce Reviewed-by: Fabian Kosmale --- src/imports/statemachine/signaltransition.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/imports/statemachine/signaltransition.cpp b/src/imports/statemachine/signaltransition.cpp index 99a9ebba95..c571306658 100644 --- a/src/imports/statemachine/signaltransition.cpp +++ b/src/imports/statemachine/signaltransition.cpp @@ -171,7 +171,11 @@ void SignalTransition::connectTriggered() QV4::ExecutionEngine *jsEngine = QQmlEngine::contextForObject(this)->engine()->handle(); QV4::Scope scope(jsEngine); QV4::Scoped qobjectSignal(scope, QJSValuePrivate::convertedToValue(jsEngine, m_signal)); - Q_ASSERT(qobjectSignal); + if (!qobjectSignal) { + m_signalExpression.take(nullptr); + return; + } + QMetaMethod metaMethod = target->metaObject()->method(qobjectSignal->methodIndex()); int signalIndex = QMetaObjectPrivate::signalIndex(metaMethod); -- cgit v1.2.3 From 2a6897b9cee24c1631655c02cd41c3640e9d807a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20S=C3=B8rvig?= Date: Wed, 23 Nov 2022 10:11:52 +0100 Subject: Fix "white line on top and left side of screen" issue Reproduced on Android, where devices sometimes have screen sizes which are not evenly dividable by the device scale factor (see QTBUG-87334 for examples). Get the surface size for renderSceneGraph() directly from the QPlatformWindow size. This avoids using the QWindow size, which might have been rounded and can yield a surface size which are off by a one or two of pixels. Also change the "logicalSize" calculation to always use the size passed to renderSceneGraph(), in order to avoid rounding errors also here. Fixes: QTBUG-87334 Change-Id: I23b5784305a876e1ef15ff6b01be09c6ce28409e Reviewed-by: Qt CI Bot Reviewed-by: Assam Boudjelthia --- src/quick/items/qquickwindow.cpp | 12 ++---------- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 12 +++++++++++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index c6c7b6171e..5d993e4698 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -591,15 +591,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa renderer->setDevicePixelRatio(1); } } else { - QSize pixelSize; - QSizeF logicalSize; - if (surfaceSize.isEmpty()) { - pixelSize = size * devicePixelRatio; - logicalSize = size; - } else { - pixelSize = surfaceSize; - logicalSize = QSizeF(surfaceSize) / devicePixelRatio; - } + const QSize pixelSize = surfaceSize.isEmpty() ? size * devicePixelRatio : surfaceSize; QRect rect(QPoint(0, 0), pixelSize); renderer->setDeviceRect(rect); renderer->setViewportRect(rect); @@ -607,7 +599,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa QSGAbstractRenderer::MatrixTransformFlags matrixFlags; if (flipY) matrixFlags |= QSGAbstractRenderer::MatrixTransformFlipY; - renderer->setProjectionMatrixToRect(QRectF(QPoint(0, 0), logicalSize), matrixFlags); + renderer->setProjectionMatrixToRect(QRectF(QPoint(0, 0), size), matrixFlags); renderer->setDevicePixelRatio(devicePixelRatio); } diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index da0e8bdc7c..457e362b80 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -368,6 +368,7 @@ public: QQuickWindow *window; // Will be 0 when window is not exposed QSize windowSize; + QSize windowPixelSize; float dpr = 1; int rhiSampleCount = 1; bool rhiDeviceLost = false; @@ -406,6 +407,8 @@ bool QSGRenderThread::event(QEvent *e) stopEventProcessing = true; window = se->window; windowSize = se->size; + if (window) + windowPixelSize = window->handle()->geometry().size(); dpr = se->dpr; pendingUpdate |= SyncRequest; @@ -833,7 +836,14 @@ void QSGRenderThread::syncAndRender(QImage *grabImage) } } if (current) { - d->renderSceneGraph(windowSize, rhi ? cd->swapchain->currentPixelSize() : QSize()); + const QSize surfaceSize = [this, cd]{ + if (rhi) + return cd->swapchain->currentPixelSize(); + if (windowPixelSize.isValid()) + return windowPixelSize; + return QSize(); + }(); + d->renderSceneGraph(windowSize, surfaceSize); if (profileFrames) renderTime = threadTimer.nsecsElapsed(); -- cgit v1.2.3 From cfd461d438d40cc55e8085b79d0e4b2c03371e46 Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Wed, 8 Feb 2023 13:57:55 +0100 Subject: Revert "Trim file names before adding them to qml components and scripts" This reverts commit 5dffe98733ba05a8da801af0008f085ec2857ddd. Reason for revert: This breaks Quick style plugin loading QTBUG-110433 Task-number: QTBUG-36637 Task-number: QTBUG-97834 Task-number: QTBUG-110433 Change-Id: I6f03cfe2633408e057a8c640acda5b59f5e5840c Reviewed-by: Alexandru Croitor --- tools/qmlimportscanner/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp index 6e2300a069..52eebcdf65 100644 --- a/tools/qmlimportscanner/main.cpp +++ b/tools/qmlimportscanner/main.cpp @@ -182,11 +182,11 @@ QVariantMap pluginsForModulePath(const QString &modulePath) { } else if (sections.size() == 2 && sectionType != "module" && sectionType != "typeinfo") { componentFiles.append(modulePath + QLatin1Char('/') - + QString::fromUtf8(sections.at(1)).trimmed()); + + QString::fromUtf8(sections.at(1))); } else if (sections.size() == 3 || (sectionType == "singleton" && sections.size() == 4)) { int fileNameIndex = (sectionType == "singleton") ? 3 : 2; - const QString fileName = QString::fromUtf8(sections.at(fileNameIndex)).trimmed(); + const QString fileName = QString::fromUtf8(sections.at(fileNameIndex)); const QString filePath = modulePath + QLatin1Char('/') + fileName; if (fileName.endsWith(QLatin1String(".js")) || fileName.endsWith(QLatin1String(".mjs"))) -- cgit v1.2.3 From d83b399d412375a0878b8023b8ea6fc115e98c70 Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Wed, 8 Feb 2023 14:15:32 +0100 Subject: Revert "Add listing of the components and scripts that belongs to the qml module" This reverts commit 2cc85e60d4313bd845bfdc233e5e75a8b7ccb01f. Reason for revert: This breaks Quick style plugin loading QTBUG-110433 Task-number: QTBUG-36637 Task-number: QTBUG-97834 Task-number: QTBUG-110433 Change-Id: If1aa6b6019a2db7652fa6b9fbe034fd1ef66a492 Reviewed-by: Alexandru Croitor --- tools/qmlimportscanner/main.cpp | 66 ++++++++--------------------------------- 1 file changed, 12 insertions(+), 54 deletions(-) diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp index 52eebcdf65..9f6a89810f 100644 --- a/tools/qmlimportscanner/main.cpp +++ b/tools/qmlimportscanner/main.cpp @@ -71,14 +71,6 @@ inline QString dependenciesLiteral() { return QStringLiteral("dependencies"); } inline QString moduleLiteral() { return QStringLiteral("module"); } inline QString javascriptLiteral() { return QStringLiteral("javascript"); } inline QString directoryLiteral() { return QStringLiteral("directory"); } -inline QString componentsLiteral() -{ - return QStringLiteral("components"); -} -inline QString scriptsLiteral() -{ - return QStringLiteral("scripts"); -} void printUsage(const QString &appNameIn) { @@ -158,42 +150,21 @@ QVariantMap pluginsForModulePath(const QString &modulePath) { QString plugins; QString classnames; QStringList dependencies; - QStringList componentFiles; - QStringList scriptFiles; QByteArray line; do { line = qmldirFile.readLine(); - const QList sections = line.split(' '); - if (sections.size() > 0) { - const QByteArray §ionType = sections.at(0); - if (sectionType == "plugin") { - plugins += QString::fromUtf8(line.split(' ').at(1)); - plugins += QLatin1Char(' '); - } else if (sectionType == "classname") { - classnames += QString::fromUtf8(line.split(' ').at(1)); - classnames += QLatin1Char(' '); - } else if (sectionType == "depends") { - if (sections.size() != 3) - std::cerr << "depends: expected 2 arguments: module identifier and version" - << std::endl; - else - dependencies << QString::fromUtf8(sections.at(1)) + QLatin1Char(' ') - + QString::fromUtf8(sections.at(2)).simplified(); - } else if (sections.size() == 2 && sectionType != "module" - && sectionType != "typeinfo") { - componentFiles.append(modulePath + QLatin1Char('/') - + QString::fromUtf8(sections.at(1))); - } else if (sections.size() == 3 - || (sectionType == "singleton" && sections.size() == 4)) { - int fileNameIndex = (sectionType == "singleton") ? 3 : 2; - const QString fileName = QString::fromUtf8(sections.at(fileNameIndex)); - const QString filePath = modulePath + QLatin1Char('/') + fileName; - if (fileName.endsWith(QLatin1String(".js")) - || fileName.endsWith(QLatin1String(".mjs"))) - scriptFiles.append(filePath); - else - componentFiles.append(filePath); - } + if (line.startsWith("plugin")) { + plugins += QString::fromUtf8(line.split(' ').at(1)); + plugins += QLatin1Char(' '); + } else if (line.startsWith("classname")) { + classnames += QString::fromUtf8(line.split(' ').at(1)); + classnames += QLatin1Char(' '); + } else if (line.startsWith("depends")) { + const QList dep = line.split(' '); + if (dep.length() != 3) + std::cerr << "depends: expected 2 arguments: module identifier and version" << std::endl; + else + dependencies << QString::fromUtf8(dep[1]) + QLatin1Char(' ') + QString::fromUtf8(dep[2]).simplified(); } } while (line.length() > 0); @@ -202,12 +173,7 @@ QVariantMap pluginsForModulePath(const QString &modulePath) { pluginInfo[pluginsLiteral()] = plugins.simplified(); pluginInfo[classnamesLiteral()] = classnames.simplified(); if (dependencies.length()) - dependencies.removeDuplicates(); pluginInfo[dependenciesLiteral()] = dependencies; - if (!componentFiles.isEmpty()) - pluginInfo[componentsLiteral()] = componentFiles; - if (!scriptFiles.isEmpty()) - pluginInfo[scriptsLiteral()] = scriptFiles; return pluginInfo; } @@ -281,8 +247,6 @@ QVariantList findPathsForModuleImports(const QVariantList &imports) QVariantMap plugininfo = pluginsForModulePath(import.value(pathLiteral()).toString()); QString plugins = plugininfo.value(pluginsLiteral()).toString(); QString classnames = plugininfo.value(classnamesLiteral()).toString(); - QStringList components = plugininfo.value(componentsLiteral()).toStringList(); - QStringList scripts = plugininfo.value(scriptsLiteral()).toStringList(); if (!plugins.isEmpty()) import.insert(QStringLiteral("plugin"), plugins); if (!classnames.isEmpty()) @@ -298,12 +262,6 @@ QVariantList findPathsForModuleImports(const QVariantList &imports) importsCopy.append(depImport); } } - if (!components.isEmpty()) { - import.insert(componentsLiteral(), components); - } - if (!scripts.isEmpty()) { - import.insert(scriptsLiteral(), scripts); - } } done.append(import); } -- cgit v1.2.3 From 261624e2d44ce9db0cb81abb230942becdb32af8 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 24 Jan 2023 11:43:11 +0100 Subject: Doc: Mention QDS and UI files in Best Practices Developers can easily break QDS .ui.qml files if they edit them as code. Link to the description of UI files in QDS Manual. Fixes: QTBUG-110354 Change-Id: Id5dc0e9fd420e0e4807a39d4f8d7d121e5137636 Reviewed-by: Thomas Hartmann (cherry picked from commit 5fabb872e0041aaf134b33e140d8f8512c31455b) Reviewed-by: Qt Cherry-pick Bot --- .../doc/src/guidelines/qtquick-bestpractices.qdoc | 27 +++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc b/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc index abfff7cc11..8cd51a50c6 100644 --- a/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc +++ b/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc @@ -52,11 +52,16 @@ options that align with the latest UI design trends. If these UI controls do not satisfy your application's needs, only then it is recommended to create a custom control. +You can use the controls when you design UIs in Qt Design Studio. In addition, +it provides timeline-based animations, visual effects, layouts, and a +live-preview for prototyping applications. \section2 Related Information \list \li \l{Qt Quick Controls} +\li \l{Customizing Qt Quick Controls} \li \l{Qt Quick} +\li \l{Qt Design Studio Manual} \endlist \omit @@ -146,7 +151,7 @@ specific file managed by the resource system. For example, if we wanted to give \li \l{The Qt Resource System} \endlist -\section1 Separate UI from Logic +\section1 Separate UI from Business Logic One of the key goals that most application developers want to achieve is to create a maintainable application. One of the ways to achieve this goal is @@ -162,8 +167,8 @@ reasons why an application's UI should be written in QML: \li JavaScript can easily be used in QML to respond to events. \endlist -Being a strongly typed language, C++ is best suited for an application's logic. -Typically, such code performs tasks such as complex calculations +Being a strongly typed language, C++ is best suited for an application's +business logic. Typically, such code performs tasks such as complex calculations or data processing, which are faster in C++ than QML. Qt offers various approaches to integrate QML and C++ code in an application. @@ -326,6 +331,22 @@ see \l {Choosing the Correct Integration Method Between C++ and QML}. \li \l{Qt Quick Controls - Chat Tutorial}{Chat application tutorial} \endlist +\section1 Using Qt Design Studio + +Qt Design Studio uses UI files that have the filename extension \e {.ui.qml} +to separate the visual parts of the UI from the UI logic you implement in +\e {.qml} files. You should edit UI files only in the \uicontrol {2D} view in +Qt Design Studio. If you use some other tool to add code that Qt Design Studio +does not support, it displays error messages. Fix the errors to enable visual +editing of the UI files again. Typically, you should move the unsupported code +to a \e {.qml} file. + +\section2 Related Information + +\list + \li \l{Qt Design Studio: UI Files} +\endlist + \section1 Using Qt Quick Layouts Qt offers Qt Quick Layouts to arrange Qt Quick items visually in a layout. -- cgit v1.2.3 From 0a8a7521ed395f385d111aa602f9c7b8d09ca991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20S=C3=B8rvig?= Date: Tue, 28 Feb 2023 12:48:30 +0100 Subject: Revert "Fix "white line on top and left side of screen" issue" This reverts commit 2a6897b9cee24c1631655c02cd41c3640e9d807a. This caused a regression on iOS where Qt painted to the bottom left quarter of the app window only. Fixes: QTBUG-111542 Change-Id: I9c56e410994966d01a29dfea45e5aec1f3e5a106 Reviewed-by: Assam Boudjelthia --- src/quick/items/qquickwindow.cpp | 12 ++++++++++-- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 12 +----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 5d993e4698..c6c7b6171e 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -591,7 +591,15 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa renderer->setDevicePixelRatio(1); } } else { - const QSize pixelSize = surfaceSize.isEmpty() ? size * devicePixelRatio : surfaceSize; + QSize pixelSize; + QSizeF logicalSize; + if (surfaceSize.isEmpty()) { + pixelSize = size * devicePixelRatio; + logicalSize = size; + } else { + pixelSize = surfaceSize; + logicalSize = QSizeF(surfaceSize) / devicePixelRatio; + } QRect rect(QPoint(0, 0), pixelSize); renderer->setDeviceRect(rect); renderer->setViewportRect(rect); @@ -599,7 +607,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa QSGAbstractRenderer::MatrixTransformFlags matrixFlags; if (flipY) matrixFlags |= QSGAbstractRenderer::MatrixTransformFlipY; - renderer->setProjectionMatrixToRect(QRectF(QPoint(0, 0), size), matrixFlags); + renderer->setProjectionMatrixToRect(QRectF(QPoint(0, 0), logicalSize), matrixFlags); renderer->setDevicePixelRatio(devicePixelRatio); } diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 457e362b80..da0e8bdc7c 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -368,7 +368,6 @@ public: QQuickWindow *window; // Will be 0 when window is not exposed QSize windowSize; - QSize windowPixelSize; float dpr = 1; int rhiSampleCount = 1; bool rhiDeviceLost = false; @@ -407,8 +406,6 @@ bool QSGRenderThread::event(QEvent *e) stopEventProcessing = true; window = se->window; windowSize = se->size; - if (window) - windowPixelSize = window->handle()->geometry().size(); dpr = se->dpr; pendingUpdate |= SyncRequest; @@ -836,14 +833,7 @@ void QSGRenderThread::syncAndRender(QImage *grabImage) } } if (current) { - const QSize surfaceSize = [this, cd]{ - if (rhi) - return cd->swapchain->currentPixelSize(); - if (windowPixelSize.isValid()) - return windowPixelSize; - return QSize(); - }(); - d->renderSceneGraph(windowSize, surfaceSize); + d->renderSceneGraph(windowSize, rhi ? cd->swapchain->currentPixelSize() : QSize()); if (profileFrames) renderTime = threadTimer.nsecsElapsed(); -- cgit v1.2.3