diff options
Diffstat (limited to 'tests')
163 files changed, 2268 insertions, 291 deletions
diff --git a/tests/auto/core/qqmlsettings/CMakeLists.txt b/tests/auto/core/qqmlsettings/CMakeLists.txt index 0d596a31dc..07606afc24 100644 --- a/tests/auto/core/qqmlsettings/CMakeLists.txt +++ b/tests/auto/core/qqmlsettings/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qqmlsettings LANGUAGES C CXX ASM) + project(tst_qqmlsettings LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/core/qqmlstandardpaths/CMakeLists.txt b/tests/auto/core/qqmlstandardpaths/CMakeLists.txt index 6078c10755..de30007643 100644 --- a/tests/auto/core/qqmlstandardpaths/CMakeLists.txt +++ b/tests/auto/core/qqmlstandardpaths/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qqmlstandardpaths LANGUAGES C CXX ASM) + project(tst_qqmlstandardpaths LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/core/qqmlsysteminformation/CMakeLists.txt b/tests/auto/core/qqmlsysteminformation/CMakeLists.txt index c69564634e..45c21fecd2 100644 --- a/tests/auto/core/qqmlsysteminformation/CMakeLists.txt +++ b/tests/auto/core/qqmlsysteminformation/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qqmlsysteminformation LANGUAGES C CXX ASM) + project(tst_qqmlsysteminformation LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index a3dc327cc2..aec22d32a5 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -282,6 +282,7 @@ private slots: void jsonStringifyHugeArray(); void tostringRecursionCheck(); + void arrayJoinRecursionCheck(); void arrayIncludesWithLargeArray(); void printCircularArray(); void typedArraySet(); @@ -321,6 +322,8 @@ private slots: void multiMatchingRegularExpression(); + void evalInGlobalContext(); + public: Q_INVOKABLE QJSValue throwingCppMethod1(); Q_INVOKABLE void throwingCppMethod2(); @@ -5133,11 +5136,11 @@ void tst_QJSEngine::mathMinMax() QJSValue result = engine.evaluate("var a = .5; Math.min(1, 2, 3.5 + a, '5')"); QCOMPARE(result.toNumber(), 1.0); - QVERIFY(QV4::Value(QJSValuePrivate::asReturnedValue(&result)).isInteger()); + QVERIFY(QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&result)).isInteger()); result = engine.evaluate("var a = .5; Math.max('0', 1, 2, 3.5 + a)"); QCOMPARE(result.toNumber(), 4.0); - QVERIFY(QV4::Value(QJSValuePrivate::asReturnedValue(&result)).isInteger()); + QVERIFY(QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&result)).isInteger()); } void tst_QJSEngine::mathNegativeZero() @@ -5523,6 +5526,20 @@ void tst_QJSEngine::tostringRecursionCheck() } main(); )js"); + + QVERIFY(value.isError()); + QCOMPARE(value.toString(), QLatin1String("RangeError: Maximum call stack size exceeded.")); +} + +void tst_QJSEngine::arrayJoinRecursionCheck() +{ + QJSEngine engine; + auto value = engine.evaluate(R"js( + a=[0,1]; + a[0]=a; + a+0 + )js"); + QVERIFY(value.isError()); QCOMPARE(value.toString(), QLatin1String("RangeError: Maximum call stack size exceeded.")); } @@ -6435,6 +6452,14 @@ void tst_QJSEngine::multiMatchingRegularExpression() QCOMPARE(result2.toString(), "4F15 9D7A D402 55D9 4A5B 7EB9 AAAC D740 8C79 245D "_L1); } +void tst_QJSEngine::evalInGlobalContext() +{ + QJSEngine myEngine; + const QJSValue fun = myEngine.globalObject().property(QLatin1String("eval")); + const QJSValue ret = fun.call({ QLatin1String("99") }); + QCOMPARE(ret.toString(), QLatin1String("99")); +} + QTEST_MAIN(tst_QJSEngine) #include "tst_qjsengine.moc" diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp index e65c1a3259..0511dcbae8 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp @@ -2820,7 +2820,7 @@ void tst_QJSValue::deleteFromDifferentThread() std::unique_ptr<QThread> thread(QThread::create([&]() { QMutexLocker locker(&mutex); QJSValuePrivate::free(&jsval); - QJSValuePrivate::setValue(&jsval, QV4::Encode::undefined()); + QJSValuePrivate::setValue(&jsval, QV4::Value::fromReturnedValue(QV4::Encode::undefined())); QVERIFY(storage.firstPage != nullptr); condition.wakeOne(); })); diff --git a/tests/auto/qml/qml/tst_qml.cpp b/tests/auto/qml/qml/tst_qml.cpp index de884d8257..f80af89044 100644 --- a/tests/auto/qml/qml/tst_qml.cpp +++ b/tests/auto/qml/qml/tst_qml.cpp @@ -6,6 +6,8 @@ #include <QtCore/qprocess.h> #include <QtQuickTestUtils/private/qmlutils_p.h> +#include <QTemporaryFile> + class tst_qml : public QQmlDataTest { Q_OBJECT @@ -15,6 +17,7 @@ public: private slots: void initTestCase() override; void nonWindow(); + void extraPositionalArguments(); private: QString qmlPath; @@ -42,6 +45,38 @@ void tst_qml::nonWindow() QCOMPARE(qml.exitCode(), 0); // Should not exit with code 2 } +void tst_qml::extraPositionalArguments() +{ + QProcess qml; + QStringList args; + + QTemporaryFile f; + QVERIFY(f.open()); + QVERIFY(f.write(R"(import QtQml + +QtObject { + Component.onCompleted: { + let s = "" + for (let i = 2; i < Qt.application.arguments.length; ++i) + s += Qt.application.arguments[i].substring(1) + console.log(s) + Qt.quit() + } +} +)")); + f.flush(); + + args << f.fileName(); + args << "--"; + for (char c = 'a'; c <= 'z'; ++c) + args << u'-' + QString(c); + + qml.start(qmlPath, args); + QVERIFY(qml.waitForFinished()); + QVERIFY(qml.exitStatus() == QProcess::NormalExit && qml.exitCode() == 0); + QVERIFY(qml.readAllStandardError().contains("abcdefghijklmnopqrstuvwxyz")); +} + QTEST_MAIN(tst_qml) #include <tst_qml.moc> diff --git a/tests/auto/qml/qmlcachegen/data/crashes/buggyFixSuggestion.qml b/tests/auto/qml/qmlcachegen/data/crashes/buggyFixSuggestion.qml new file mode 100644 index 0000000000..f435d2ec4a --- /dev/null +++ b/tests/auto/qml/qmlcachegen/data/crashes/buggyFixSuggestion.qml @@ -0,0 +1,25 @@ +import QtQuick + +Item { + id: root + + Item { + id: inner + + Tumbler { + id: year + + delegate: Rectangle { + required property var modelData + } + } + + Tumbler { + id: month + + delegate: Rectangle { + required property var modelData + } + } + } +} diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index be219273a8..bd95946036 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -67,6 +67,9 @@ private slots: void scriptStringCachegenInteraction(); void saveableUnitPointer(); + + void crash_data(); + void crash(); }; // A wrapper around QQmlComponent to ensure the temporary reference counts @@ -115,6 +118,36 @@ static bool generateCache(const QString &qmlFileName, QByteArray *capturedStderr return proc.exitCode() == 0; } +static bool generateCpp(const QString &qmlFileName, QByteArray *capturedStderr = nullptr) +{ +#if defined(QTEST_CROSS_COMPILED) + QTest::qFail("You cannot call qmlcachegen on the target.", __FILE__, __LINE__); + return false; +#endif + QProcess proc; + if (capturedStderr == nullptr) + proc.setProcessChannelMode(QProcess::ForwardedChannels); + proc.setProgram(QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath) + + QLatin1String("/qmlcachegen")); + QTemporaryDir outputDir; + const QString outputFile = outputDir.filePath("output.cpp"_L1); + proc.setArguments(QStringList{ "--resource-path"_L1, "qrc:/qt/qml/Crashes/testFile.qml"_L1, + "-o"_L1, outputFile, qmlFileName }); + proc.start(); + if (!proc.waitForFinished()) + return false; + + if (capturedStderr) + *capturedStderr = proc.readAllStandardError(); + + if (!QFile::exists(outputFile)) + return false; + + if (proc.exitStatus() != QProcess::NormalExit) + return false; + return proc.exitCode() == 0; +} + tst_qmlcachegen::tst_qmlcachegen() : QQmlDataTest(QT_QMLTEST_DATADIR) { @@ -235,7 +268,8 @@ void tst_qmlcachegen::translationExpressionSupport() "}"); - QVERIFY(generateCache(testFilePath)); + QByteArray errors; + QVERIFY2(generateCache(testFilePath, &errors), errors.constData()); const QString cacheFilePath = testFilePath + QLatin1Char('c'); QVERIFY(QFile::exists(cacheFilePath)); @@ -837,6 +871,27 @@ void tst_qmlcachegen::saveableUnitPointer() QCOMPARE(unit.flags, flags); } +void tst_qmlcachegen::crash_data() +{ + QTest::addColumn<QString>("fileName"); + + QTest::addRow("buggyFixSuggestion") << u"buggyFixSuggestion.qml"_s; +} + +void tst_qmlcachegen::crash() +{ +#if defined(QTEST_CROSS_COMPILED) + QSKIP("Cannot call qmlcachegen on cross-compiled target."); +#endif + + QFETCH(QString, fileName); + const QString filePath = testFile("crashes/" + fileName); + + QFile file(filePath); + QVERIFY(file.exists()); + QVERIFY(generateCpp(filePath)); +} + const QQmlScriptString &ScriptStringProps::undef() const { return m_undef; diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index d80783078f..c78acadd58 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -37,6 +37,7 @@ set(qml_files BadType.qml BaseMember.qml BindingExpression.qml + Categorizer.qml Cycle1.qml Cycle2.qml Cycle3.qml @@ -161,6 +162,7 @@ set(qml_files listlength.qml math.qml mathOperations.qml + mergeSideEffects.qml methods.qml modulePrefix.qml moveRegVoid.qml diff --git a/tests/auto/qml/qmlcppcodegen/data/Categorizer.qml b/tests/auto/qml/qmlcppcodegen/data/Categorizer.qml new file mode 100644 index 0000000000..83117f5d01 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/Categorizer.qml @@ -0,0 +1,60 @@ +pragma Strict +import QtQml + +QtObject { + id: root + + enum Parameters { + Length = 32, + Iterations = 2, + + Category0 = 0xf0f, + Category1 = 0xf0f0, + Category2 = 0xf0f0f, + Maximum = 0xf0f0f0, + Mask = 0xabcdef + } + + function randomNumber() : int { + return (Math.random() * Categorizer.Maximum); + } + + property list<double> numbers: { + // Can't StoreElement on non-list-properties in 6.5. + // To keep the pragma Strict, slightly adjust the original code here. + return [ + randomNumber(), randomNumber(), randomNumber(), randomNumber(), + randomNumber(), randomNumber(), randomNumber(), randomNumber(), + randomNumber(), randomNumber(), randomNumber(), randomNumber(), + randomNumber(), randomNumber(), randomNumber(), randomNumber(), + randomNumber(), randomNumber(), randomNumber(), randomNumber(), + randomNumber(), randomNumber(), randomNumber(), randomNumber(), + randomNumber(), randomNumber(), randomNumber(), randomNumber(), + randomNumber(), randomNumber(), randomNumber(), randomNumber(), + ]; + } + + function sum() : list<double> { + var numbers = root.numbers; + + var cat1Sum = 0; + var cat2Sum = 0; + var cat3Sum = 0; + var huge = 0; + for (var i = 0; i < Categorizer.Iterations; ++i) { + for (var j = 0; j < Categorizer.Length; ++j) { + var num = numbers[j] & Categorizer.Mask; + if (num < Categorizer.Category0) + cat1Sum += num; + else if (num < Categorizer.Category1) + cat2Sum += num; + else if (num < Categorizer.Category2) + cat3Sum += num; + else + huge += num; + } + } + + return [cat1Sum, cat2Sum, cat3Sum, huge]; + } +} diff --git a/tests/auto/qml/qmlcppcodegen/data/mergeSideEffects.qml b/tests/auto/qml/qmlcppcodegen/data/mergeSideEffects.qml new file mode 100644 index 0000000000..d4a8fec42e --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/mergeSideEffects.qml @@ -0,0 +1,20 @@ +import QtQml + +QtObject { + property bool no: false + property list<int> a: [1] + property list<int> b: [2] + + property int c: { + let numbers = a; + a = [3]; // create side effect affecting "numbers" + + if (no) { + // Force two branches to be merged on "numbers" + numbers = b + } + + // Side effect is still in effect + return numbers[0]; + } +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index dae83e2c86..07d1d99f00 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -36,6 +36,7 @@ private slots: void signalHandler(); void idAccess(); void globals(); + void mergeSideEffects(); void multiLookup(); void enums(); void funcWithParams(); @@ -196,6 +197,7 @@ private slots: void equalityTestsWithNullOrUndefined(); void basicBlocksWithBackJump(); void listOfInvisible(); + void writeAndReturnTempArray(); }; void tst_QmlCppCodegen::initTestCase() @@ -3110,6 +3112,16 @@ void tst_QmlCppCodegen::inaccessibleProperty() QCOMPARE(o->property("c").toInt(), 5); } +void tst_QmlCppCodegen::mergeSideEffects() +{ + QQmlEngine engine; + QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/mergeSideEffects.qml"_s)); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + QCOMPARE(o->property("c").toInt(), 3); +} + void tst_QmlCppCodegen::typePropagationLoop() { QQmlEngine engine; @@ -3772,6 +3784,42 @@ void tst_QmlCppCodegen::basicBlocksWithBackJump() QVERIFY(!expectingMessage); } +void tst_QmlCppCodegen::writeAndReturnTempArray() +{ + QQmlEngine engine; + QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Categorizer.qml"_s)); + + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + + const QVariant numbers = object->property("numbers"); + QCOMPARE(numbers.metaType(), QMetaType::fromType<QList<double>>()); + const QList<double> numbersContent = numbers.value<QList<double>>(); + QCOMPARE(numbersContent.length(), 32); + for (double number: std::as_const(numbersContent)) + QVERIFY(number >= 0 && number < double(0xf0f0f0)); + + QList<double> expected { 0, 0, 0, 0}; + for (int i = 0; i < 2; ++i) { + for (double number : std::as_const(numbersContent)) { + const int num = QJSNumberCoercion::toInteger((number)) & 0xabcdef; + if (num < 0xf0f) + expected[0] += num; + else if (num < 0xf0f0) + expected[1] += num; + else if (num < 0xf0f0f) + expected[2] += num; + else + expected[3] += num; + } + } + + QList<double> sum; + QMetaObject::invokeMethod(object.data(), "sum", Q_RETURN_ARG(QList<double>, sum)); + QCOMPARE(sum, expected); +} + QTEST_MAIN(tst_QmlCppCodegen) #include "tst_qmlcppcodegen.moc" diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp index 9633d5dd1c..9475ef409e 100644 --- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp +++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp @@ -357,7 +357,7 @@ void tst_qmldiskcache::regenerateAfterChange() QCOMPARE(quint32(obj->nBindings), quint32(2)); QCOMPARE(obj->bindingTable()->type(), QV4::CompiledData::Binding::Type_Number); - const QV4::Value value(testUnit->constants()[obj->bindingTable()->value.constantValueIndex]); + const auto value = QV4::Value::fromReturnedValue(testUnit->constants()[obj->bindingTable()->value.constantValueIndex]); QCOMPARE(value.doubleValue(), double(42)); QCOMPARE(quint32(testUnit->functionTableSize), quint32(1)); @@ -1353,7 +1353,7 @@ void tst_qmldiskcache::inlineComponentDoesNotCauseConstantInvalidation() testCompiler.reset(); QVERIFY(testCompiler.writeTestFile(code)); - QVERIFY(testCompiler.loadTestFile()); + QVERIFY2(testCompiler.loadTestFile(), qPrintable(testCompiler.lastErrorString)); const quintptr data1 = testCompiler.unitData(); QVERIFY(data1 != 0); diff --git a/tests/auto/qml/qmllint/data/InlineComponentSearchInfiniteLoop_Main.qml b/tests/auto/qml/qmllint/data/InlineComponentSearchInfiniteLoop_Main.qml new file mode 100644 index 0000000000..ee82e0c96b --- /dev/null +++ b/tests/auto/qml/qmllint/data/InlineComponentSearchInfiniteLoop_Main.qml @@ -0,0 +1,6 @@ +import QtQuick +import Other + +Item { + InlineComponentSearchInfiniteLoop_Other.a {} +} diff --git a/tests/auto/qml/qmllint/data/InlineComponentSearchInfiniteLoop_Other.qml b/tests/auto/qml/qmllint/data/InlineComponentSearchInfiniteLoop_Other.qml new file mode 100644 index 0000000000..724639b75d --- /dev/null +++ b/tests/auto/qml/qmllint/data/InlineComponentSearchInfiniteLoop_Other.qml @@ -0,0 +1,8 @@ +import QtQuick + +Item { + id: root + PropertyChanges { + root.whatever: 1 + } +} diff --git a/tests/auto/qml/qmllint/data/locationUnqualifiedLookupAssign.qml b/tests/auto/qml/qmllint/data/locationUnqualifiedLookupAssign.qml new file mode 100644 index 0000000000..b770a71a44 --- /dev/null +++ b/tests/auto/qml/qmllint/data/locationUnqualifiedLookupAssign.qml @@ -0,0 +1,7 @@ +import QtQml + +QtObject { + function f() { + console.log(a = 1) + } +} diff --git a/tests/auto/qml/qmllint/data/requiredPropertyInGroupedPropertyScope.qml b/tests/auto/qml/qmllint/data/requiredPropertyInGroupedPropertyScope.qml new file mode 100644 index 0000000000..ba8d37cb10 --- /dev/null +++ b/tests/auto/qml/qmllint/data/requiredPropertyInGroupedPropertyScope.qml @@ -0,0 +1,10 @@ +import QtQuick + +Item { + id: root + required property int i + + PropertyChanges { + root.width: 100 + } +} diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 3bb3853d6a..882b97be83 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -513,7 +513,7 @@ void TestQmllint::dirtyQmlCode_data() 3, 1 } } }; QTest::newRow("invalidAliasTarget1") << QStringLiteral("invalidAliasTarget.qml") << Result { { Message { - QStringLiteral("Invalid alias expression – an initalizer is needed."), + QStringLiteral("Invalid alias expression - an initalizer is needed."), 6, 18 } } }; QTest::newRow("invalidAliasTarget2") << QStringLiteral("invalidAliasTarget.qml") << Result { { Message { @@ -1109,6 +1109,13 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)", QTest::newRow("missingRequiredOnObjectDefinitionBinding") << QStringLiteral("missingRequiredPropertyOnObjectDefinitionBinding.qml") << Result{ { { uR"(Component is missing required property i from here)"_s, 4, 26 } } }; + QTest::newRow("locationUnqualifiedLookupAssign") + << QStringLiteral("locationUnqualifiedLookupAssign.qml") + << Result{ { Message{ QStringLiteral("Unqualified access"), 5, 21 } } }; + QTest::newRow("inlineComponentSearchInfiniteLoop") + << QStringLiteral("InlineComponentSearchInfiniteLoop_Main.qml") + << Result{ { { "InlineComponentSearchInfiniteLoop_Other.a was not found. " + "Did you add all import paths?"_L1, 5, 5 } } }; } void TestQmllint::dirtyQmlCode() @@ -1246,7 +1253,8 @@ void TestQmllint::cleanQmlCode_data() QTest::newRow("QQmlEasingEnums::Type") << QStringLiteral("animationEasing.qml"); QTest::newRow("ValidLiterals") << QStringLiteral("validLiterals.qml"); QTest::newRow("GoodModulePrefix") << QStringLiteral("goodModulePrefix.qml"); - QTest::newRow("required property in Component") << QStringLiteral("requiredPropertyInComponent.qml"); + QTest::newRow("required_property_in_Component") << QStringLiteral("requiredPropertyInComponent.qml"); + QTest::newRow("requiredPropertyInGroupedPropertyScope") << QStringLiteral("requiredPropertyInGroupedPropertyScope.qml"); QTest::newRow("bytearray") << QStringLiteral("bytearray.qml"); QTest::newRow("initReadonly") << QStringLiteral("initReadonly.qml"); QTest::newRow("connectionNoParent") << QStringLiteral("connectionNoParent.qml"); // QTBUG-97600 @@ -1305,9 +1313,6 @@ void TestQmllint::cleanQmlCode_data() void TestQmllint::cleanQmlCode() { QFETCH(QString, filename); - - QJsonArray warnings; - runTest(filename, Result::clean()); } @@ -1365,8 +1370,6 @@ void TestQmllint::compilerWarnings() QFETCH(Result, result); QFETCH(bool, enableCompilerWarnings); - QJsonArray warnings; - auto categories = QQmlJSLogger::defaultCategories(); auto category = std::find(categories.begin(), categories.end(), qmlCompiler); diff --git a/tests/auto/qml/qmltc/tst_qmltc.cpp b/tests/auto/qml/qmltc/tst_qmltc.cpp index f477956060..e00cfa58c0 100644 --- a/tests/auto/qml/qmltc/tst_qmltc.cpp +++ b/tests/auto/qml/qmltc/tst_qmltc.cpp @@ -96,6 +96,8 @@ #include <QtTest/qsignalspy.h> +#include <QtGui/qquaternion.h> + #include <QtCore/private/qobject_p.h> #include <QtTest/private/qemulationdetector_p.h> #include <QtCore/qtranslator.h> diff --git a/tests/auto/qml/qqmlbinding/data/bindingInDeadContext.qml b/tests/auto/qml/qqmlbinding/data/bindingInDeadContext.qml new file mode 100644 index 0000000000..3e86a1a1fd --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/bindingInDeadContext.qml @@ -0,0 +1,18 @@ +import QtQml + +QtObject { + id: outer + objectName: "outer" + + property Component c: QtObject { + id: inner1 + objectName: inner2.objectName + "a" + } + + property QtObject inner1: c.createObject() + + property QtObject inner2: QtObject { + id: inner2 + objectName: "a" + } +} diff --git a/tests/auto/qml/qqmlbinding/data/deleteStashedObject.qml b/tests/auto/qml/qqmlbinding/data/deleteStashedObject.qml new file mode 100644 index 0000000000..fb95305791 --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/deleteStashedObject.qml @@ -0,0 +1,51 @@ +pragma ComponentBehavior: Bound +import QtQml + +QtObject { + id: root + + property Component c: Component { + QtObject { + Component.onDestruction: { + console.log("dead") + timer.start() + } + } + } + + property QtObject stashed: c.createObject() + property QtObject replacement: QtObject {} + + onStashedChanged: { + if (stashed) { + page = stashed + console.log("alive") + binding.when = true + } + } + + property QtObject page + + property Binding binding: Binding { + id: binding + target: root + property: "page" + when: false + value: root.replacement + } + + property Timer timer: Timer { + id: timer + interval: 10 + onTriggered: { + console.log("before") + binding.when = false + console.log("after") + } + } + + Component.onCompleted: { + console.log("destroy") + stashed.destroy(); + } +} diff --git a/tests/auto/qml/qqmlbinding/data/multiValueTypeBinding.qml b/tests/auto/qml/qqmlbinding/data/multiValueTypeBinding.qml new file mode 100644 index 0000000000..7f1ba9b886 --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/multiValueTypeBinding.qml @@ -0,0 +1,16 @@ +import QtQml + +QtObject { + property alias labelY: label.rect.y + property alias labelWidth: label.rect.width + + labelY: { return 24 } + labelWidth: 9 + + property QtObject label: QtObject { + id: label + + property rect rect + rect.x: { return 12 } + } +} diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp index 9503ec80c5..a7bb2fa722 100644 --- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp +++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp @@ -32,6 +32,7 @@ private slots: void disabledOnReadonlyProperty(); void delayed(); void bindingOverwriting(); + void bindingInDeadContext(); void bindToQmlComponent(); void bindingDoesNoWeirdConversion(); void bindNaNToInt(); @@ -41,6 +42,8 @@ private slots: void whenEvaluatedEarlyEnough(); void propertiesAttachedToBindingItself(); void toggleEnableProperlyRemembersValues(); + void deleteStashedObject(); + void multiValueTypeBinding(); private: QQmlEngine engine; @@ -472,6 +475,40 @@ void tst_qqmlbinding::bindingOverwriting() QLoggingCategory::setFilterRules(QString()); } +void tst_qqmlbinding::bindingInDeadContext() +{ + // We manually control the deletion order of the objects here. + // This is what some of our views also do. One way to prevent + // the engine from deleting objects is to parent them to the + // application. + + QScopedPointer<QObject> o; + QScopedPointer<QObject> inner1; + { + QScopedPointer<QObject> inner2; + + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("bindingInDeadContext.qml")); + + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + o.reset(c.create()); + QVERIFY(!o.isNull()); + o->setParent(QCoreApplication::instance()); + + inner1.reset(o->property("inner1").value<QObject *>()); + QVERIFY(inner1); + inner1->setParent(QCoreApplication::instance()); + + inner2.reset(o->property("inner2").value<QObject *>()); + QVERIFY(inner2); + inner2->setParent(QCoreApplication::instance()); + } + + // The objectName binding did not get re-evaluated when inner2 died + // because the engine was gone already. + QCOMPARE(inner1->objectName(), "aa"); +} + void tst_qqmlbinding::bindToQmlComponent() { QQmlEngine engine; @@ -654,6 +691,41 @@ void tst_qqmlbinding::toggleEnableProperlyRemembersValues() } } +void tst_qqmlbinding::deleteStashedObject() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("deleteStashedObject.qml")); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + + QTest::ignoreMessage(QtDebugMsg, "alive"); + QTest::ignoreMessage(QtDebugMsg, "destroy"); + QScopedPointer<QObject> object(component.create()); + QVERIFY(object); + QVERIFY(object->property("page").value<QObject *>() != nullptr); + + QTest::ignoreMessage(QtDebugMsg, "dead"); + QTest::ignoreMessage(QtDebugMsg, "before"); + QTest::ignoreMessage(QtDebugMsg, "after"); + QTRY_VERIFY(object->property("page").value<QObject *>() == nullptr); +} + +void tst_qqmlbinding::multiValueTypeBinding() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("multiValueTypeBinding.qml")); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QScopedPointer<QObject> object(component.create()); + QVERIFY(object); + + QObject *label = object->property("label").value<QObject *>(); + QVERIFY(label); + + QRectF rect = label->property("rect").toRectF(); + QCOMPARE(rect.x(), 12); + QCOMPARE(rect.y(), 24); + QCOMPARE(rect.width(), 9); +} + QTEST_MAIN(tst_qqmlbinding) #include "tst_qqmlbinding.moc" diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index 59703d5c36..20eaa36970 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -22,6 +22,9 @@ #include <qcolor.h> #include <qsignalspy.h> #include "lifecyclewatcher.h" + +#include <QtGui/qquaternion.h> + #include <algorithm> using namespace Qt::StringLiterals; diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp index a14f980766..d4ac14bfb4 100644 --- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp +++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp @@ -852,13 +852,13 @@ void tst_qqmlcontext::contextLeak() QVERIFY(ddata); QQmlRefPointer<QQmlContextData> context = ddata->context; QVERIFY(context); - QVERIFY(!context->importedScripts().isNullOrUndefined()); - QCOMPARE(int(context->importedScripts().valueRef()->as<QV4::Object>()->getLength()), 1); + QV4::Scope scope(engine.handle()); + QV4::PersistentValue scopedScripts = context->importedScripts(); + QVERIFY(!scopedScripts.isNullOrUndefined()); + QCOMPARE(int(scopedScripts.as<QV4::Object>()->getLength()), 1); - QV4::Scope scope(ddata->jsWrapper.engine()); QV4::ScopedValue scriptContextWrapper(scope); - scriptContextWrapper = context->importedScripts().valueRef() - ->as<QV4::Object>()->get(uint(0)); + scriptContextWrapper = scopedScripts.as<QV4::Object>()->get(uint(0)); scriptContext = scriptContextWrapper->as<QV4::QQmlContextWrapper>()->getContext(); } diff --git a/tests/auto/qml/qqmlecmascript/data/jittedJavaScriptExpressionDoesNotCrashOnExceptionBeingThrown.qml b/tests/auto/qml/qqmlecmascript/data/jittedJavaScriptExpressionDoesNotCrashOnExceptionBeingThrown.qml new file mode 100644 index 0000000000..7249113fd0 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/jittedJavaScriptExpressionDoesNotCrashOnExceptionBeingThrown.qml @@ -0,0 +1,40 @@ +import QtQml +import QtQuick + +Window { + id: root + + Item { + id: child + + Timer { + id: timer + + property int fuel: 10 + + interval: 1 + repeat: true + running: true + onTriggered: { + if (--fuel == 0) + running = false; + parent.state = parent.state === "inactive" ? "active" : "inactive"; + } + } + + states: [ + State { + name: "active" + StateChangeScript { + script: root.active = true; + } + }, + State { + name: "inactive" + StateChangeScript { + script: root.active = false; + } + } + ] + } +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 1612848dfb..dcde9a62f1 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -26,6 +26,7 @@ #include <private/qv4objectiterator_p.h> #include <private/qqmlabstractbinding_p.h> #include <private/qqmlvaluetypeproxybinding_p.h> +#include <private/qqmltimer_p.h> #include <QtCore/private/qproperty_p.h> #include <QtQuick/qquickwindow.h> #include <QtQuick/private/qquickitem_p.h> @@ -200,6 +201,7 @@ private slots: void assignSequenceTypes(); void sequenceSort_data(); void sequenceSort(); + void sequenceConversionViaSequentialIterableFallback(); void dateParse(); void utcDate(); void negativeYear(); @@ -425,6 +427,8 @@ private slots: void methodCallOnDerivedSingleton(); + void jittedJavaScriptExpressionDoesNotCrashOnExceptionBeingThrown(); + private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); static void verifyContextLifetime(const QQmlRefPointer<QQmlContextData> &ctxt); @@ -8251,6 +8255,19 @@ void tst_qqmlecmascript::sequenceSort() QVERIFY(q.toBool()); } +void tst_qqmlecmascript::sequenceConversionViaSequentialIterableFallback() +{ + QQmlEngine engine; + QSet<QString> mySet { {"test"}, {"test2"}, {"test3"} }; + QJSManagedValue jsManagedVal(QVariant::fromValue(mySet), &engine); + QVERIFY(jsManagedVal.isArray()); + // we can't rely on any order in the set + QSet<QString> result; + for (int i = 0, end = jsManagedVal.property("length").toInt(); i != end; ++i) + result.insert(jsManagedVal.property(i).toString()); + QCOMPARE(result, mySet); +} + void tst_qqmlecmascript::dateParse() { QQmlEngine engine; @@ -10504,6 +10521,24 @@ void tst_qqmlecmascript::methodCallOnDerivedSingleton() QVERIFY(singleton->m_okay); } +void tst_qqmlecmascript::jittedJavaScriptExpressionDoesNotCrashOnExceptionBeingThrown() +{ + QQmlEngine engine; + + engine.handle()->memoryManager->aggressiveGC = true; + + QQmlComponent c(&engine, testFileUrl("jittedJavaScriptExpressionDoesNotCrashOnExceptionBeingThrown.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY2(o, qPrintable(c.errorString())); + + QQmlContext *context = qmlContext(o.data()); + auto timer = qobject_cast<QQmlTimer*>(context->objectForName("timer")); + QVERIFY(timer); + + QTRY_VERIFY(!timer->isRunning()); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index bf68de0d2f..0dfb78fef1 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -1581,8 +1581,10 @@ void tst_qqmlengine::stringToColor() const QMetaType metaType(QMetaType::QColor); QVariant color(metaType); + QV4::Scope scope(engine.handle()); + QV4::ScopedValue colorString(scope, engine.handle()->newString(QStringLiteral("#abcdef"))); QVERIFY(QV4::ExecutionEngine::metaTypeFromJS( - engine.handle()->newString(QStringLiteral("#abcdef"))->asReturnedValue(), + colorString, metaType, color.data())); QVERIFY(color.isValid()); QCOMPARE(color.metaType(), metaType); diff --git a/tests/auto/qml/qqmllanguage/data/WithInline.qml b/tests/auto/qml/qqmllanguage/data/WithInline.qml new file mode 100644 index 0000000000..3620574c8f --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/WithInline.qml @@ -0,0 +1,8 @@ +import QtQml + +QtObject { + objectName: "outer" + component Inline: QtObject { + objectName: "inner" + } +} diff --git a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.11.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.11.errors.txt new file mode 100644 index 0000000000..e072be7a4e --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.11.errors.txt @@ -0,0 +1 @@ +8:5:Cannot assign to non-existent property "root" diff --git a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.11.qml b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.11.qml new file mode 100644 index 0000000000..edb32af51c --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.11.qml @@ -0,0 +1,9 @@ +import QtQml +QtObject { + id: root + component C : QtObject { + property int i + } + property C c: C {} + root.c.i: 4 +} diff --git a/tests/auto/qml/qqmllanguage/data/urlWithFragment.qml b/tests/auto/qml/qqmllanguage/data/urlWithFragment.qml new file mode 100644 index 0000000000..f68c816c10 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/urlWithFragment.qml @@ -0,0 +1,6 @@ +import QtQuick + +Loader { + source: 'WithInline.qml#0' + objectName: item?.objectName ?? "none" +} diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index df89dcff39..e793bae848 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -447,6 +447,8 @@ private slots: void aliasOfBindableValueTypeProperty(); + void urlWithFragment(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -633,6 +635,7 @@ void tst_qqmllanguage::errors_data() QTest::newRow("invalidGroupedProperty.8") << "invalidGroupedProperty.8.qml" << "invalidGroupedProperty.8.errors.txt" << false; QTest::newRow("invalidGroupedProperty.9") << "invalidGroupedProperty.9.qml" << "invalidGroupedProperty.9.errors.txt" << false; QTest::newRow("invalidGroupedProperty.10") << "invalidGroupedProperty.10.qml" << "invalidGroupedProperty.10.errors.txt" << false; + QTest::newRow("invalidGroupedProperty.11") << "invalidGroupedProperty.11.qml" << "invalidGroupedProperty.11.errors.txt" << false; QTest::newRow("importNamespaceConflict") << "importNamespaceConflict.qml" << "importNamespaceConflict.errors.txt" << false; QTest::newRow("importVersionMissing (builtin)") << "importVersionMissingBuiltIn.qml" << "importVersionMissingBuiltIn.errors.txt" << false; @@ -8393,6 +8396,17 @@ void tst_qqmllanguage::aliasOfBindableValueTypeProperty() QCOMPARE(bindable.metaType(), QMetaType::fromType<QPointF>()); } +void tst_qqmllanguage::urlWithFragment() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("urlWithFragment.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + QCOMPARE(o->objectName(), "outer"); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/qml/qqmllistmodel/data/valuesOfInnerList.qml b/tests/auto/qml/qqmllistmodel/data/valuesOfInnerList.qml new file mode 100644 index 0000000000..9d28111da4 --- /dev/null +++ b/tests/auto/qml/qqmllistmodel/data/valuesOfInnerList.qml @@ -0,0 +1,17 @@ +import QtQml 2.15 + +ListModel { + id: listModel + + Component.onCompleted: { + const rawObj = { innerList: [1, 2, 3] } + listModel.append(rawObj) + const convertedObj = listModel.get(0) + + console.log(rawObj.innerList) + console.log(Object.values(rawObj.innerList)) + + console.log(convertedObj.innerList) + console.log(Object.values(convertedObj.innerList)) + } +} diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp index 4010be56b3..ba0e83238b 100644 --- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp +++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp @@ -120,6 +120,7 @@ private slots: void enumsInListElement(); void protectQObjectFromGC(); void deadModelData(); + void valuesOfInnerList(); }; bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object) @@ -2003,6 +2004,24 @@ void tst_qqmllistmodel::deadModelData() } } +void tst_qqmllistmodel::valuesOfInnerList() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("valuesOfInnerList.qml")); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + + QTest::ignoreMessage(QtDebugMsg, "[1,2,3]"); + QTest::ignoreMessage(QtDebugMsg, "[1,2,3]"); + QTest::ignoreMessage(QtDebugMsg, QRegularExpression("QQmlListModel\\(0x[0-9a-f]*\\)")); + + // Array with values of all the properties of QQmlListModel, one of which is "agent" + QTest::ignoreMessage( + QtDebugMsg, QRegularExpression("\\[.*QQmlListModelWorkerAgent\\(0x[0-9a-f]*\\).*\\]")); + + QScopedPointer<QObject> o(component.create()); + QVERIFY(!o.isNull()); +} + QTEST_MAIN(tst_qqmllistmodel) #include "tst_qqmllistmodel.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.errors.txt b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.errors.txt deleted file mode 100644 index de75f47c03..0000000000 --- a/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.errors.txt +++ /dev/null @@ -1 +0,0 @@ -1:1:module "org.qtproject.AutoTestQmlNestedPluginType.Nested" is not installed diff --git a/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.qml b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.qml index 35fff29a69..5148653a53 100644 --- a/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.qml +++ b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.qml @@ -1,5 +1,8 @@ import org.qtproject.AutoTestQmlNestedPluginType.Nested 1.0 import org.qtproject.AutoTestQmlNestedPluginType 1.0 +import QtQml MyNestedPluginType { + property Conflict conflict: Conflict {} + Component.onCompleted: console.log(conflict.value) } diff --git a/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp index 4400c11996..47fba6049f 100644 --- a/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp @@ -40,11 +40,13 @@ public: { Q_ASSERT(QLatin1String(uri) == "org.qtproject.AutoTestQmlNestedPluginType"); qmlRegisterType<MyPluginType>(uri, 1, 0, "MyPluginType"); + qmlRegisterType<MyPluginType>(uri, 1, 0, "Conflict"); QString nestedUri(uri); nestedUri += QLatin1String(".Nested"); qmlRegisterType<MyNestedPluginType>(nestedUri.toLatin1().constData(), 1, 0, "MyNestedPluginType"); + qmlRegisterType<MyNestedPluginType>(nestedUri.toLatin1().constData(), 1, 0, "Conflict"); } }; diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp index a4901aebad..ff12a150a5 100644 --- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp @@ -453,18 +453,22 @@ void tst_qqmlmoduleplugin::importsNested_data() { QTest::addColumn<QString>("file"); QTest::addColumn<QString>("errorFile"); - - // Note: no other test case should import the plugin used for this test, or the - // wrong order test will pass spuriously - QTest::newRow("wrongOrder") << "importsNested.1.qml" << "importsNested.1.errors.txt"; - QTest::newRow("missingImport") << "importsNested.3.qml" << "importsNested.3.errors.txt"; - QTest::newRow("invalidVersion") << "importsNested.4.qml" << "importsNested.4.errors.txt"; - QTest::newRow("correctOrder") << "importsNested.2.qml" << QString(); + QTest::addColumn<bool>("expectGreeting"); + + // NB: The order is wrong in the sense that it tries to load the "Nested" URI first, which + // is not visible in the file system. However, in the process of loading the non-nested + // URI it can discover the types for the nested one and insert them in the right place. + // This used to be an error but doesn't have to be. + QTest::newRow("wrongOrder") << "importsNested.1.qml" << QString() << true; + QTest::newRow("missingImport") << "importsNested.3.qml" << "importsNested.3.errors.txt" << false; + QTest::newRow("invalidVersion") << "importsNested.4.qml" << "importsNested.4.errors.txt" << false; + QTest::newRow("correctOrder") << "importsNested.2.qml" << QString() << false; } void tst_qqmlmoduleplugin::importsNested() { QFETCH(QString, file); QFETCH(QString, errorFile); + QFETCH(bool, expectGreeting); // Note: because imports are cached between test case data rows (and the plugins remain loaded), // these tests should really be run in new instances of the app... @@ -481,6 +485,10 @@ void tst_qqmlmoduleplugin::importsNested() QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlNestedPluginType' does not contain a module identifier directive - it cannot be protected from external registrations."); QQmlComponent component(&engine, testFile(file)); + + if (expectGreeting) + QTest::ignoreMessage(QtDebugMsg, "Hello"); + QObject *obj = component.create(); if (errorFile.isEmpty()) { diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index 396f876fe4..b64b39defe 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -1346,6 +1346,18 @@ void tst_qqmlproperty::read() QCOMPARE(QQmlProperty::read(object.data(), "Foo.MyContainer.foo", qmlContext(object.data())), QVariant(10)); } + + // value type list + { + QQmlComponent component(&engine); + component.setData("import QtQml\nQtObject { property list<string> strings: [`a`, `b`] }", QUrl()); + QScopedPointer<QObject> object(component.create()); + QVERIFY(object != nullptr); + + QQmlProperty p(object.data(), "strings", qmlContext(object.data())); + QStringList expected {"a", "b"}; + QCOMPARE(p.read(), expected); + } } void tst_qqmlproperty::write() diff --git a/tests/auto/qml/qqmlsettings/data/coexistence/Core.qml b/tests/auto/qml/qqmlsettings/data/coexistence/Core.qml new file mode 100644 index 0000000000..ae786263fb --- /dev/null +++ b/tests/auto/qml/qqmlsettings/data/coexistence/Core.qml @@ -0,0 +1,5 @@ +import QtQuick +import QtCore + +Item {} + diff --git a/tests/auto/qml/qqmlsettings/data/coexistence/Labs.qml b/tests/auto/qml/qqmlsettings/data/coexistence/Labs.qml new file mode 100644 index 0000000000..54cdfcdfb9 --- /dev/null +++ b/tests/auto/qml/qqmlsettings/data/coexistence/Labs.qml @@ -0,0 +1,8 @@ +import QtQuick +import Qt.labs.settings as L + +Item { + id: root + Core {} + property L.Settings settings: L.Settings {} +} diff --git a/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp b/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp index 88d8c58e2c..00757fec07 100644 --- a/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp +++ b/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp @@ -32,6 +32,7 @@ private slots: void siblings(); void initial(); void noApplicationIdentifiersSet(); + void coexistence(); }; // ### Replace keyValueMap("foo", "bar") with QVariantMap({{"foo", "bar"}}) @@ -492,6 +493,18 @@ void tst_QQmlSettings::noApplicationIdentifiersSet() QVERIFY(!settings.value("success").toBool()); } + +void tst_QQmlSettings::coexistence() +{ + QQmlEngine engine; + QTest::ignoreMessage(QtWarningMsg, QRegularExpression( + ".*QML Settings: The Settings type from Qt.labs.settings is deprecated and will be removed in a future release. Please use the one from QtCore instead." + )); + QQmlComponent component(&engine, testFileUrl("coexistence/Labs.qml")); + QScopedPointer<QObject> root(component.create()); + QVERIFY(root.data()); +} + QTEST_MAIN(tst_QQmlSettings) #include "tst_qqmlsettings.moc" diff --git a/tests/auto/qml/qqmltablemodel/data/TestModel.qml b/tests/auto/qml/qqmltablemodel/data/TestModel.qml index a862af35d2..d90631fb38 100644 --- a/tests/auto/qml/qqmltablemodel/data/TestModel.qml +++ b/tests/auto/qml/qqmltablemodel/data/TestModel.qml @@ -3,8 +3,6 @@ import Qt.labs.qmlmodels 1.0 -import "TestUtils.js" as TestUtils - TableModel { id: testModel objectName: "testModel" diff --git a/tests/auto/qml/qqmltablemodel/data/TestUtils.js b/tests/auto/qml/qqmltablemodel/data/TestUtils.js deleted file mode 100644 index 83ac1b80a8..0000000000 --- a/tests/auto/qml/qqmltablemodel/data/TestUtils.js +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -function testModelRoleDataProvider(index, role, cellData) { - switch (role) { - case "display": - switch (index.column) { - case 0: - return cellData.name - case 1: - return cellData.age - } - break - case "name": - return cellData.name - case "age": - return cellData.age - } - return cellData -} diff --git a/tests/auto/qml/qqmltypeloader/data/qobjectSingletonUser.qml b/tests/auto/qml/qqmltypeloader/data/qobjectSingletonUser.qml new file mode 100644 index 0000000000..d8b380928c --- /dev/null +++ b/tests/auto/qml/qqmltypeloader/data/qobjectSingletonUser.qml @@ -0,0 +1,7 @@ +import QtQml +import Qt.example.qobjectSingleton 1.0 + +QtObject { + property int someValue: MyApi.someProperty + property int doneSomething: MyApi.doSomething() +} diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp index cb4610d01b..8ef73de70c 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp @@ -4,6 +4,7 @@ #include <QtTest/QtTest> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlfile.h> +#include <QtQml/qqmlapplicationengine.h> #include <QtQml/qqmlnetworkaccessmanagerfactory.h> #include <QtQuick/qquickview.h> #include <QtQuick/qquickitem.h> @@ -50,6 +51,7 @@ private slots: void signalHandlersAreCompatible(); void loadTypeOnShutdown(); void floodTypeLoaderEventQueue(); + void loadLocalTypesAfterRemoteFails(); private: void checkSingleton(const QString & dataDirectory); @@ -829,6 +831,65 @@ void tst_QQMLTypeLoader::floodTypeLoaderEventQueue() } } +class SingletonTypeExample : public QObject +{ + Q_OBJECT + Q_PROPERTY(int someProperty READ someProperty WRITE setSomeProperty NOTIFY somePropertyChanged) + +public: + explicit SingletonTypeExample(QObject* parent = nullptr) : QObject(parent) {} + + Q_INVOKABLE int doSomething() + { + setSomeProperty(5); + return m_someProperty; + } + + int someProperty() const { return m_someProperty; } + void setSomeProperty(int val) { + if (m_someProperty != val) { + m_someProperty = val; + emit somePropertyChanged(val); + } + } + +signals: + void somePropertyChanged(int newValue); + +private: + int m_someProperty = 0; +}; + +class HttpUrlInterceptor : public QQmlAbstractUrlInterceptor +{ +public: + QUrl intercept(const QUrl &path, DataType type) override + { + QUrl result = path; + if (path.scheme() == "http" && type == QmldirFile) + result.setFragment("qmldir"); + return result; + } +}; + +void tst_QQMLTypeLoader::loadLocalTypesAfterRemoteFails() +{ + std::unique_ptr<SingletonTypeExample> example = std::make_unique<SingletonTypeExample>(); + qmlRegisterSingletonInstance("Qt.example.qobjectSingleton", 1, 0, "MyApi", example.get()); + + HttpUrlInterceptor interceptor; + QQmlEngine engine; + engine.addUrlInterceptor(&interceptor); + engine.addImportPath(QString("http:/127.0.0.1/")); + + QQmlComponent component(&engine, testFileUrl("qobjectSingletonUser.qml")); + QTRY_VERIFY2(component.isReady(), qPrintable(component.errorString())); + + QScopedPointer<QObject> object(component.create()); + QCOMPARE(object->property("someValue").toInt(), 5); + QCOMPARE(object->property("doneSomething").toInt(), 5); +} + QTEST_MAIN(tst_QQMLTypeLoader) #include "tst_qqmltypeloader.moc" diff --git a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp index 930ac11fbe..ad475cf1a1 100644 --- a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp +++ b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp @@ -12,6 +12,8 @@ #include <QtQuickTestUtils/private/qmlutils_p.h> #include "testtypes.h" +#include <QtGui/qquaternion.h> + QT_BEGIN_NAMESPACE extern int qt_defaultDpi(void); QT_END_NAMESPACE diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp index 1f9dfb7fd4..cb157d1a8c 100644 --- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp +++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp @@ -14,6 +14,8 @@ #include <QtQuickTestUtils/private/qmlutils_p.h> #include "testtypes.h" +#include <QtGui/qquaternion.h> + QT_BEGIN_NAMESPACE extern int qt_defaultDpi(void); QT_END_NAMESPACE diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/BLACKLIST b/tests/auto/quick/pointerhandlers/mousearea_interop/BLACKLIST index 74d29b4ac3..cb290fe641 100644 --- a/tests/auto/quick/pointerhandlers/mousearea_interop/BLACKLIST +++ b/tests/auto/quick/pointerhandlers/mousearea_interop/BLACKLIST @@ -1,7 +1,3 @@ # QTBUG-95938 [dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch] opensuse-leap - -# QTBUG-95938 -[dragHandlerInSiblingStealingGrabFromMouseAreaViaMouse] -opensuse-leap diff --git a/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp b/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp index 556acbc828..6331a2d390 100644 --- a/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp +++ b/tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp @@ -43,6 +43,7 @@ void tst_MouseAreaInterop::createView(QScopedPointer<QQuickView> &window, const window.reset(new QQuickView); window->setSource(testFileUrl(fileName)); QTRY_COMPARE(window->status(), QQuickView::Ready); + window.data()->setFlag(Qt::FramelessWindowHint); QQuickViewTestUtils::centerOnScreen(window.data()); QQuickViewTestUtils::moveMouseAway(window.data()); @@ -58,6 +59,10 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaMouse createView(windowPtr, "dragTakeOverFromSibling.qml"); QQuickView * window = windowPtr.data(); + const QPoint pos = QGuiApplication::primaryScreen()->availableGeometry().topLeft(); + window->setFramePosition(pos); + QTRY_COMPARE(window->framePosition(), pos); + QPointer<QQuickPointerHandler> handler = window->rootObject()->findChild<QQuickPointerHandler*>(); QVERIFY(handler); QQuickMouseArea *ma = window->rootObject()->findChild<QQuickMouseArea*>(); @@ -108,6 +113,10 @@ void tst_MouseAreaInterop::dragHandlerInSiblingStealingGrabFromMouseAreaViaTouch QQuickView * window = windowPtr.data(); auto devPriv = QPointingDevicePrivate::get(touchDevice); + const QPoint pos = QGuiApplication::primaryScreen()->availableGeometry().topLeft(); + window->setFramePosition(pos); + QTRY_COMPARE(window->framePosition(), pos); + QPointer<QQuickPointerHandler> handler = window->rootObject()->findChild<QQuickPointerHandler*>(); QVERIFY(handler); QQuickMouseArea *ma = window->rootObject()->findChild<QQuickMouseArea*>(); diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp index b3b2259319..bff6ca9733 100644 --- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp @@ -394,14 +394,25 @@ void tst_HoverHandler::movingItemWithHoverHandler() QTRY_COMPARE(paddleHH->isHovered(), true); // TODO check the cursor shape after fixing QTBUG-53987 + const auto &deliveryTargets = + QQuickPointerHandlerPrivate::deviceDeliveryTargets(QPointingDevice::primaryPointingDevice()); + const auto targetsCount = deliveryTargets.size(); + qCDebug(lcPointerTests) << "deviceDeliveryTargets before paddle movement" << deliveryTargets; paddle->setX(100); QTRY_COMPARE(paddleHH->isHovered(), false); + // QQuickDeliveryAgentPrivate::deliverHoverEvent() clears the deviceDeliveryTargets list, + // and then each HoverHandler's QQuickPointerHandler::handlePointerEvent() adds itself again. + // As long as we visit the same handlers each time, the list should not grow. (QTBUG-135975) + qCDebug(lcPointerTests) << "deviceDeliveryTargets after paddle movement" << deliveryTargets; + QCOMPARE(deliveryTargets.size(), targetsCount); paddle->setX(p.x() - paddle->width() / 2); QTRY_COMPARE(paddleHH->isHovered(), true); + QCOMPARE(deliveryTargets.size(), targetsCount); paddle->setX(540); QTRY_COMPARE(paddleHH->isHovered(), false); + QCOMPARE(deliveryTargets.size(), targetsCount); } void tst_HoverHandler::margin() // QTBUG-85303 diff --git a/tests/auto/quick/qquickanimations/data/animationInstantiator.qml b/tests/auto/quick/qquickanimations/data/animationInstantiator.qml new file mode 100644 index 0000000000..48206073d0 --- /dev/null +++ b/tests/auto/quick/qquickanimations/data/animationInstantiator.qml @@ -0,0 +1,40 @@ +import QtQuick + +Item { + id: root + property int v: 0 + + Transition { + id: transition + NumberAnimation {} + } + + Instantiator { + id: instantiator + + delegate: NumberAnimation {} + + onObjectAdded: (index, object) => { + transition.animations.splice(index, 0, object) + } + + onObjectRemoved: (index, object) => { + // NB: This is a logic error. The indices of other entries change when we remove one + // from the middle, but Instantiator will still report the old indices. + // We still want to do this, in order ot exercise the code that nulls dangling + // pointers. + transition.animations.splice(index, 1) + } + } + + Timer { + interval: 2 + running: true + repeat: true + onTriggered: { + instantiator.model = (++v % 2) ? 0 : 10 + } + } +} + + diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp index ce5473c8a5..083efc9213 100644 --- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp +++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp @@ -102,6 +102,7 @@ private slots: void restartNestedAnimationGroupWhenDirty(); void targetsDeletedNotRemoved(); void alwaysRunToEndSetFalseRestartBug(); + void animationInstantiator(); }; #define QTIMED_COMPARE(lhs, rhs) do { \ @@ -2331,6 +2332,16 @@ void tst_qquickanimations::alwaysRunToEndSetFalseRestartBug() QCOMPARE(sequential.isRunning(), false); } +void tst_qquickanimations::animationInstantiator() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("animationInstantiator.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + QTRY_VERIFY(o->property("v").toInt() > 10); +} + QTEST_MAIN(tst_qquickanimations) #include "tst_qquickanimations.moc" diff --git a/tests/auto/quick/qquickapplication/BLACKLIST b/tests/auto/quick/qquickapplication/BLACKLIST deleted file mode 100644 index b8bc4363f1..0000000000 --- a/tests/auto/quick/qquickapplication/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[state] -opensuse-leap # QTBUG-122031 diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp index 0bac4baaea..aed74dce10 100644 --- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp +++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp @@ -165,7 +165,8 @@ void tst_qquickapplication::state() // Otherwise, the application can only be in two states, Active and Inactive. These are // triggered by window activation. window.show(); - window.requestActivate(); + if (QGuiApplication::platformName().toLower() != QLatin1String("xcb")) + window.requestActivate(); QVERIFY(QTest::qWaitForWindowActive(&window)); QCOMPARE(QGuiApplication::focusWindow(), &window); QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationActive); diff --git a/tests/auto/quick/qquicklistview/BLACKLIST b/tests/auto/quick/qquicklistview/BLACKLIST index a686534d20..e463fc0b45 100644 --- a/tests/auto/quick/qquicklistview/BLACKLIST +++ b/tests/auto/quick/qquicklistview/BLACKLIST @@ -1,6 +1,3 @@ -#QTBUG-53863 -[populateTransitions] -opensuse-42.1 # QTBUG-75202 [contentHeightWithDelayRemove] macos ci diff --git a/tests/auto/quick/qquickloader/data/invalidateContext.qml b/tests/auto/quick/qquickloader/data/invalidateContext.qml new file mode 100644 index 0000000000..b5a28f5d0f --- /dev/null +++ b/tests/auto/quick/qquickloader/data/invalidateContext.qml @@ -0,0 +1,28 @@ +import QtQuick + +Item { + Loader { + active: loaderActive + sourceComponent: comp + } + + Component { + id: comp + Column { + Repeater { + id: repeater + model: cppModel + + Component.onCompleted: console.log("Repeater constructed"); + Component.onDestruction: console.log("Repeater destroyed"); + + delegate: Text { + text: { + console.log("updating text"); + return display + rootData.getValue(); + } + } + } + } + } +} diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index 389f037166..afc49fe74d 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -117,6 +117,8 @@ private slots: void stackOverflow(); void stackOverflow2(); void boundComponent(); + + void invalidateContext(); }; Q_DECLARE_METATYPE(QList<QQmlError>) @@ -1585,6 +1587,60 @@ void tst_QQuickLoader::boundComponent() QCOMPARE(o->objectName(), QStringLiteral("loaded")); } +class CppModel : public QAbstractListModel +{ +public: + virtual int rowCount(const QModelIndex &) const override {return 1;} + virtual QVariant data(const QModelIndex &, int) const override { return "test"; } + + void reset () {beginResetModel(); endResetModel();} +}; + +class RootData : public QObject +{ + Q_OBJECT +public: + RootData() : object(std::make_unique<QObject>()) + { + object->setObjectName("objectName"); + } + + Q_INVOKABLE QString getValue() const { return object->objectName(); } + + void deleteObject() { object.reset(); } + +private: + std::unique_ptr<QObject> object; +}; + +void tst_QQuickLoader::invalidateContext() +{ + CppModel model; + RootData rootData; + + QQmlEngine engine; + QQmlContext *rootContext = engine.rootContext(); + rootContext->setContextProperty("cppModel", &model); + rootContext->setContextProperty("loaderActive", true); + rootContext->setContextProperty("rootData", &rootData); + + QQmlComponent component(&engine, testFileUrl("invalidateContext.qml"));\ + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + + QTest::ignoreMessage(QtDebugMsg, "Repeater constructed"); + QTest::ignoreMessage(QtDebugMsg, "updating text"); + QScopedPointer<QObject> o(component.create()); + + QTest::ignoreMessage(QtDebugMsg, "Repeater destroyed"); + rootContext->setContextProperty("loaderActive", false); + + // The object should never be used anymore, as loader is inactive + rootData.deleteObject(); + + // Should not trigger any re-evaluation (which would crash in getValue()) + model.reset(); +} + QTEST_MAIN(tst_QQuickLoader) #include "tst_qquickloader.moc" diff --git a/tests/auto/quick/qquickmultipointtoucharea/data/inFlickableWithScale.qml b/tests/auto/quick/qquickmultipointtoucharea/data/inFlickableWithScale.qml new file mode 100644 index 0000000000..9af4c36241 --- /dev/null +++ b/tests/auto/quick/qquickmultipointtoucharea/data/inFlickableWithScale.qml @@ -0,0 +1,27 @@ +import QtQuick + +Rectangle { + id: root + width: 240 + height: 320 + + property bool gestureStarted: false + + Flickable { + id: flick + anchors.fill: parent + anchors.margins: 50 + clip: true + contentWidth: width + contentHeight: height * 2 + + scale: 0.5 + + MultiPointTouchArea { + anchors.fill: parent + onGestureStarted: (gesture) => { + root.gestureStarted = true + } + } + } +} diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp index 81e57bfd12..6fe27ebe6f 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp +++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp @@ -40,6 +40,7 @@ private slots: void inFlickable(); void inFlickable2(); void inFlickableWithPressDelay(); + void inFlickableWithScale(); void inMouseArea(); void mouseAsTouchpoint(); void invisible(); @@ -860,6 +861,35 @@ void tst_QQuickMultiPointTouchArea::inFlickableWithPressDelay() // QTBUG-78818 QTRY_VERIFY(!flickable->isMoving()); } +// QTBUG-131886 +void tst_QQuickMultiPointTouchArea::inFlickableWithScale() +{ + const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl("inFlickableWithScale.qml"))); + + QQuickFlickable *flickable = window.rootObject()->findChild<QQuickFlickable*>(); + QVERIFY(flickable != nullptr); + QQuickMultiPointTouchArea *mpta = window.rootObject()->findChild<QQuickMultiPointTouchArea*>(); + QVERIFY(mpta != nullptr); + + QSignalSpy gestureStartedSpy(mpta, &QQuickMultiPointTouchArea::gestureStarted); + + // press and drag over dragThreshold emits gestureStarted even when scaled + QPoint p1(120, 160); // size is 240 x 320, press in the center + QTest::touchEvent(&window, device).press(0, p1); + QQuickTouchUtils::flush(&window); + + p1 += QPoint(0, dragThreshold); + QTest::touchEvent(&window, device).move(0, p1); + QQuickTouchUtils::flush(&window); + + QCOMPARE(gestureStartedSpy.size(), 1); + + QTest::touchEvent(&window, device).release(0, p1); + QQuickTouchUtils::flush(&window); +} + // QTBUG-31047 void tst_QQuickMultiPointTouchArea::inMouseArea() { diff --git a/tests/auto/quick/qquickshape/data/changeElementsImperatively.qml b/tests/auto/quick/qquickshape/data/changeElementsImperatively.qml new file mode 100644 index 0000000000..129be7222a --- /dev/null +++ b/tests/auto/quick/qquickshape/data/changeElementsImperatively.qml @@ -0,0 +1,21 @@ +import QtQuick +import QtQuick.Shapes + +Shape { + width: 640 + height: 480 + + Component.onCompleted: { + bottomPathLine.x = 20 + } + + ShapePath { + PathLine {} + PathLine { + id: bottomPathLine + } + PathArc {} + PathLine {} + PathArc {} + } +} diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp index a9e15939d3..c9e7af5ee7 100644 --- a/tests/auto/quick/qquickshape/tst_qquickshape.cpp +++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp @@ -62,6 +62,7 @@ private slots: void multilineDataTypes_data(); void multilineDataTypes(); void multilineStronglyTyped(); + void changeElementsImperatively(); private: QVector<QPolygonF> m_lowPolyLogo; @@ -674,6 +675,13 @@ void tst_QQuickShape::multilineStronglyTyped() } } +void tst_QQuickShape::changeElementsImperatively() +{ + QQuickView window; + // Shouldn't crash. + QVERIFY(QQuickTest::showView(window, testFileUrl("changeElementsImperatively.qml"))); +} + QTEST_MAIN(tst_QQuickShape) #include "tst_qquickshape.moc" diff --git a/tests/auto/quick/qquicktext/BLACKLIST b/tests/auto/quick/qquicktext/BLACKLIST index a4e9c44eab..3c64442e2b 100644 --- a/tests/auto/quick/qquicktext/BLACKLIST +++ b/tests/auto/quick/qquicktext/BLACKLIST @@ -1,5 +1,4 @@ -[fontSizeMode] -opensuse-42.1 + [contentSize] windows gcc msvc-2019 diff --git a/tests/auto/quick/qquicktextedit/data/readOnly.qml b/tests/auto/quick/qquicktextedit/data/readOnly.qml index 085adba5fb..4aea6a78ab 100644 --- a/tests/auto/quick/qquicktextedit/data/readOnly.qml +++ b/tests/auto/quick/qquicktextedit/data/readOnly.qml @@ -1,12 +1,38 @@ -import QtQuick 2.0 +import QtQuick Rectangle { property variant myInput: input width: 800; height: 600; color: "blue" - TextEdit { id: input; focus: true + property bool activateSelectAllShortcut: false + property bool activateCopyShortcut: false + property bool activatePageupShortcut: false + property bool acceptShortcutOverride: true + + Shortcut { + sequences: [StandardKey.SelectAll] + onActivated: { activateSelectAllShortcut = true } + } + + Shortcut { + sequences: [StandardKey.Copy] + onActivated: { activateCopyShortcut = true } + } + + Shortcut { + sequences: [StandardKey.MoveToPreviousPage] + onActivated: { activatePageupShortcut = true } + } + + TextEdit { + id: input + + focus: true readOnly: true text: "I am the very model of a modern major general.\n" + Keys.onShortcutOverride: event => { + event.accepted = acceptShortcutOverride + } } } diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index 399627c4f1..31945b3776 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -3256,11 +3256,53 @@ void tst_qquicktextedit::readOnly() QString initial = edit->text(); for (int k=Qt::Key_0; k<=Qt::Key_Z; k++) simulateKey(&window, k); + simulateKey(&window, Qt::Key_Return); simulateKey(&window, Qt::Key_Space); simulateKey(&window, Qt::Key_Escape); QCOMPARE(edit->text(), initial); + // Read-only shall support Selection and Copy by default + QCOMPARE(window.rootObject()->property("acceptShortcutOverride").toBool(), true); + simulateKeys(&window, QKeySequence(QKeySequence::SelectAll)); + QCOMPARE(window.rootObject()->property("activateSelectAllShortcut").toBool(), false); + QCOMPARE(edit->cursorPosition(), edit->text().size()); + QCOMPARE(edit->selectedText(), edit->text()); +#ifndef QT_NO_CLIPBOARD + // Copy the selected text into the clipboard + if (PlatformQuirks::isClipboardAvailable()) { + if (auto *clipBoard = QGuiApplication::clipboard()) { + simulateKeys(&window, QKeySequence(QKeySequence::Copy)); + QCOMPARE(window.rootObject()->property("activateCopyShortcut").toBool(), false); + QCOMPARE(clipBoard->text(), edit->text()); + clipBoard->clear(); + } + } +#endif + edit->setCursorPosition(0); + + window.rootObject()->setProperty("acceptShortcutOverride", false); + QCOMPARE(window.rootObject()->property("acceptShortcutOverride").toBool(), false); + simulateKeys(&window, QKeySequence(QKeySequence::SelectAll)); + QCOMPARE(window.rootObject()->property("activateSelectAllShortcut").toBool(), true); + QCOMPARE(edit->cursorPosition(), 0); + QCOMPARE(edit->selectedText(), ""); +#ifndef QT_NO_CLIPBOARD + // Copy the selected text into the clipboard + if (PlatformQuirks::isClipboardAvailable()) { + if (auto *clipBoard = QGuiApplication::clipboard()) { + simulateKeys(&window, QKeySequence(QKeySequence::Copy)); + QCOMPARE(window.rootObject()->property("activateCopyShortcut").toBool(), true); + QCOMPARE(clipBoard->text(), ""); + } + } +#endif + simulateKeys(&window, QKeySequence(QKeySequence::MoveToPreviousPage)); + QCOMPARE(window.rootObject()->property("activatePageupShortcut").toBool(), true); + + window.rootObject()->setProperty("acceptShortcutOverride", true); + QCOMPARE(window.rootObject()->property("acceptShortcutOverride").toBool(), true); + edit->setCursorPosition(3); edit->setReadOnly(false); QCOMPARE(edit->isReadOnly(), false); diff --git a/tests/auto/quick/qquicktreeview/data/editdelegate.qml b/tests/auto/quick/qquicktreeview/data/editdelegate.qml new file mode 100644 index 0000000000..f8f908807f --- /dev/null +++ b/tests/auto/quick/qquicktreeview/data/editdelegate.qml @@ -0,0 +1,91 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Window + +Item { + width: 800 + height: 600 + + property alias treeView: treeView + property alias textInput: textInput + + TextInput { + id: textInput + width: 100 + height: 10 + } + + TreeView { + id: treeView + anchors.fill: parent + clip: true + + property Item editItem: null + property var editIndex + + selectionModel: ItemSelectionModel {} + + delegate: Rectangle { + id: root + implicitWidth: 100 + implicitHeight: 50 + clip: true + color: current || selected ? "lightgreen" : "white" + + property alias text: label.text + + readonly property real indent: 20 + readonly property real padding: 5 + + // Assigned to by TreeView: + required property TreeView treeView + required property bool isTreeNode + required property bool expanded + required property int hasChildren + required property int depth + required property bool current + required property bool selected + required property bool editing + + Text { + id: indicator + visible: root.isTreeNode && root.hasChildren + x: padding + (root.depth * root.indent) + text: root.expanded ? "▼" : "▶" + } + + Text { + id: label + x: padding + (root.isTreeNode ? (root.depth + 1) * root.indent : 0) + width: root.width - root.padding - x + clip: true + text: model.display + } + + TableView.editDelegate: TextInput { + id: editRoot + anchors.fill: parent + text: display + horizontalAlignment: TextInput.AlignHCenter + verticalAlignment: TextInput.AlignVCenter + activeFocusOnTab: true + + required property bool editing + + Component.onCompleted: { + treeView.editItem = editRoot + treeView.editIndex = treeView.index(row, column) + selectAll() + } + + Component.onDestruction: { + treeView.editItem = null + treeView.editIndex = treeView.index(-1, -1) + } + } + } + } + +} diff --git a/tests/auto/quick/qquicktreeview/testmodel.cpp b/tests/auto/quick/qquicktreeview/testmodel.cpp index a6a756ba68..231df4c5b0 100644 --- a/tests/auto/quick/qquicktreeview/testmodel.cpp +++ b/tests/auto/quick/qquicktreeview/testmodel.cpp @@ -129,7 +129,6 @@ bool TestModel::insertRows(int position, int rows, const QModelIndex &parent) return true; } - void insertColumnsRecursive(TreeItem *item, int row, int pos, int cols) { for (int col = 0; col < cols; col++) @@ -158,3 +157,11 @@ bool TestModel::insertColumns(int position, int cols, const QModelIndex &parent) endInsertColumns(); return true; } + +Qt::ItemFlags TestModel::flags(const QModelIndex &index) const +{ + if (m_editableIndices.contains(index)) + return Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable; + + return Qt::ItemIsSelectable|Qt::ItemIsEnabled; +} diff --git a/tests/auto/quick/qquicktreeview/testmodel.h b/tests/auto/quick/qquicktreeview/testmodel.h index 182211e050..b7d10fb468 100644 --- a/tests/auto/quick/qquicktreeview/testmodel.h +++ b/tests/auto/quick/qquicktreeview/testmodel.h @@ -36,11 +36,14 @@ public: bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex &index) const override; + Qt::ItemFlags flags(const QModelIndex &index) const override; int maxDepth() { return 4; } bool insertRows(int position, int rows, const QModelIndex &parent) override; bool insertColumns(int position, int cols, const QModelIndex &parent) override; + QList<QModelIndex> m_editableIndices; + private: QScopedPointer<TreeItem> m_rootItem; int m_columnCount = 5; diff --git a/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp b/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp index e16797c7fa..e0ddc3d731 100644 --- a/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp +++ b/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp @@ -7,6 +7,7 @@ #include <QtQuick/qquickview.h> #include <QtQuick/private/qquicktreeview_p.h> #include <QtQuick/private/qquicktreeview_p_p.h> +#include <QtQuick/private/qquicktextinput_p.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcontext.h> @@ -88,6 +89,10 @@ private slots: void sortTreeModel(); void sortTreeModelDynamic_data(); void sortTreeModelDynamic(); + void editUsingEditTriggers_data(); + void editUsingEditTriggers(); + void editOnNonEditableCell_data(); + void editOnNonEditableCell(); }; tst_qquicktreeview::tst_qquicktreeview() @@ -1204,6 +1209,335 @@ void tst_qquicktreeview::sortTreeModelDynamic() } } +void tst_qquicktreeview::editUsingEditTriggers_data() +{ + QTest::addColumn<QQuickTreeView::EditTriggers>("editTriggers"); + QTest::addColumn<bool>("interactive"); + + QTest::newRow("NoEditTriggers") << QQuickTreeView::EditTriggers(QQuickTreeView::NoEditTriggers); + QTest::newRow("SingleTapped") << QQuickTreeView::EditTriggers(QQuickTreeView::SingleTapped); + QTest::newRow("DoubleTapped") << QQuickTreeView::EditTriggers(QQuickTreeView::DoubleTapped); + QTest::newRow("SelectedTapped") << QQuickTreeView::EditTriggers(QQuickTreeView::SelectedTapped); + QTest::newRow("EditKeyPressed") << QQuickTreeView::EditTriggers(QQuickTreeView::EditKeyPressed); + QTest::newRow("AnyKeyPressed") << QQuickTreeView::EditTriggers(QQuickTreeView::AnyKeyPressed); + QTest::newRow("DoubleTapped | EditKeyPressed") + << QQuickTreeView::EditTriggers(QQuickTreeView::DoubleTapped | QQuickTreeView::EditKeyPressed); + QTest::newRow("SingleTapped | AnyKeyPressed") + << QQuickTreeView::EditTriggers(QQuickTreeView::SingleTapped | QQuickTreeView::AnyKeyPressed); +} + +void tst_qquicktreeview::editUsingEditTriggers() +{ + // Check that you can start to edit in treeView + // using the available edit triggers. + QFETCH(QQuickTreeView::EditTriggers, editTriggers); + LOAD_TREEVIEW("editdelegate.qml"); + + TestModel testModel; + treeView->setModel(QVariant::fromValue(&testModel)); + treeView->forceActiveFocus(); + treeView->expand(0); + + WAIT_UNTIL_POLISHED; + + QCOMPARE(treeView->editTriggers(), QQuickTreeView::EditKeyPressed); + treeView->setEditTriggers(editTriggers); + + const char kEditItem[] = "editItem"; + const char kEditIndex[] = "editIndex"; + + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + + const QPoint cell1(0, 0); + const QPoint cell2(1, 1); + const QModelIndex index1 = treeView->modelIndex(cell1); + const QModelIndex index2 = treeView->modelIndex(cell2); + const auto item1 = treeView->itemAtCell(cell1); + const auto item2 = treeView->itemAtCell(cell2); + QVERIFY(item1); + QVERIFY(item2); + + testModel.m_editableIndices = { index1, index2 }; + + QQuickWindow *window = treeView->window(); + + const QPoint localPos = QPoint(item1->width() - 1, item1->height() - 1); + const QPoint localPosOutside = QPoint(treeView->contentWidth() + 10, treeView->contentHeight() + 10); + const QPoint tapPos1 = window->contentItem()->mapFromItem(item1, localPos).toPoint(); + const QPoint tapPos2 = window->contentItem()->mapFromItem(item2, localPos).toPoint(); + const QPoint tapOutsideContentItem = window->contentItem()->mapFromItem(item2, localPosOutside).toPoint(); + + if (editTriggers & QQuickTreeView::SingleTapped) { + // edit cell 1 + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos1); + QCOMPARE(treeView->selectionModel()->currentIndex(), index1); + const auto editItem1 = treeView->property(kEditItem).value<QQuickItem *>(); + QVERIFY(editItem1); + QVERIFY(editItem1->hasActiveFocus()); + QCOMPARE(treeView->property(kEditIndex).value<QModelIndex>(), index1); + + // edit cell 2 (without closing the previous edit session first) + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos2); + QCOMPARE(treeView->selectionModel()->currentIndex(), index2); + const auto editItem2 = treeView->property(kEditItem).value<QQuickItem *>(); + QVERIFY(editItem2); + QVERIFY(editItem2->hasActiveFocus()); + QCOMPARE(treeView->property(kEditIndex).value<QModelIndex>(), index2); + + // single tap outside content item should close the editor + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapOutsideContentItem); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + QCOMPARE(treeView->selectionModel()->currentIndex(), index2); + } + + if (editTriggers & QQuickTreeView::DoubleTapped) { + // edit cell 1 + QTest::mouseDClick(window, Qt::LeftButton, Qt::NoModifier, tapPos1); + QCOMPARE(treeView->selectionModel()->currentIndex(), index1); + const auto editItem1 = treeView->property(kEditItem).value<QQuickItem *>(); + QVERIFY(editItem1); + QVERIFY(editItem1->hasActiveFocus()); + QCOMPARE(treeView->property(kEditIndex).value<QModelIndex>(), index1); + + // edit cell 2 (without closing the previous edit session first) + QTest::mouseDClick(window, Qt::LeftButton, Qt::NoModifier, tapPos2); + QCOMPARE(treeView->selectionModel()->currentIndex(), index2); + const auto editItem2 = treeView->property(kEditItem).value<QQuickItem *>(); + QVERIFY(editItem2); + QVERIFY(editItem2->hasActiveFocus()); + QCOMPARE(treeView->property(kEditIndex).value<QModelIndex>(), index2); + + // single tap outside the edit item should close the editor + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos1); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + QCOMPARE(treeView->selectionModel()->currentIndex(), index1); + + if (!(editTriggers & QQuickTreeView::SingleTapped)) { + // single tap on a cell should not open the editor + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos1); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + } + + // single tap outside content item should make sure editing ends + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapOutsideContentItem); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + } + + if (editTriggers & QQuickTreeView::SelectedTapped) { + // select cell first, then tap on it + treeView->selectionModel()->setCurrentIndex(index1, QItemSelectionModel::Select); + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos1); + QCOMPARE(treeView->selectionModel()->currentIndex(), index1); + const auto editItem1 = treeView->property(kEditItem).value<QQuickItem *>(); + QVERIFY(editItem1); + QVERIFY(editItem1->hasActiveFocus()); + QCOMPARE(treeView->property(kEditIndex).value<QModelIndex>(), index1); + + // tap on a non-selected cell. This should close the editor, and move + // the current index, but not begin to edit the cell. + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos2); + QCOMPARE(treeView->selectionModel()->currentIndex(), index2); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + + // tap on a non-selected cell while no editor is active + treeView->selectionModel()->setCurrentIndex(index1, QItemSelectionModel::NoUpdate); + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos2); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + QCOMPARE(treeView->selectionModel()->currentIndex(), index2); + + // tap on the current cell. This alone should not start an edit (unless it's also selected) + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos1); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + } + + if (editTriggers & QQuickTreeView::EditKeyPressed) { + treeView->selectionModel()->setCurrentIndex(index1, QItemSelectionModel::NoUpdate); + QTest::keyClick(window, Qt::Key_Return); + const auto editItem1 = treeView->property(kEditItem).value<QQuickItem *>(); + QVERIFY(editItem1); + QVERIFY(editItem1->hasActiveFocus()); + QCOMPARE(treeView->property(kEditIndex).value<QModelIndex>(), index1); + + // Pressing escape should close the editor + QTest::keyClick(window, Qt::Key_Escape); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + QCOMPARE(treeView->selectionModel()->currentIndex(), index1); + + // Pressing Enter to open the editor again + QTest::keyClick(window, Qt::Key_Enter); + const auto editItem2 = treeView->property(kEditItem).value<QQuickItem *>(); + QVERIFY(editItem2); + QVERIFY(editItem2->hasActiveFocus()); + QCOMPARE(treeView->property(kEditIndex).value<QModelIndex>(), index1); + + // single tap outside the edit item should close the editor + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos2); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + } + + if (editTriggers & QQuickTreeView::AnyKeyPressed) { + // Pressing key x should start to edit. And in case of AnyKeyPressed, we + // also replay the key event to the focus object. + treeView->selectionModel()->setCurrentIndex(index1, QItemSelectionModel::NoUpdate); + QTest::keyClick(window, Qt::Key_X); + QCOMPARE(treeView->selectionModel()->currentIndex(), index1); + QCOMPARE(treeView->property(kEditIndex).value<QModelIndex>(), index1); + auto textInput1 = treeView->property(kEditItem).value<QQuickTextInput *>(); + QVERIFY(textInput1); + QVERIFY(textInput1->hasActiveFocus()); + QCOMPARE(textInput1->text(), "x"); + + // Pressing escape should close the editor + QTest::keyClick(window, Qt::Key_Escape); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + QCOMPARE(treeView->selectionModel()->currentIndex(), index1); + + // Pressing a modifier key alone should not open the editor + QTest::keyClick(window, Qt::Key_Shift); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QTest::keyClick(window, Qt::Key_Control); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QTest::keyClick(window, Qt::Key_Alt); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QTest::keyClick(window, Qt::Key_Meta); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + + // Pressing enter should also start to edit. But this is a + // special case, we don't replay enter into the focus object. + treeView->selectionModel()->setCurrentIndex(index1, QItemSelectionModel::NoUpdate); + QTest::keyClick(window, Qt::Key_Enter); + QCOMPARE(treeView->selectionModel()->currentIndex(), index1); + QCOMPARE(treeView->property(kEditIndex).value<QModelIndex>(), index1); + auto textInput2 = treeView->property(kEditItem).value<QQuickTextInput *>(); + QVERIFY(textInput2); + QVERIFY(textInput2->hasActiveFocus()); + + if (!(editTriggers & QQuickTreeView::SingleTapped)) { + // single tap outside the edit item should close the editor + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos2); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + } + + // single tap outside content item should make sure editing ends + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapOutsideContentItem); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + } + + if (editTriggers == QQuickTreeView::NoEditTriggers) { + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos1); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + QTest::mouseDClick(window, Qt::LeftButton, Qt::NoModifier, tapPos1); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + treeView->selectionModel()->setCurrentIndex(index1, QItemSelectionModel::NoUpdate); + QTest::keyClick(window, Qt::Key_Return); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + QTest::keyClick(window, Qt::Key_Enter); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + QTest::keyClick(window, Qt::Key_X); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + } +} + +void tst_qquicktreeview::editOnNonEditableCell_data() +{ + QTest::addColumn<QQuickTreeView::EditTriggers>("editTriggers"); + + QTest::newRow("SingleTapped") << QQuickTreeView::EditTriggers(QQuickTreeView::SingleTapped); + QTest::newRow("DoubleTapped") << QQuickTreeView::EditTriggers(QQuickTreeView::DoubleTapped); + QTest::newRow("SelectedTapped") << QQuickTreeView::EditTriggers(QQuickTreeView::SelectedTapped); + QTest::newRow("EditKeyPressed") << QQuickTreeView::EditTriggers(QQuickTreeView::EditKeyPressed); + QTest::newRow("AnyKeyPressed") << QQuickTreeView::EditTriggers(QQuickTreeView::EditKeyPressed); +} + +void tst_qquicktreeview::editOnNonEditableCell() +{ + // Check that the user cannot edit a non-editable cell from the edit triggers. + // Note: we don't want TreeView to print out warnings in this case, since + // the user is not doing anything wrong. We only want to print out warnings if + // the application is calling edit() explicitly on a cell that cannot be edited + // (separate test below). + QFETCH(QQuickTreeView::EditTriggers, editTriggers); + LOAD_TREEVIEW("editdelegate.qml"); + + TestModel testModel; + treeView->setModel(QVariant::fromValue(&testModel)); + treeView->forceActiveFocus(); + treeView->expand(0); + + WAIT_UNTIL_POLISHED; + + const char kEditItem[] = "editItem"; + const char kEditIndex[] = "editIndex"; + + const QPoint cell(1, 1); + const QModelIndex index1 = treeView->modelIndex(cell); + const auto item = treeView->itemAtCell(cell); + QVERIFY(item); + + QQuickWindow *window = treeView->window(); + + const QPoint localPos = QPoint(item->width() - 1, item->height() - 1); + const QPoint tapPos = window->contentItem()->mapFromItem(item, localPos).toPoint(); + + if (editTriggers & QQuickTreeView::SingleTapped) { + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + } + + if (editTriggers & QQuickTreeView::DoubleTapped) { + QTest::mouseDClick(window, Qt::LeftButton, Qt::NoModifier, tapPos); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + } + + if (editTriggers & QQuickTreeView::SelectedTapped) { + // select cell first, then tap on it + treeView->selectionModel()->setCurrentIndex(index1, QItemSelectionModel::NoUpdate); + QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, tapPos); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + } + + if (editTriggers & QQuickTreeView::EditKeyPressed) { + treeView->selectionModel()->setCurrentIndex(index1, QItemSelectionModel::NoUpdate); + QTest::keyClick(window, Qt::Key_Enter); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + QTest::keyClick(window, Qt::Key_Return); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + } + + if (editTriggers & QQuickTreeView::AnyKeyPressed) { + treeView->selectionModel()->setCurrentIndex(index1, QItemSelectionModel::NoUpdate); + QTest::keyClick(window, Qt::Key_X); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + QTest::keyClick(window, Qt::Key_Enter); + QVERIFY(!treeView->property(kEditItem).value<QQuickItem *>()); + QVERIFY(!treeView->property(kEditIndex).value<QModelIndex>().isValid()); + } +} + QTEST_MAIN(tst_qquicktreeview) #include "tst_qquicktreeview.moc" diff --git a/tests/auto/quickcontrols/accessibility/data/accessibleName/button.qml b/tests/auto/quickcontrols/accessibility/data/accessibleName/button.qml new file mode 100644 index 0000000000..c985e72b78 --- /dev/null +++ b/tests/auto/quickcontrols/accessibility/data/accessibleName/button.qml @@ -0,0 +1,10 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls + +Button { + text: "Hello world" + id: button +} diff --git a/tests/auto/quickcontrols/accessibility/data/accessibleName/button2.qml b/tests/auto/quickcontrols/accessibility/data/accessibleName/button2.qml new file mode 100644 index 0000000000..5f1ceabea2 --- /dev/null +++ b/tests/auto/quickcontrols/accessibility/data/accessibleName/button2.qml @@ -0,0 +1,10 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls + +Button { + text: "Th&is && that" + id: button +} diff --git a/tests/auto/quickcontrols/accessibility/data/accessibleName/button3.qml b/tests/auto/quickcontrols/accessibility/data/accessibleName/button3.qml new file mode 100644 index 0000000000..d41d2ee1eb --- /dev/null +++ b/tests/auto/quickcontrols/accessibility/data/accessibleName/button3.qml @@ -0,0 +1,11 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls + +Button { + text: "Hello world" + Accessible.name: "Explicitly set accessible name" + id: button +} diff --git a/tests/auto/quickcontrols/accessibility/tst_accessibility.cpp b/tests/auto/quickcontrols/accessibility/tst_accessibility.cpp index 40ee98691d..3aa6b63d06 100644 --- a/tests/auto/quickcontrols/accessibility/tst_accessibility.cpp +++ b/tests/auto/quickcontrols/accessibility/tst_accessibility.cpp @@ -31,6 +31,8 @@ private slots: void override(); void ordering(); + + void accessibleName(); private: QQmlEngine engine; }; @@ -274,6 +276,45 @@ void tst_accessibility::ordering() #endif } +void tst_accessibility::accessibleName() +{ +#if QT_CONFIG(accessibility) + if (!QAccessible::isActive()) { + QPlatformAccessibility *accessibility = platformAccessibility(); + if (!accessibility) + QSKIP("No QPlatformAccessibility available."); + accessibility->setActive(true); + } + + QQmlComponent component(&engine); + + // verify that accessible name matches the button text if none was set explicitly + component.loadUrl(testFileUrl("accessibleName/button.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY2(!object.isNull(), qPrintable(component.errorString())); + QAccessibleInterface *buttonAcc = QAccessible::queryAccessibleInterface(object.get()); + QVERIFY(buttonAcc); + QCOMPARE(buttonAcc->text(QAccessible::Name), "Hello world"); + + // verify that ampersand ('&') for mnemonic and to escape literal ampersand in button + // text are not contained in accessible name + component.loadUrl(testFileUrl("accessibleName/button2.qml")); + QScopedPointer<QObject> object2(component.create()); + QVERIFY2(!object.isNull(), qPrintable(component.errorString())); + QAccessibleInterface *button2Acc = QAccessible::queryAccessibleInterface(object2.get()); + QVERIFY(button2Acc); + QCOMPARE(button2Acc->text(QAccessible::Name), "This & that"); + + // verify that explicitly set accesible name is used + component.loadUrl(testFileUrl("accessibleName/button3.qml")); + QScopedPointer<QObject> object3(component.create()); + QVERIFY2(!object.isNull(), qPrintable(component.errorString())); + QAccessibleInterface *button3Acc = QAccessible::queryAccessibleInterface(object3.get()); + QVERIFY(button3Acc); + QCOMPARE(button3Acc->text(QAccessible::Name), "Explicitly set accessible name"); +#endif +} + QTEST_MAIN(tst_accessibility) #include "tst_accessibility.moc" diff --git a/tests/auto/quickcontrols/controls/basic/CMakeLists.txt b/tests/auto/quickcontrols/controls/basic/CMakeLists.txt index 74bbf2954e..bf61a4fc7d 100644 --- a/tests/auto/quickcontrols/controls/basic/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/basic/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_basic LANGUAGES C CXX ASM) + project(tst_basic LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/fusion/CMakeLists.txt b/tests/auto/quickcontrols/controls/fusion/CMakeLists.txt index e3d38e1cf3..95c6d9f540 100644 --- a/tests/auto/quickcontrols/controls/fusion/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/fusion/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_fusion LANGUAGES C CXX ASM) + project(tst_fusion LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/imagine/CMakeLists.txt b/tests/auto/quickcontrols/controls/imagine/CMakeLists.txt index c296a5b1a4..67560bf225 100644 --- a/tests/auto/quickcontrols/controls/imagine/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/imagine/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_imagine LANGUAGES C CXX ASM) + project(tst_imagine LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/ios/CMakeLists.txt b/tests/auto/quickcontrols/controls/ios/CMakeLists.txt index 4e0cb72e68..55c16a2735 100644 --- a/tests/auto/quickcontrols/controls/ios/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/ios/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_ios LANGUAGES C CXX ASM) + project(tst_ios LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/macos/CMakeLists.txt b/tests/auto/quickcontrols/controls/macos/CMakeLists.txt index 3202601316..f33ef26c78 100644 --- a/tests/auto/quickcontrols/controls/macos/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/macos/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_macos LANGUAGES C CXX ASM) + project(tst_macos LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/material/CMakeLists.txt b/tests/auto/quickcontrols/controls/material/CMakeLists.txt index 2f14b5253d..f59a1a09e8 100644 --- a/tests/auto/quickcontrols/controls/material/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/material/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_material LANGUAGES C CXX ASM) + project(tst_material LANGUAGES C CXX) find_package(Qt6 REQUIRED COMPONENTS ShaderTools) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/universal/CMakeLists.txt b/tests/auto/quickcontrols/controls/universal/CMakeLists.txt index f39975ab15..2ac791ccb9 100644 --- a/tests/auto/quickcontrols/controls/universal/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/universal/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_universal LANGUAGES C CXX ASM) + project(tst_universal LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/controls/windows/CMakeLists.txt b/tests/auto/quickcontrols/controls/windows/CMakeLists.txt index 1d6ab1fc57..f1c1a4d1d7 100644 --- a/tests/auto/quickcontrols/controls/windows/CMakeLists.txt +++ b/tests/auto/quickcontrols/controls/windows/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_windows LANGUAGES C CXX ASM) + project(tst_windows LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/cursor/CMakeLists.txt b/tests/auto/quickcontrols/cursor/CMakeLists.txt index 6d0fa9eed6..85f39ba90a 100644 --- a/tests/auto/quickcontrols/cursor/CMakeLists.txt +++ b/tests/auto/quickcontrols/cursor/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_cursor LANGUAGES C CXX ASM) + project(tst_cursor LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/customization/CMakeLists.txt b/tests/auto/quickcontrols/customization/CMakeLists.txt index 79dd408257..cca6dfe5a5 100644 --- a/tests/auto/quickcontrols/customization/CMakeLists.txt +++ b/tests/auto/quickcontrols/customization/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_customization LANGUAGES C CXX ASM) + project(tst_customization LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/designer/CMakeLists.txt b/tests/auto/quickcontrols/designer/CMakeLists.txt index 9ad0512f80..3457961f54 100644 --- a/tests/auto/quickcontrols/designer/CMakeLists.txt +++ b/tests/auto/quickcontrols/designer/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_designer LANGUAGES C CXX ASM) + project(tst_designer LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/focus/CMakeLists.txt b/tests/auto/quickcontrols/focus/CMakeLists.txt index 87200bf05c..9db0b48bd6 100644 --- a/tests/auto/quickcontrols/focus/CMakeLists.txt +++ b/tests/auto/quickcontrols/focus/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_focus LANGUAGES C CXX ASM) + project(tst_focus LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/font/CMakeLists.txt b/tests/auto/quickcontrols/font/CMakeLists.txt index 9eaee341d0..4266cfc756 100644 --- a/tests/auto/quickcontrols/font/CMakeLists.txt +++ b/tests/auto/quickcontrols/font/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_font LANGUAGES C CXX ASM) + project(tst_font LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/palette/CMakeLists.txt b/tests/auto/quickcontrols/palette/CMakeLists.txt index fd4ee2d680..747ea76226 100644 --- a/tests/auto/quickcontrols/palette/CMakeLists.txt +++ b/tests/auto/quickcontrols/palette/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_palette LANGUAGES C CXX ASM) + project(tst_palette LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/platform/CMakeLists.txt b/tests/auto/quickcontrols/platform/CMakeLists.txt index a2f77fdd9c..5f6d64491f 100644 --- a/tests/auto/quickcontrols/platform/CMakeLists.txt +++ b/tests/auto/quickcontrols/platform/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_platform LANGUAGES C CXX ASM) + project(tst_platform LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt b/tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt index 8bc7b26b31..cf73a05132 100644 --- a/tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt +++ b/tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_pointerhandlers LANGUAGES C CXX ASM) + project(tst_pointerhandlers LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/pressandhold/CMakeLists.txt b/tests/auto/quickcontrols/pressandhold/CMakeLists.txt index 8d8c967a56..9f4a889916 100644 --- a/tests/auto/quickcontrols/pressandhold/CMakeLists.txt +++ b/tests/auto/quickcontrols/pressandhold/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_pressandhold LANGUAGES C CXX ASM) + project(tst_pressandhold LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt b/tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt index a24d019827..4e40383d9c 100644 --- a/tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickapplicationwindow LANGUAGES C CXX ASM) + project(tst_qquickapplicationwindow LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp b/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp index a02ab9c595..8ef7122d29 100644 --- a/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp +++ b/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp @@ -891,7 +891,7 @@ void tst_QQuickApplicationWindow::layoutLayout() QCOMPARE(headerChild->width(), qreal(window->width())); QVERIFY(header->height() > 0); - QQuickItem *footerChild = header->findChild<QQuickItem*>(); + QQuickItem *footerChild = footer->findChild<QQuickItem*>(); QVERIFY(footerChild); QCOMPARE(footer->x(), 0.0); QCOMPARE(footer->y(), content->height()); diff --git a/tests/auto/quickcontrols/qquickcolor/CMakeLists.txt b/tests/auto/quickcontrols/qquickcolor/CMakeLists.txt index efd06f15ff..4bbed44111 100644 --- a/tests/auto/quickcontrols/qquickcolor/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickcolor/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickcolor LANGUAGES C CXX ASM) + project(tst_qquickcolor LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickcontainer/CMakeLists.txt b/tests/auto/quickcontrols/qquickcontainer/CMakeLists.txt index c79e508cd1..c04b31a415 100644 --- a/tests/auto/quickcontrols/qquickcontainer/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickcontainer/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickcontainer LANGUAGES C CXX ASM) + project(tst_qquickcontainer LANGUAGES C CXX) find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickcontainer/data/skipReorderContentModelItem.qml b/tests/auto/quickcontrols/qquickcontainer/data/skipReorderContentModelItem.qml new file mode 100644 index 0000000000..9074904026 --- /dev/null +++ b/tests/auto/quickcontrols/qquickcontainer/data/skipReorderContentModelItem.qml @@ -0,0 +1,57 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls +import QtQml.Models + +Window { + width: 640 + height: 480 + + property alias navigationBar: navigationbar + + component NavigationBar: Container { + id: container + + property alias model: repeater.model + property alias listView: list + + implicitHeight: 20 + + contentItem: Item { + width: parent.width + height: parent.height + + ListView { + id: list + model: container.contentModel + snapMode: ListView.SnapToItem + orientation: ListView.Horizontal + interactive: width < contentWidth + clip: interactive + spacing: 20 + + anchors { + right: parent.right + top: parent.top + bottom: parent.bottom + left: parent.left + } + } + } + + Repeater { + id: repeater + delegate: Text { + text: modelData + } + } + } + + NavigationBar { + id: navigationbar + width: 100 + model: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] + } +} diff --git a/tests/auto/quickcontrols/qquickcontainer/tst_qquickcontainer.cpp b/tests/auto/quickcontrols/qquickcontainer/tst_qquickcontainer.cpp index ce95f2cc37..b61717e4c9 100644 --- a/tests/auto/quickcontrols/qquickcontainer/tst_qquickcontainer.cpp +++ b/tests/auto/quickcontrols/qquickcontainer/tst_qquickcontainer.cpp @@ -8,6 +8,8 @@ #include <QtQuickTestUtils/private/qmlutils_p.h> #include <QtQuickTestUtils/private/visualtestutils_p.h> #include <QtQuickControlsTestUtils/private/controlstestutils_p.h> +#include <QtQuick/private/qquicklistview_p.h> +#include <QtQmlModels/private/qqmlobjectmodel_p.h> using namespace QQuickVisualTestUtils; using namespace QQuickControlsTestUtils; @@ -22,6 +24,7 @@ public: private slots: void zeroSize_data(); void zeroSize(); + void skipReorderContentModelItem(); }; tst_qquickcontainer::tst_qquickcontainer() @@ -102,6 +105,34 @@ void tst_qquickcontainer::zeroSize() QCOMPARE(QQuickItemPrivate::get(text4)->culled, isItemView); } +void tst_qquickcontainer::skipReorderContentModelItem() +{ + QQuickControlsApplicationHelper helper(this, "skipReorderContentModelItem.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + centerOnScreen(helper.window); + helper.window->show(); + QVERIFY(QTest::qWaitForWindowExposed(helper.window)); + + const auto *container = helper.window->property("navigationBar").value<QQuickContainer *>(); + QVERIFY(container); + const auto *listView = container->property("listView").value<QQuickListView *>(); + QVERIFY(listView); + const auto *contentModel = container->property("contentModel").value<QQmlObjectModel *>(); + QVERIFY(contentModel); + + QCOMPARE(listView->count(), contentModel->count()); + + int totalWidth = listView->spacing() * (contentModel->count() - 1); + for (int index = 0; index < contentModel->count(); index++) + totalWidth += qobject_cast<QQuickText *>(listView->itemAtIndex(index))->width(); + QVERIFY(totalWidth > listView->width()); + + for (int index = 0; index < listView->count(); index++) { + const auto *textItem = qobject_cast<QQuickText *>(listView->itemAtIndex(index)); + QCOMPARE(textItem->text().toInt(), index + 1); + } +} + QTEST_MAIN(tst_qquickcontainer) #include "tst_qquickcontainer.moc" diff --git a/tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt b/tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt index a43b14f1fa..51686657ca 100644 --- a/tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickcontrol LANGUAGES C CXX ASM) + project(tst_qquickcontrol LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt b/tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt index 2515a8d30e..bb78889d4f 100644 --- a/tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickdrawer LANGUAGES C CXX ASM) + project(tst_qquickdrawer LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt b/tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt index 1925c85dc8..2f0c1c2285 100644 --- a/tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickheaderview LANGUAGES C CXX ASM) + project(tst_qquickheaderview LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt b/tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt index 58f8a8f6f5..0620eaa28e 100644 --- a/tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickiconimage LANGUAGES C CXX ASM) + project(tst_qquickiconimage LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt b/tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt index 48ede72c13..63ee07ca02 100644 --- a/tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickiconlabel LANGUAGES C CXX ASM) + project(tst_qquickiconlabel LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickiconlabel/data/childPaintOrder.qml b/tests/auto/quickcontrols/qquickiconlabel/data/childPaintOrder.qml new file mode 100644 index 0000000000..b26d36fac6 --- /dev/null +++ b/tests/auto/quickcontrols/qquickiconlabel/data/childPaintOrder.qml @@ -0,0 +1,32 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl + +AbstractButton { + id: control + width: 200 + height: 200 + text: "Button" + icon.source: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png" + icon.color: enabled ? "transparent" : "red" + + contentItem: IconLabel { + id: iconLabel + objectName: "iconLabel" + display: control.display + icon: control.icon + text: control.text + font: control.font + + Text { + objectName: "childText" + color: "red" + anchors.centerIn: parent + text: "Should be in front" + font.bold: true + } + } +} diff --git a/tests/auto/quickcontrols/qquickiconlabel/tst_qquickiconlabel.cpp b/tests/auto/quickcontrols/qquickiconlabel/tst_qquickiconlabel.cpp index 8d42cf5faf..cc11acee1d 100644 --- a/tests/auto/quickcontrols/qquickiconlabel/tst_qquickiconlabel.cpp +++ b/tests/auto/quickcontrols/qquickiconlabel/tst_qquickiconlabel.cpp @@ -12,13 +12,16 @@ #include <QtQuick/private/qquicktext_p.h> #include <QtQuick/private/qquickimage_p_p.h> #include <QtQuickTestUtils/private/qmlutils_p.h> +#include <QtQuickTestUtils/private/viewtestutils_p.h> #include <QtQuickTestUtils/private/visualtestutils_p.h> #include <QtQuickTemplates2/private/qquickabstractbutton_p.h> #include <QtQuickTemplates2/private/qquickicon_p.h> #include <QtQuickControls2Impl/private/qquickiconimage_p.h> #include <QtQuickControls2Impl/private/qquickiconlabel_p.h> #include <QtQuickControls2Impl/private/qquickiconlabel_p_p.h> +#include <QtQuickControls2Impl/private/qquickmnemoniclabel_p.h> +using namespace QQuickViewTestUtils; using namespace QQuickVisualTestUtils; class tst_qquickiconlabel : public QQmlDataTest @@ -35,6 +38,7 @@ private slots: void emptyIconSource(); void colorChanges(); void iconSourceContext(); + void childPaintOrder(); }; tst_qquickiconlabel::tst_qquickiconlabel() @@ -340,6 +344,22 @@ void tst_qquickiconlabel::iconSourceContext() } +// QTBUG-133924: check that items declared as children of us are rendered on top of the label and icon image. +void tst_qquickiconlabel::childPaintOrder() +{ + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl("childPaintOrder.qml"))); + + auto *iconLabel = window.findChild<QQuickItem *>("iconLabel"); + QVERIFY(iconLabel); + auto *iconLabelPrivate = static_cast<QQuickIconLabelPrivate *>(QQuickItemPrivate::get(iconLabel)); + + auto *childText = window.findChild<QQuickItem *>("childText"); + QVERIFY(childText); + const QList<QQuickItem *> expectedPaintOrder = { iconLabelPrivate->label, iconLabelPrivate->image, childText }; + QCOMPARE(iconLabelPrivate->paintOrderChildItems(), expectedPaintOrder); +} + QTEST_MAIN(tst_qquickiconlabel) #include "tst_qquickiconlabel.moc" diff --git a/tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt b/tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt index 1985784386..d1b8f8b16e 100644 --- a/tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickimaginestyle LANGUAGES C CXX ASM) + project(tst_qquickimaginestyle LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt b/tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt index 0afeaf2fb3..a74a9d1a54 100644 --- a/tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickmaterialstyle LANGUAGES C CXX ASM) + project(tst_qquickmaterialstyle LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml b/tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml index 69a2d95ab3..862aa15488 100644 --- a/tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml +++ b/tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml @@ -1325,4 +1325,33 @@ TestCase { tryCompare(busyIndicator.contentItem, "visible", true) } + + Component { + id: labelInPopupComponent + + Popup { + id: popupInstance + + property alias label: label + + Material.theme: Material.Dark + + Label { + id: label + text: "Should have a dark theme" + } + } + } + + function test_popupPropagatesToChildItem() { + let popup = createTemporaryObject(labelInPopupComponent, testCase) + verify(popup) + + compare(popup.Material.theme, Material.Dark) + compare(popup.label.Material.theme, Material.Dark) + + popup.Material.theme = Material.Light + compare(popup.Material.theme, Material.Light) + compare(popup.label.Material.theme, Material.Light) + } } diff --git a/tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt b/tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt index 36c518aa9c..56364c5a63 100644 --- a/tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickmaterialstyleconf LANGUAGES C CXX ASM) + project(tst_qquickmaterialstyleconf LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt b/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt index 0277c88446..4b4e89d545 100644 --- a/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickmenu LANGUAGES C CXX ASM) + project(tst_qquickmenu LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickmenu/data/animationOnHeight.qml b/tests/auto/quickcontrols/qquickmenu/data/animationOnHeight.qml new file mode 100644 index 0000000000..e01e764efd --- /dev/null +++ b/tests/auto/quickcontrols/qquickmenu/data/animationOnHeight.qml @@ -0,0 +1,70 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Templates as T + +ApplicationWindow { + width: 600 + height: 400 + + Action { + id: copyAction + text: "Copy" + } + + // Based on FluentWinUI3's Menu. + T.Menu { + id: menu + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + delegate: MenuItem { } + + contentItem: ListView { + implicitHeight: contentHeight + model: menu.contentModel + interactive: Window.window + ? contentHeight + menu.topPadding + menu.bottomPadding > menu.height + : false + currentIndex: menu.currentIndex + spacing: 4 + clip: true + + ScrollIndicator.vertical: ScrollIndicator {} + } + + enter: Transition { + NumberAnimation { + property: "height" + from: menu.implicitHeight * 0.33 + to: menu.implicitHeight + easing.type: Easing.OutCubic + duration: 1 + } + } + + background: Rectangle { + implicitWidth: 200 + implicitHeight: 30 + border.width: 1 + } + + T.Overlay.modal: Rectangle { + color: "transparent" + } + + T.Overlay.modeless: Rectangle { + color: "transparent" + } + + Action { + text: "Cut" + } + } + + Component.onCompleted: { + menu.addAction(copyAction) + } +} diff --git a/tests/auto/quickcontrols/qquickmenu/data/customMenuUseRepeaterAsTheContentItem.qml b/tests/auto/quickcontrols/qquickmenu/data/customMenuUseRepeaterAsTheContentItem.qml index bfa8f66be5..ebd0ab26b3 100644 --- a/tests/auto/quickcontrols/qquickmenu/data/customMenuUseRepeaterAsTheContentItem.qml +++ b/tests/auto/quickcontrols/qquickmenu/data/customMenuUseRepeaterAsTheContentItem.qml @@ -9,7 +9,6 @@ ApplicationWindow { Menu { id: menu - visible: true contentItem: FocusScope { implicitHeight: flickable.height diff --git a/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml b/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml index 1156d30aef..9299edb77d 100644 --- a/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml +++ b/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml @@ -15,7 +15,7 @@ Window { id: menu anchors.centerIn: parent height: 100 - visible: true + Repeater { model: 10 delegate: MenuItem { diff --git a/tests/auto/quickcontrols/qquickmenu/data/shortcutInNestedSubMenuAction.qml b/tests/auto/quickcontrols/qquickmenu/data/shortcutInNestedSubMenuAction.qml new file mode 100644 index 0000000000..02cb7d15c4 --- /dev/null +++ b/tests/auto/quickcontrols/qquickmenu/data/shortcutInNestedSubMenuAction.qml @@ -0,0 +1,30 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls + +ApplicationWindow { + id: root + width: 400 + height: 400 + + property int triggeredCount + + Menu { + objectName: "topLevelMenu" + + Menu { + objectName: "subMenu" + + Menu { + objectName: "subSubMenu" + + Action { + shortcut: StandardKey.Copy + onTriggered: ++root.triggeredCount + } + } + } + } +} diff --git a/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp b/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp index 041c3d7ab9..578d5e84b4 100644 --- a/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp +++ b/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp @@ -15,6 +15,7 @@ #include <QtQml/qqmlcontext.h> #include <QtQuick/qquickview.h> #include <QtQuick/private/qquickitem_p.h> +#include <QtQuick/private/qquicklistview_p.h> #include <QtQuick/private/qquickmousearea_p.h> #include <QtQuick/private/qquickrectangle_p.h> #include <QtQuickTest/quicktest.h> @@ -95,6 +96,8 @@ private slots: void customMenuUseRepeaterAsTheContentItem(); void invalidUrlInImgTag(); void mousePropagationWithinPopup(); + void shortcutInNestedSubMenuAction(); + void animationOnHeight(); }; tst_QQuickMenu::tst_QQuickMenu() @@ -2365,6 +2368,41 @@ void tst_QQuickMenu::mousePropagationWithinPopup() } } +void tst_QQuickMenu::shortcutInNestedSubMenuAction() +{ + QQuickControlsApplicationHelper helper(this, QLatin1String("shortcutInNestedSubMenuAction.qml")); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickApplicationWindow *window = helper.appWindow; + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + // Shouldn't result in an infinite loop. + QTest::keyClick(window, Qt::Key_C, Qt::ControlModifier); + QCOMPARE(window->property("triggeredCount").value<int>(), 1); +} + +void tst_QQuickMenu::animationOnHeight() +{ + QQuickControlsApplicationHelper helper(this, QLatin1String("animationOnHeight.qml")); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickApplicationWindow *window = helper.appWindow; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *menu = window->findChild<QQuickMenu *>(); + QVERIFY(menu); + menu->popup(QPointF(100, 100)); + QTRY_VERIFY(menu->isOpened()); + + // After adding the Action, the contentHeight of the Menu's ListView should + // be not be greater than its height; it shouldn't be possible to scroll. + auto *listView = qobject_cast<QQuickListView *>(menu->contentItem()); + const qreal itemHeight = menu->itemAt(0)->height(); + QCOMPARE(listView->contentHeight(), itemHeight * 2 + listView->spacing()); + QCOMPARE_GE(listView->height(), listView->contentHeight()); +} + QTEST_QUICKCONTROLS_MAIN(tst_QQuickMenu) #include "tst_qquickmenu.moc" diff --git a/tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt b/tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt index cee75be2f9..0796160031 100644 --- a/tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickmenubar LANGUAGES C CXX ASM) + project(tst_qquickmenubar LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickmenubar/data/clearMenus.qml b/tests/auto/quickcontrols/qquickmenubar/data/clearMenus.qml new file mode 100644 index 0000000000..6844902fb6 --- /dev/null +++ b/tests/auto/quickcontrols/qquickmenubar/data/clearMenus.qml @@ -0,0 +1,35 @@ +import QtQuick +import QtQuick.Templates + +Item { + property int v: 0 + + MenuBar { + id: menuBar + Menu {} + } + + Instantiator { + id: instantiator + + delegate: Menu {} + + onObjectAdded: (index, object) => { + menuBar.menus.push(object) + } + + onObjectRemoved: (index, object) => { + menuBar.menus.length = 0; + } + } + + Timer { + running: v < 2 + interval: 1 + repeat: true + + onTriggered: { + instantiator.model = (++v % 2) ? 0 : 2 + } + } +} diff --git a/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp b/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp index ee593e1701..7cb842d5a7 100644 --- a/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp +++ b/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp @@ -36,6 +36,7 @@ private slots: void altNavigation(); void addRemove(); void checkHighlightWhenMenuDismissed(); + void clearMenus(); private: QScopedPointer<QPointingDevice> touchScreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice()); @@ -771,6 +772,16 @@ void tst_qquickmenubar::checkHighlightWhenMenuDismissed() QVERIFY(!dynamicMenuBarItem->isHighlighted()); } +void tst_qquickmenubar::clearMenus() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("clearMenus.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + QTRY_COMPARE(o->property("v").toInt(), 2); +} + QTEST_QUICKCONTROLS_MAIN(tst_qquickmenubar) #include "tst_qquickmenubar.moc" diff --git a/tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt b/tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt index e8a4e733b8..43ac4fca05 100644 --- a/tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickninepatchimage LANGUAGES C CXX ASM) + project(tst_qquickninepatchimage LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt b/tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt index e5d9da4dc9..969604455c 100644 --- a/tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickpopup LANGUAGES C CXX ASM) + project(tst_qquickpopup LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt b/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt index 81eb78c906..a0f9d12503 100644 --- a/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickpopup LANGUAGES C CXX ASM) + project(tst_qquickpopup LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickpopup/data/propagateTouchEvents.qml b/tests/auto/quickcontrols/qquickpopup/data/propagateTouchEvents.qml new file mode 100644 index 0000000000..01c7fe39de --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/propagateTouchEvents.qml @@ -0,0 +1,17 @@ +import QtQuick +import QtQuick.Controls + +Window { + id: rootItem + width: 100 + height: 100 + + property alias tapHandler: tHandler + + Popup { + id: popupItem + width: 50 + height: 50 + background: Item { TapHandler { id: tHandler } } + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp index 966f908e80..6dc260faea 100644 --- a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp +++ b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp @@ -30,6 +30,7 @@ #include <QtQuickTemplates2/private/qquickdrawer_p.h> #include <QtQuick/private/qquicklistview_p.h> #include <QtQuick/private/qquicktextedit_p.h> +#include <QtQuick/private/qquicktaphandler_p.h> #include <QtQuick/private/qquickdroparea_p.h> #include <QtQuickControlsTestUtils/private/controlstestutils_p.h> #include <QtQuickControlsTestUtils/private/qtest_quickcontrols_p.h> @@ -105,6 +106,7 @@ private slots: void doubleClickInMouseArea(); void pointerEventsNotBlockedForNonPopupChildrenOfOverlayWithHigherZ(); void resetHoveredStateForItemsWithinPopup(); + void propagateTouchEvents(); private: QScopedPointer<QPointingDevice> touchScreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice()); @@ -2364,6 +2366,14 @@ void tst_QQuickPopup::pointerEventsNotBlockedForNonPopupChildrenOfOverlayWithHig QCOMPARE(lowerMouseAreaSpy.count(), 0); QCOMPARE(upperMouseAreaSpy.count(), 1); + // Verify that the upper mouse area is hovered, even when a mouse press happens on top of a modal dialog + upperMouseArea->setHoverEnabled(true); + QTest::mouseMove(window, button->mapToScene(button->boundingRect().center() - QPoint(1,1)).toPoint()); + QVERIFY(!upperMouseArea->hovered()); + upperMouseArea->setEnabled(true); + QTest::mouseMove(window, button->mapToScene(button->boundingRect().center() + QPoint(1,1)).toPoint()); + QVERIFY(upperMouseArea->hovered()); + popup->close(); } @@ -2401,6 +2411,34 @@ void tst_QQuickPopup::resetHoveredStateForItemsWithinPopup() QTRY_VERIFY(!controlItem->isHovered()); } +void tst_QQuickPopup::propagateTouchEvents() +{ + QQuickApplicationHelper helper(this, "propagateTouchEvents.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *popup = window->contentItem()->findChild<QQuickPopup *>(); + popup->open(); + QTRY_VERIFY(popup->isOpened()); + + auto *tapHandler = window->property("tapHandler").value<QQuickTapHandler *>(); + QVERIFY(tapHandler); + QSignalSpy tapSpy(tapHandler, &QQuickTapHandler::tapped); + // check for the item within the popup for touch events + QTest::touchEvent(window, touchScreen.data()).press(0, QPoint(10, 10)); + QTest::touchEvent(window, touchScreen.data()).release(0, QPoint(10, 10)); + QCOMPARE(tapSpy.count(), 1); + + // touch outside to close the popup window + QTest::touchEvent(window, touchScreen.data()).press(0, QPoint(90, 90)); + QTest::touchEvent(window, touchScreen.data()).release(0, QPoint(90, 90)); + QCOMPARE(tapSpy.count(), 1); + + QTRY_VERIFY(!popup->isOpened()); +} + QTEST_QUICKCONTROLS_MAIN(tst_QQuickPopup) #include "tst_qquickpopup.moc" diff --git a/tests/auto/quickcontrols/qquickstyle/CMakeLists.txt b/tests/auto/quickcontrols/qquickstyle/CMakeLists.txt index 4255850e30..525f56bdea 100644 --- a/tests/auto/quickcontrols/qquickstyle/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickstyle/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickstyle LANGUAGES C CXX ASM) + project(tst_qquickstyle LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt b/tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt index f64b896e5c..01dcd5b942 100644 --- a/tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquicktextarea LANGUAGES C CXX ASM) + project(tst_qquicktextarea LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt b/tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt index 50755b7f1c..7f4cac7f34 100644 --- a/tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquicktextfield LANGUAGES C CXX ASM) + project(tst_qquicktextfield LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt b/tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt index 94d4096586..063a90a358 100644 --- a/tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquicktreeviewdelegate LANGUAGES C CXX ASM) + project(tst_qquicktreeviewdelegate LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt b/tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt index a7f8ebfd6f..2122fac1db 100644 --- a/tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickuniversalstyle LANGUAGES C CXX ASM) + project(tst_qquickuniversalstyle LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt b/tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt index cfe781950d..86d100b1be 100644 --- a/tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_qquickuniversalstyleconf LANGUAGES C CXX ASM) + project(tst_qquickuniversalstyleconf LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/revisions/CMakeLists.txt b/tests/auto/quickcontrols/revisions/CMakeLists.txt index 8c51f85d20..46f0734f68 100644 --- a/tests/auto/quickcontrols/revisions/CMakeLists.txt +++ b/tests/auto/quickcontrols/revisions/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_revisions LANGUAGES C CXX ASM) + project(tst_revisions LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/sanity/CMakeLists.txt b/tests/auto/quickcontrols/sanity/CMakeLists.txt index 6c99b5b7c7..e301e72d44 100644 --- a/tests/auto/quickcontrols/sanity/CMakeLists.txt +++ b/tests/auto/quickcontrols/sanity/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_sanity LANGUAGES C CXX ASM) + project(tst_sanity LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/snippets/CMakeLists.txt b/tests/auto/quickcontrols/snippets/CMakeLists.txt index cfb2fb4560..08b55c2645 100644 --- a/tests/auto/quickcontrols/snippets/CMakeLists.txt +++ b/tests/auto/quickcontrols/snippets/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_snippets LANGUAGES C CXX ASM) + project(tst_snippets LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/styleimports/CMakeLists.txt b/tests/auto/quickcontrols/styleimports/CMakeLists.txt index 4d19521f2e..e2f4e8d7a9 100644 --- a/tests/auto/quickcontrols/styleimports/CMakeLists.txt +++ b/tests/auto/quickcontrols/styleimports/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_styleimports LANGUAGES C CXX ASM) + project(tst_styleimports LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt b/tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt index 6e7f22da64..adec66b532 100644 --- a/tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt +++ b/tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_styleimportscompiletimematerial LANGUAGES C CXX ASM) + project(tst_styleimportscompiletimematerial LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt b/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt index 6e56e6a96e..ddb9a64413 100644 --- a/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt +++ b/tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_styleimportscompiletimeqmlonly LANGUAGES C CXX ASM) + project(tst_styleimportscompiletimeqmlonly LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickcontrols/translation/CMakeLists.txt b/tests/auto/quickcontrols/translation/CMakeLists.txt index 745262cdcc..228fdf25e2 100644 --- a/tests/auto/quickcontrols/translation/CMakeLists.txt +++ b/tests/auto/quickcontrols/translation/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_translation LANGUAGES C CXX ASM) + project(tst_translation LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp b/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp index a42ea91b6d..6b81b9abbb 100644 --- a/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp +++ b/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp @@ -104,9 +104,13 @@ private: QStringList tempSubDirExpectedVisibleFiles(DelegateOrderPolicy order) const; QTemporaryDir tempDir; + QString tempDirCanonicalPath; QScopedPointer<QFile> tempFile1; + QString tempFile1CanonicalPath; QScopedPointer<QFile> tempFile2; + QString tempFile2CanonicalPath; QDir tempSubDir; + QString tempSubDirCanonicalPath; QDir tempSubSubDir; QScopedPointer<QFile> tempSubFile1; QScopedPointer<QFile> tempSubFile2; @@ -114,6 +118,7 @@ private: QTemporaryDir largeTempDir; QStringList largeTempDirPaths; QDir largeTempDirLargeSubDir; + QString largeTempDirLargeSubDirCanonicalPath; const int largeTempDirLargeSubDirIndex = 80; QDir oldCurrentDir; @@ -125,8 +130,8 @@ private: QStringList tst_QQuickFileDialogImpl::tempDirExpectedVisibleFiles(DelegateOrderPolicy order) const { return order == ShowDirectoriesFirst - ? QStringList { tempSubDir.path(), tempFile1->fileName(), tempFile2->fileName() } - : QStringList { tempFile1->fileName(), tempFile2->fileName(), tempSubDir.path() }; + ? QStringList { tempSubDirCanonicalPath, tempFile1CanonicalPath, tempFile2CanonicalPath } + : QStringList { tempFile1CanonicalPath, tempFile2CanonicalPath, tempSubDirCanonicalPath }; } QStringList tst_QQuickFileDialogImpl::tempSubDirExpectedVisibleFiles(DelegateOrderPolicy order) const @@ -150,12 +155,17 @@ void tst_QQuickFileDialogImpl::initTestCase() qputenv("QT_QUICK_DIALOGS_PRESELECT_FIRST_FILE", "1"); + // Ensure that each test starts off in the temporary directory. + oldCurrentDir = QDir::current(); + QDir::setCurrent(tempDir.path()); + QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString())); + tempDirCanonicalPath = QFileInfo(tempDir.path()).canonicalFilePath(); // QTEST_QUICKCONTROLS_MAIN constructs the test case object once, // and then calls qRun() for each style, and qRun() calls initTestCase(). // So, we need to check if we've already made the temporary directory. // Note that this is only necessary if the test is run with more than one style. - if (!QDir(tempDir.path()).isEmpty()) + if (!QDir(tempDirCanonicalPath).isEmpty()) return; /* @@ -169,29 +179,35 @@ void tst_QQuickFileDialogImpl::initTestCase() ├── file1.txt (tempFile1) └── file2.txt (tempFile2) */ - tempSubDir = QDir(tempDir.path()); + tempSubDir = QDir(tempDirCanonicalPath); QVERIFY2(tempSubDir.mkdir("sub-dir"), qPrintable(QString::fromLatin1( "Failed to make sub-directory \"sub-dir\" in %1. Permissions are: %2") - .arg(tempDir.path()).arg(QDebug::toString(QFileInfo(tempDir.path()).permissions())))); + .arg(tempDirCanonicalPath).arg(QDebug::toString(QFileInfo(tempDirCanonicalPath).permissions())))); QVERIFY(tempSubDir.cd("sub-dir")); + tempSubDirCanonicalPath = tempSubDir.canonicalPath(); + QVERIFY(!tempSubDirCanonicalPath.isEmpty()); - tempSubSubDir = QDir(tempSubDir.path()); + tempSubSubDir = QDir(tempSubDirCanonicalPath); QVERIFY2(tempSubSubDir.mkdir("sub-sub-dir"), qPrintable(QString::fromLatin1( "Failed to make sub-directory \"sub-sub-dir\" in %1. Permissions are: %2") - .arg(tempSubDir.path()).arg(QDebug::toString(QFileInfo(tempSubDir.path()).permissions())))); + .arg(tempSubDirCanonicalPath).arg(QDebug::toString(QFileInfo(tempSubDirCanonicalPath).permissions())))); QVERIFY(tempSubSubDir.cd("sub-sub-dir")); - tempSubFile1.reset(new QFile(tempSubDir.path() + "/sub-file1.txt")); + tempSubFile1.reset(new QFile(tempSubDirCanonicalPath + "/sub-file1.txt")); QVERIFY(tempSubFile1->open(QIODevice::ReadWrite)); - tempSubFile2.reset(new QFile(tempSubDir.path() + "/sub-file2.txt")); + tempSubFile2.reset(new QFile(tempSubDirCanonicalPath + "/sub-file2.txt")); QVERIFY(tempSubFile2->open(QIODevice::ReadWrite)); - tempFile1.reset(new QFile(tempDir.path() + "/file1.txt")); + tempFile1.reset(new QFile(tempDirCanonicalPath + "/file1.txt")); QVERIFY(tempFile1->open(QIODevice::ReadWrite)); + tempFile1CanonicalPath = QFileInfo(tempFile1->fileName()).canonicalFilePath(); + QVERIFY(!tempFile1CanonicalPath.isEmpty()); - tempFile2.reset(new QFile(tempDir.path() + "/file2.txt")); + tempFile2.reset(new QFile(tempDirCanonicalPath + "/file2.txt")); QVERIFY(tempFile2->open(QIODevice::ReadWrite)); + tempFile2CanonicalPath = QFileInfo(tempFile2->fileName()).canonicalFilePath(); + QVERIFY(!tempFile1CanonicalPath.isEmpty()); /* Create another temporary directory that contains a large amount of folders. @@ -199,11 +215,12 @@ void tst_QQuickFileDialogImpl::initTestCase() QVERIFY2(largeTempDir.isValid(), qPrintable(largeTempDir.errorString())); const static int largeFileCount = 100; const QDir largeTempDirectory(largeTempDir.path()); + const QString largeTempDirectoryCanonicalPath = largeTempDirectory.canonicalPath(); for (int i = 0; i < largeFileCount; ++i) { // Pad with zeroes so that the directories are ordered as we expect. const QString dirName = QString::fromLatin1("dir%1").arg(i, 3, 10, QLatin1Char('0')); QVERIFY(largeTempDirectory.mkdir(dirName)); - largeTempDirPaths.append(largeTempDirectory.filePath(dirName)); + largeTempDirPaths.append(largeTempDirectoryCanonicalPath + '/' + dirName); } // ... and within one of those folders, more folders. @@ -213,10 +230,7 @@ void tst_QQuickFileDialogImpl::initTestCase() const QDir largeTempSubDirectory = QDir(largeTempDirLargeSubDir.path()); for (int i = 0; i < largeFileCount; ++i) QVERIFY(largeTempSubDirectory.mkdir(QString::fromLatin1("sub-dir%1").arg(i, 3, 10, QLatin1Char('0')))); - - // Ensure that each test starts off in the temporary directory. - oldCurrentDir = QDir::current(); - QDir::setCurrent(tempDir.path()); + largeTempDirLargeSubDirCanonicalPath = largeTempDirLargeSubDir.canonicalPath(); } void tst_QQuickFileDialogImpl::init() @@ -322,7 +336,8 @@ void tst_QQuickFileDialogImpl::defaults() QTRY_VERIFY(dialogHelper.isQuickDialogOpen()); QQuickFileDialogImpl *quickDialog = dialogHelper.window()->findChild<QQuickFileDialogImpl*>(); QVERIFY(quickDialog); - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(QDir().absolutePath()), QUrl::fromLocalFile(tempSubDir.path()), 0); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(QDir().absolutePath()), + QUrl::fromLocalFile(tempSubDirCanonicalPath), 0); QCOMPARE(quickDialog->title(), QString()); } @@ -340,9 +355,10 @@ void tst_QQuickFileDialogImpl::chooseFileViaStandardButtons() QQuickFileDialogDelegate *delegate = nullptr; QTRY_VERIFY(findViewDelegateItem(dialogHelper.fileDialogListView, 2, delegate)); - COMPARE_URL(delegate->file(), QUrl::fromLocalFile(tempFile2->fileName())); + COMPARE_URL(delegate->file(), QUrl::fromLocalFile(tempFile2CanonicalPath)); QVERIFY(clickButton(delegate)); - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempFile2->fileName()), 2); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), + QUrl::fromLocalFile(tempFile2CanonicalPath), 2); QCOMPARE(dialogSelectedFileChangedSpy.size(), 1); QCOMPARE(dialogCurrentFileChangedSpy.size(), 1); @@ -353,9 +369,9 @@ void tst_QQuickFileDialogImpl::chooseFileViaStandardButtons() QQuickAbstractButton* openButton = findDialogButton(dialogButtonBox, "Open"); QVERIFY(openButton); QVERIFY(clickButton(openButton)); - COMPARE_URL(dialogHelper.dialog->selectedFile(), QUrl::fromLocalFile(tempFile2->fileName())); - COMPARE_URLS(dialogHelper.dialog->selectedFiles(), { QUrl::fromLocalFile(tempFile2->fileName()) }); - COMPARE_URL(dialogHelper.quickDialog->selectedFile(), QUrl::fromLocalFile(tempFile2->fileName())); + COMPARE_URL(dialogHelper.dialog->selectedFile(), QUrl::fromLocalFile(tempFile2CanonicalPath)); + COMPARE_URLS(dialogHelper.dialog->selectedFiles(), { QUrl::fromLocalFile(tempFile2CanonicalPath) }); + COMPARE_URL(dialogHelper.quickDialog->selectedFile(), QUrl::fromLocalFile(tempFile2CanonicalPath)); QCOMPARE(dialogSelectedFileChangedSpy.size(), 1); QCOMPARE(dialogCurrentFileChangedSpy.size(), 1); QTRY_VERIFY(!dialogHelper.quickDialog->isVisible()); @@ -371,12 +387,12 @@ void tst_QQuickFileDialogImpl::chooseFileViaDoubleClick() // Select the delegate by double-clicking. QQuickFileDialogDelegate *delegate = nullptr; QTRY_VERIFY(findViewDelegateItem(dialogHelper.fileDialogListView, 2, delegate)); - COMPARE_URL(delegate->file(), QUrl::fromLocalFile(tempFile2->fileName())) + COMPARE_URL(delegate->file(), QUrl::fromLocalFile(tempFile2CanonicalPath)) QVERIFY(doubleClickButton(delegate)); - COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile2->fileName())) - COMPARE_URLS(dialogHelper.dialog->currentFiles(), { QUrl::fromLocalFile(tempFile2->fileName()) }) - COMPARE_URL(dialogHelper.dialog->selectedFile(), QUrl::fromLocalFile(tempFile2->fileName())) - COMPARE_URLS(dialogHelper.dialog->selectedFiles(), { QUrl::fromLocalFile(tempFile2->fileName()) }) + COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile2CanonicalPath)) + COMPARE_URLS(dialogHelper.dialog->currentFiles(), { QUrl::fromLocalFile(tempFile2CanonicalPath) }) + COMPARE_URL(dialogHelper.dialog->selectedFile(), QUrl::fromLocalFile(tempFile2CanonicalPath)) + COMPARE_URLS(dialogHelper.dialog->selectedFiles(), { QUrl::fromLocalFile(tempFile2CanonicalPath) }) QVERIFY(!dialogHelper.dialog->isVisible()); QTRY_VERIFY(!dialogHelper.quickDialog->isVisible()); } @@ -390,7 +406,8 @@ void tst_QQuickFileDialogImpl::chooseFileViaTextEdit() // on the current item when we set it in setFileDialogListViewCurrentIndex(), // which can make the TextField's visibility check // below fail due to it being hidden when it loses activeFocus. - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), + QUrl::fromLocalFile(tempSubDir.path()), 0); // Get the text edit visible with Ctrl+L. QTest::keySequence(dialogHelper.window(), editPathKeySequence); @@ -401,14 +418,14 @@ void tst_QQuickFileDialogImpl::chooseFileViaTextEdit() QCOMPARE(breadcrumbBar->textField()->selectedText(), breadcrumbBar->textField()->text()); // Enter the path to the file in the text edit. - enterText(dialogHelper.window(), tempFile2->fileName()); - QCOMPARE(breadcrumbBar->textField()->text(), tempFile2->fileName()); + enterText(dialogHelper.window(), tempFile2CanonicalPath); + QCOMPARE(breadcrumbBar->textField()->text(), tempFile2CanonicalPath); // Hit enter to accept. QTest::keyClick(dialogHelper.window(), Qt::Key_Return); - COMPARE_URL(dialogHelper.quickDialog->selectedFile(), QUrl::fromLocalFile(tempFile2->fileName())); - COMPARE_URL(dialogHelper.dialog->selectedFile(), QUrl::fromLocalFile(tempFile2->fileName())); - COMPARE_URLS(dialogHelper.dialog->selectedFiles(), { QUrl::fromLocalFile(tempFile2->fileName()) }); + COMPARE_URL(dialogHelper.quickDialog->selectedFile(), QUrl::fromLocalFile(tempFile2CanonicalPath)); + COMPARE_URL(dialogHelper.dialog->selectedFile(), QUrl::fromLocalFile(tempFile2CanonicalPath)); + COMPARE_URLS(dialogHelper.dialog->selectedFiles(), { QUrl::fromLocalFile(tempFile2CanonicalPath) }); QVERIFY(!dialogHelper.dialog->isVisible()); QTRY_VERIFY(!dialogHelper.quickDialog->isVisible()); } @@ -420,16 +437,17 @@ void tst_QQuickFileDialogImpl::chooseFileViaEnter() OPEN_QUICK_DIALOG(); // Before moving down, the first delegate in the view should be selected and have focus. - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), + QUrl::fromLocalFile(tempSubDirCanonicalPath), 0); // Select the first file in the view by navigating with the down key. QTest::keyClick(dialogHelper.window(), Qt::Key_Down); - COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile1->fileName())); + COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile1CanonicalPath)); // Select the delegate by pressing enter. QTest::keyClick(dialogHelper.window(), Qt::Key_Return); - COMPARE_URL(dialogHelper.dialog->selectedFile(), QUrl::fromLocalFile(tempFile1->fileName())); - COMPARE_URLS(dialogHelper.dialog->selectedFiles(), { QUrl::fromLocalFile(tempFile1->fileName()) }); + COMPARE_URL(dialogHelper.dialog->selectedFile(), QUrl::fromLocalFile(tempFile1CanonicalPath)); + COMPARE_URLS(dialogHelper.dialog->selectedFiles(), { QUrl::fromLocalFile(tempFile1CanonicalPath) }); QVERIFY(!dialogHelper.dialog->isVisible()); QTRY_VERIFY(!dialogHelper.quickDialog->isVisible()); QCOMPARE(dialogHelper.dialog->result(), QQuickFileDialog::Accepted); @@ -441,8 +459,8 @@ void tst_QQuickFileDialogImpl::bindCurrentFolder_data() QTest::addColumn<QUrl>("expectedFolder"); QTest::addColumn<QStringList>("expectedVisibleFiles"); - const auto currentDirUrl = QUrl::fromLocalFile(QDir::current().path()); - const auto tempSubDirUrl = QUrl::fromLocalFile(tempSubDir.path()); + const auto currentDirUrl = QUrl::fromLocalFile(QDir::current().canonicalPath()); + const auto tempSubDirUrl = QUrl::fromLocalFile(tempSubDirCanonicalPath); const auto tempSubFile1Url = QUrl::fromLocalFile(tempSubFile1->fileName()); const QStringList currentDirFiles = tempDirExpectedVisibleFiles(ShowDirectoriesFirst); @@ -470,7 +488,8 @@ void tst_QQuickFileDialogImpl::bindCurrentFolder() // Even waiting for ListView polish and that the FolderListModel's status is ready aren't enough // on Windows, apparently, as sometimes there just aren't any delegates by the time we do the check. // So, we use QTRY_VERIFY2 each time we call this function just to be safe. - QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView, expectedVisibleFiles, failureMessage), qPrintable(failureMessage)); + QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView, expectedVisibleFiles, failureMessage), + qPrintable(failureMessage)); // Check that the breadcrumb bar is correct by constructing the expected files from the expectedFolder. auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>(); @@ -487,10 +506,11 @@ void tst_QQuickFileDialogImpl::changeFolderViaStandardButtons() // Select the delegate by clicking once. QQuickFileDialogDelegate *delegate = nullptr; QTRY_VERIFY(findViewDelegateItem(dialogHelper.fileDialogListView, 0, delegate)); - COMPARE_URL(delegate->file(), QUrl::fromLocalFile(tempSubDir.path())); + COMPARE_URL(delegate->file(), QUrl::fromLocalFile(tempSubDirCanonicalPath)); QVERIFY(clickButton(delegate)); // The selectedFile should change, but not currentFolder. - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), + QUrl::fromLocalFile(tempSubDirCanonicalPath), 0); // Click the "Open" button. The dialog should navigate to that directory, but still be open. QVERIFY(dialogHelper.quickDialog->footer()); @@ -500,7 +520,7 @@ void tst_QQuickFileDialogImpl::changeFolderViaStandardButtons() QVERIFY(openButton); QVERIFY(clickButton(openButton)); COMPARE_URL(dialogHelper.dialog->selectedFile(), QUrl::fromLocalFile(tempSubSubDir.path())); - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir.path())); + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDirCanonicalPath)); QVERIFY(dialogHelper.dialog->isVisible()); dialogHelper.dialog->close(); @@ -530,14 +550,14 @@ void tst_QQuickFileDialogImpl::changeFolderViaDoubleClick() QQuickFileDialogDelegate *subDirDelegate = nullptr; const int subDirIndex = showDirsFirst ? 0 : 2; QTRY_VERIFY(findViewDelegateItem(dialogHelper.fileDialogListView, subDirIndex, subDirDelegate)); - COMPARE_URL(subDirDelegate->file(), QUrl::fromLocalFile(tempSubDir.path())); + COMPARE_URL(subDirDelegate->file(), QUrl::fromLocalFile(tempSubDirCanonicalPath)); QVERIFY(doubleClickButton(subDirDelegate)); const QStringList expectedVisibleFiles = tempSubDirExpectedVisibleFiles(showDirsFirst ? ShowDirectoriesFirst : ShowFilesFirst); QString failureMessage; QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView, expectedVisibleFiles, failureMessage), qPrintable(failureMessage)); // The first file in the directory should now be selected. const QUrl firstFileUrl = showDirsFirst ? QUrl::fromLocalFile(tempSubSubDir.path()) : QUrl::fromLocalFile(tempSubFile1->fileName()); - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempSubDir.path()), firstFileUrl, 0); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempSubDirCanonicalPath), firstFileUrl, 0); // Since we only chose a folder, the dialog should still be open. QVERIFY(dialogHelper.dialog->isVisible()); @@ -552,7 +572,8 @@ void tst_QQuickFileDialogImpl::chooseFolderViaTextEdit() FileDialogTestHelper dialogHelper(this, "fileDialog.qml"); OPEN_QUICK_DIALOG(); // See comment in chooseFileViaTextEdit for why we check for this. - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), + QUrl::fromLocalFile(tempSubDirCanonicalPath), 0); // Get the text edit visible with Ctrl+L. const auto editPathKeySequence = QKeySequence(Qt::CTRL | Qt::Key_L); @@ -564,8 +585,8 @@ void tst_QQuickFileDialogImpl::chooseFolderViaTextEdit() QCOMPARE(breadcrumbBar->textField()->selectedText(), breadcrumbBar->textField()->text()); // Enter the path to the folder in the text edit. - enterText(dialogHelper.window(), tempSubDir.path()); - QCOMPARE(breadcrumbBar->textField()->text(), tempSubDir.path()); + enterText(dialogHelper.window(), tempSubDirCanonicalPath); + QCOMPARE(breadcrumbBar->textField()->text(), tempSubDirCanonicalPath); // Hit enter to accept. QTest::keyClick(dialogHelper.window(), Qt::Key_Return); @@ -574,7 +595,7 @@ void tst_QQuickFileDialogImpl::chooseFolderViaTextEdit() tempSubDirExpectedVisibleFiles(ShowDirectoriesFirst), failureMessage), qPrintable(failureMessage)); // The first file in the directory should be selected, which is "sub-sub-dir". // Note that the TextEdit will still have focus, so we can't use VERIFY_FILE_SELECTED_AND_FOCUSED. - VERIFY_FILE_SELECTED(QUrl::fromLocalFile(tempSubDir.path()), QUrl::fromLocalFile(tempSubSubDir.path())); + VERIFY_FILE_SELECTED(QUrl::fromLocalFile(tempSubDirCanonicalPath), QUrl::fromLocalFile(tempSubSubDir.path())); VERIFY_DELEGATE_CURRENT(QUrl::fromLocalFile(tempSubSubDir.path()), 0) QVERIFY(dialogHelper.dialog->isVisible()); @@ -590,7 +611,8 @@ void tst_QQuickFileDialogImpl::chooseFolderViaEnter() OPEN_QUICK_DIALOG(); // The first delegate in the view should be selected and have focus. - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), + QUrl::fromLocalFile(tempSubDirCanonicalPath), 0); // Select the delegate by pressing enter. QTest::keyClick(dialogHelper.window(), Qt::Key_Return); @@ -598,7 +620,8 @@ void tst_QQuickFileDialogImpl::chooseFolderViaEnter() QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView, tempSubDirExpectedVisibleFiles(ShowDirectoriesFirst), failureMessage), qPrintable(failureMessage)); // The first file in the new directory should be selected, which is "sub-sub-dir". - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempSubDir.path()), QUrl::fromLocalFile(tempSubSubDir.path()), 0); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempSubDirCanonicalPath), + QUrl::fromLocalFile(tempSubSubDir.path()), 0); // Since we only chose a folder, the dialog should still be open. QVERIFY(dialogHelper.dialog->isVisible()); @@ -613,7 +636,8 @@ void tst_QQuickFileDialogImpl::chooseFileAndThenFolderViaTextEdit() FileDialogTestHelper dialogHelper(this, "fileDialog.qml"); OPEN_QUICK_DIALOG(); // See comment in chooseFileViaTextEdit for why we check for this. - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), + QUrl::fromLocalFile(tempSubDirCanonicalPath), 0); // Get the text edit visible with Ctrl+L. QTest::keySequence(dialogHelper.window(), editPathKeySequence); @@ -624,14 +648,14 @@ void tst_QQuickFileDialogImpl::chooseFileAndThenFolderViaTextEdit() QCOMPARE(breadcrumbBar->textField()->selectedText(), breadcrumbBar->textField()->text()); // Enter the path to the file in the text edit. - enterText(dialogHelper.window(), tempFile2->fileName()); - QCOMPARE(breadcrumbBar->textField()->text(), tempFile2->fileName()); + enterText(dialogHelper.window(), tempFile2CanonicalPath); + QCOMPARE(breadcrumbBar->textField()->text(), tempFile2CanonicalPath); // Hit enter to accept. QTest::keyClick(dialogHelper.window(), Qt::Key_Return); - COMPARE_URL(dialogHelper.quickDialog->selectedFile(), QUrl::fromLocalFile(tempFile2->fileName())); - COMPARE_URL(dialogHelper.dialog->selectedFile(), QUrl::fromLocalFile(tempFile2->fileName())); - COMPARE_URLS(dialogHelper.dialog->selectedFiles(), { QUrl::fromLocalFile(tempFile2->fileName()) }); + COMPARE_URL(dialogHelper.quickDialog->selectedFile(), QUrl::fromLocalFile(tempFile2CanonicalPath)); + COMPARE_URL(dialogHelper.dialog->selectedFile(), QUrl::fromLocalFile(tempFile2CanonicalPath)); + COMPARE_URLS(dialogHelper.dialog->selectedFiles(), { QUrl::fromLocalFile(tempFile2CanonicalPath) }); QVERIFY(!dialogHelper.dialog->isVisible()); QTRY_VERIFY(!dialogHelper.quickDialog->isVisible()); // Check that the text edit is hidden and breadcrumbs are shown instead. @@ -647,12 +671,12 @@ void tst_QQuickFileDialogImpl::chooseFileAndThenFolderViaTextEdit() QTest::keySequence(dialogHelper.window(), editPathKeySequence); QVERIFY(breadcrumbBar->textField()->isVisible()); // The text edit should show the directory that contains the last file that was selected. - QCOMPARE(breadcrumbBar->textField()->text(), tempDir.path()); + QCOMPARE(breadcrumbBar->textField()->text(), tempDirCanonicalPath); QCOMPARE(breadcrumbBar->textField()->selectedText(), breadcrumbBar->textField()->text()); // Enter the path to the folder in the text edit. - enterText(dialogHelper.window(), tempSubDir.path()); - QCOMPARE(breadcrumbBar->textField()->text(), tempSubDir.path()); + enterText(dialogHelper.window(), tempSubDirCanonicalPath); + QCOMPARE(breadcrumbBar->textField()->text(), tempSubDirCanonicalPath); // Hit enter to accept. QTest::keyClick(dialogHelper.window(), Qt::Key_Return); @@ -661,7 +685,7 @@ void tst_QQuickFileDialogImpl::chooseFileAndThenFolderViaTextEdit() tempSubDirExpectedVisibleFiles(ShowDirectoriesFirst), failureMessage), qPrintable(failureMessage)); // The first file in the directory should be selected, which is "sub-sub-dir". // Note that the TextEdit will still have focus, so we can't use VERIFY_FILE_SELECTED_AND_FOCUSED. - VERIFY_FILE_SELECTED(QUrl::fromLocalFile(tempSubDir.path()), QUrl::fromLocalFile(tempSubSubDir.path())); + VERIFY_FILE_SELECTED(QUrl::fromLocalFile(tempSubDirCanonicalPath), QUrl::fromLocalFile(tempSubSubDir.path())); VERIFY_DELEGATE_CURRENT(QUrl::fromLocalFile(tempSubSubDir.path()), 0) // Close the dialog. @@ -676,7 +700,8 @@ void tst_QQuickFileDialogImpl::cancelDialogWhileTextEditHasFocus() FileDialogTestHelper dialogHelper(this, "fileDialog.qml"); OPEN_QUICK_DIALOG(); // See comment in chooseFileViaTextEdit for why we check for this. - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), + QUrl::fromLocalFile(tempSubDirCanonicalPath), 0); // Get the text edit visible with Ctrl+L. QTest::keySequence(dialogHelper.window(), editPathKeySequence); @@ -744,12 +769,12 @@ void tst_QQuickFileDialogImpl::goUp() // Open the dialog. Start off in "sub-dir". FileDialogTestHelper dialogHelper(this, "bindCurrentFolder.qml", {}, - {{ "initialFolder", QUrl::fromLocalFile(tempSubDir.path()) }}); + {{ "initialFolder", QUrl::fromLocalFile(tempSubDirCanonicalPath) }}); OPEN_QUICK_DIALOG(); // Go up a directory via the button next to the breadcrumb bar. - qCDebug(lcTest) << "going up to" << tempDir.path() << "- files in that dir:\n" - << QQuickFileDialogImplPrivate::get(dialogHelper.quickDialog)->fileList(QDir(tempDir.path())); + qCDebug(lcTest) << "going up to" << tempDirCanonicalPath << "- files in that dir:\n" + << QQuickFileDialogImplPrivate::get(dialogHelper.quickDialog)->fileList(QDir(tempDirCanonicalPath)); auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>(); QVERIFY(breadcrumbBar); auto barListView = qobject_cast<QQuickListView*>(breadcrumbBar->contentItem()); @@ -762,19 +787,21 @@ void tst_QQuickFileDialogImpl::goUp() QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView, tempDirExpectedVisibleFiles(showDirsFirst ? ShowDirectoriesFirst : ShowFilesFirst), failureMessage), qPrintable(failureMessage)); int expectedCurrentIndex = showDirsFirst ? 0 : 2; - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), expectedCurrentIndex); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), + QUrl::fromLocalFile(tempSubDirCanonicalPath), expectedCurrentIndex); // Go up a directory via the keyboard shortcut. - QDir tempParentDir(tempDir.path()); + QDir tempParentDir(tempDirCanonicalPath); QVERIFY(tempParentDir.cdUp()); const auto filesInTempParentDir = QQuickFileDialogImplPrivate::get(dialogHelper.quickDialog)->fileList(tempParentDir); qCDebug(lcTest) << "going up to" << tempParentDir.path() << "- files in that dir:\n" << filesInTempParentDir; QTest::keySequence(dialogHelper.window(), goUpKeySequence); // Ubuntu on QEMU arm shows no files in /tmp even if there are. if (!filesInTempParentDir.isEmpty()) { - expectedCurrentIndex = filesInTempParentDir.indexOf(QFileInfo(tempDir.path())); + expectedCurrentIndex = filesInTempParentDir.indexOf(QFileInfo(tempDirCanonicalPath)); QVERIFY(expectedCurrentIndex != -1); - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempParentDir.path()), QUrl::fromLocalFile(tempDir.path()), expectedCurrentIndex); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempParentDir.path()), + QUrl::fromLocalFile(tempDirCanonicalPath), expectedCurrentIndex); } } @@ -782,10 +809,11 @@ void tst_QQuickFileDialogImpl::goUpWhileTextEditHasFocus() { // Open the dialog. FileDialogTestHelper dialogHelper(this, "bindCurrentFolder.qml", {}, - {{ "initialFolder", QUrl::fromLocalFile(tempSubDir.path()) }}); + {{ "initialFolder", QUrl::fromLocalFile(tempSubDirCanonicalPath) }}); OPEN_QUICK_DIALOG(); // See comment in chooseFileViaTextEdit for why we check for this. - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempSubDir.path()), QUrl::fromLocalFile(tempSubSubDir.path()), 0); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempSubDirCanonicalPath), + QUrl::fromLocalFile(tempSubSubDir.path()), 0); // Get the text edit visible with Ctrl+L. QTest::keySequence(dialogHelper.window(), editPathKeySequence); @@ -800,7 +828,7 @@ void tst_QQuickFileDialogImpl::goUpWhileTextEditHasFocus() QVERIFY(QQuickTest::qWaitForPolish(barListView)); QVERIFY(clickButton(breadcrumbBar->upButton())); // The path should have changed to the parent directory. - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path())); + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDirCanonicalPath)); // The text edit should be hidden when it loses focus. QVERIFY(!breadcrumbBar->textField()->hasActiveFocus()); QVERIFY(!breadcrumbBar->textField()->isVisible()); @@ -869,7 +897,8 @@ void tst_QQuickFileDialogImpl::keyAndShortcutHandling() // Open the dialog. FileDialogTestHelper dialogHelper(this, "fileDialog.qml"); OPEN_QUICK_DIALOG(); - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), QUrl::fromLocalFile(tempSubDir.path()), 0); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), + QUrl::fromLocalFile(tempSubDirCanonicalPath), 0); // Get the text edit visible with Ctrl+L. QTest::keySequence(dialogHelper.window(), editPathKeySequence); @@ -983,8 +1012,8 @@ void tst_QQuickFileDialogImpl::changeNameFilters() QTRY_VERIFY(!comboBox->popup()->isVisible()); // Use QTRY_VERIFY2 here to fix a failure on QEMU armv7 (QT_QPA_PLATFORM=offscreen). // Not sure why it's necessary. - QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView, { tempSubDir.path() }, failureMessage), qPrintable(failureMessage)); - + QTRY_VERIFY2(verifyFileDialogDelegates(dialogHelper.fileDialogListView, + { tempSubDirCanonicalPath }, failureMessage), qPrintable(failureMessage)); // Open the popup again. QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, comboBoxCenterPos); QTRY_VERIFY(comboBox->popup()->isOpened()); @@ -1014,8 +1043,8 @@ void tst_QQuickFileDialogImpl::changeNameFiltersAfterChangingFolder() QQuickFileDialogDelegate *subDirDelegate = nullptr; QTRY_VERIFY(findViewDelegateItem(dialogHelper.fileDialogListView, 0, subDirDelegate)); QVERIFY(doubleClickButton(subDirDelegate)); - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir.path())); - COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempSubDir.path())); + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDirCanonicalPath)); + COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempSubDirCanonicalPath)); // Open the ComboBox's popup. const QQuickComboBox *comboBox = dialogHelper.quickDialog->findChild<QQuickComboBox*>(); @@ -1222,10 +1251,10 @@ void tst_QQuickFileDialogImpl::fileMode() // Select the first file (not a directory). QQuickFileDialogDelegate *tempFile1Delegate = nullptr; QTRY_VERIFY(findViewDelegateItem(dialogHelper.fileDialogListView, 1, tempFile1Delegate)); - COMPARE_URL(tempFile1Delegate->file(), QUrl::fromLocalFile(tempFile1->fileName())); + COMPARE_URL(tempFile1Delegate->file(), QUrl::fromLocalFile(tempFile1CanonicalPath)); QVERIFY(clickButton(tempFile1Delegate)); - COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile1->fileName())); - COMPARE_URLS(dialogHelper.dialog->currentFiles(), { QUrl::fromLocalFile(tempFile1->fileName()) }); + COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile1CanonicalPath)); + COMPARE_URLS(dialogHelper.dialog->currentFiles(), { QUrl::fromLocalFile(tempFile1CanonicalPath) }); // All modes should support opening an existing file, so the accept button should be enabled. QVERIFY(dialogHelper.quickDialog->footer()); @@ -1238,21 +1267,21 @@ void tst_QQuickFileDialogImpl::fileMode() // Only the OpenFiles mode should allow multiple files to be selected, however. QQuickFileDialogDelegate *tempFile2Delegate = nullptr; QTRY_VERIFY(findViewDelegateItem(dialogHelper.fileDialogListView, 2, tempFile2Delegate)); - COMPARE_URL(tempFile2Delegate->file(), QUrl::fromLocalFile(tempFile2->fileName())); + COMPARE_URL(tempFile2Delegate->file(), QUrl::fromLocalFile(tempFile2CanonicalPath)); QTest::keyPress(dialogHelper.window(), Qt::Key_Shift); QVERIFY(clickButton(tempFile2Delegate)); QTest::keyRelease(dialogHelper.window(), Qt::Key_Shift); if (fileMode == QQuickFileDialog::OpenFiles) { // currentFile() always points to the first file in the list of selected files. - COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile1->fileName())); + COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile1CanonicalPath)); const QList<QUrl> expectedSelectedFiles = { - QUrl::fromLocalFile(tempFile1->fileName()), QUrl::fromLocalFile(tempFile2->fileName()) }; + QUrl::fromLocalFile(tempFile1CanonicalPath), QUrl::fromLocalFile(tempFile2CanonicalPath) }; COMPARE_URLS(dialogHelper.dialog->currentFiles(), expectedSelectedFiles); } else { // OpenFile and SaveFile dialogs should have tempFile2 selected since it was clicked, // but the shift should do nothing, so tempFile1 should no longer be selected. - COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile2->fileName())); - COMPARE_URLS(dialogHelper.dialog->currentFiles(), { QUrl::fromLocalFile(tempFile2->fileName()) }); + COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile2CanonicalPath)); + COMPARE_URLS(dialogHelper.dialog->currentFiles(), { QUrl::fromLocalFile(tempFile2CanonicalPath) }); } // Get the text edit visible with Ctrl+L. @@ -1275,18 +1304,18 @@ void tst_QQuickFileDialogImpl::fileMode() // For OpenFile(s), we do what Qt Quick Dialogs 1.x did, and restore the previous (valid) dir path. // The currentFile(s) should remain unchanged too. QVERIFY(dialogHelper.dialog->isVisible()); - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path())); - QCOMPARE(breadcrumbBar->textField()->text(), tempDir.path()); + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDirCanonicalPath)); + QCOMPARE(breadcrumbBar->textField()->text(), tempDirCanonicalPath); // Should be unchanged from the last time. if (fileMode == QQuickFileDialog::OpenFiles) { - COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile1->fileName())); + COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile1CanonicalPath)); const QList<QUrl> expectedSelectedFiles = { - QUrl::fromLocalFile(tempFile1->fileName()), QUrl::fromLocalFile(tempFile2->fileName()) }; + QUrl::fromLocalFile(tempFile1CanonicalPath), QUrl::fromLocalFile(tempFile2CanonicalPath) }; COMPARE_URLS(dialogHelper.dialog->currentFiles(), expectedSelectedFiles); } else { // OpenFile - COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile2->fileName())); - COMPARE_URLS(dialogHelper.dialog->currentFiles(), { QUrl::fromLocalFile(tempFile2->fileName()) }); + COMPARE_URL(dialogHelper.dialog->currentFile(), QUrl::fromLocalFile(tempFile2CanonicalPath)); + COMPARE_URLS(dialogHelper.dialog->currentFiles(), { QUrl::fromLocalFile(tempFile2CanonicalPath) }); } } } @@ -1371,7 +1400,7 @@ void tst_QQuickFileDialogImpl::setSelectedFile() QFETCH(QQuickFileDialog::FileMode, fileMode); // Open the dialog. - const auto tempFile1Url = QUrl::fromLocalFile(tempFile1->fileName()); + const auto tempFile1Url = QUrl::fromLocalFile(tempFile1CanonicalPath); const QVariantMap initialProperties = { { "tempFile1Url", QVariant::fromValue(tempFile1Url) }, { "fileMode", QVariant::fromValue(fileMode) } @@ -1384,12 +1413,12 @@ void tst_QQuickFileDialogImpl::setSelectedFile() OPEN_QUICK_DIALOG(); // The selected file should be what we set. - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), tempFile1Url, 1); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), tempFile1Url, 1); // Select the next file in the view by navigating with the down key. // We know it already has focus, as VERIFY_FILE_SELECTED_AND_FOCUSED checks that. QTest::keyClick(dialogHelper.window(), Qt::Key_Down); - const auto tempFile2Url = QUrl::fromLocalFile(tempFile2->fileName()); + const auto tempFile2Url = QUrl::fromLocalFile(tempFile2CanonicalPath); COMPARE_URL(dialogHelper.quickDialog->selectedFile(), tempFile2Url); COMPARE_URL(dialogHelper.dialog->selectedFile(), tempFile2Url); @@ -1402,10 +1431,10 @@ void tst_QQuickFileDialogImpl::setSelectedFile() QCOMPARE(dialogHelper.dialog->result(), QQuickFileDialog::Accepted); // Set a different initial selectedFile and re-open. - dialogHelper.dialog->setSelectedFile(QUrl::fromLocalFile(tempFile1->fileName())); + dialogHelper.dialog->setSelectedFile(QUrl::fromLocalFile(tempFile1CanonicalPath)); QVERIFY(dialogHelper.openDialog()); QTRY_VERIFY(dialogHelper.isQuickDialogOpen()); - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), tempFile1Url, 1); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), tempFile1Url, 1); // Close it. dialogHelper.dialog->close(); @@ -1414,7 +1443,7 @@ void tst_QQuickFileDialogImpl::setSelectedFile() // Try to set an invalid selectedFile; it should be a no-op for modes other than SaveFile, // and the previous selectedFile should still be selected. - const QString invalidPath = tempDir.path() + "/does-not-exist.txt"; + const QString invalidPath = tempDirCanonicalPath + "/does-not-exist.txt"; if (fileMode != QQuickFileDialog::SaveFile) { QTest::ignoreMessage(QtWarningMsg, QRegularExpression(QLatin1String(".*QML FileDialog: Cannot set ") + invalidPath + QLatin1String(" as a selected file because it doesn't exist"))); @@ -1422,7 +1451,7 @@ void tst_QQuickFileDialogImpl::setSelectedFile() dialogHelper.dialog->setSelectedFile(QUrl::fromLocalFile(invalidPath)); QVERIFY(dialogHelper.openDialog()); if (fileMode != QQuickFileDialog::SaveFile) { - VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDir.path()), tempFile1Url, 1); + VERIFY_FILE_SELECTED_AND_FOCUSED(QUrl::fromLocalFile(tempDirCanonicalPath), tempFile1Url, 1); } else { QTRY_COMPARE(dialogHelper.fileDialogListView->currentIndex(), -1); } @@ -1474,7 +1503,7 @@ void tst_QQuickFileDialogImpl::selectExistingFileShouldWarnUserWhenFileModeEqual { FileDialogTestHelper dialogHelper(this, "fileDialog.qml"); dialogHelper.dialog->setFileMode(QQuickFileDialog::SaveFile); - dialogHelper.dialog->setSelectedFile(QUrl::fromLocalFile(tempFile1->fileName())); + dialogHelper.dialog->setSelectedFile(QUrl::fromLocalFile(tempFile1CanonicalPath)); OPEN_QUICK_DIALOG(); QQuickTest::qWaitForPolish(dialogHelper.window()); @@ -1554,8 +1583,8 @@ void tst_QQuickFileDialogImpl::selectExistingFileShouldWarnUserWhenFileModeEqual void tst_QQuickFileDialogImpl::fileNameTextFieldOnlyChangesWhenSelectingFiles() { const auto tempSubFile1Url = QUrl::fromLocalFile(tempSubFile1->fileName()); - const auto tempSubDirUrl = QUrl::fromLocalFile(tempSubDir.path()); - const auto tempFile11Url = QUrl::fromLocalFile(tempFile1->fileName()); + const auto tempSubDirUrl = QUrl::fromLocalFile(tempSubDirCanonicalPath); + const auto tempFile11Url = QUrl::fromLocalFile(tempFile1CanonicalPath); const QVariantMap initialProperties = { { "tempFile1Url", QVariant::fromValue(tempSubFile1Url) }, diff --git a/tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp b/tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp index 01116aa7e9..5450db8e37 100644 --- a/tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp +++ b/tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp @@ -68,13 +68,18 @@ private slots: private: QTemporaryDir tempDir; + QString tempDirCanonicalPath; QScopedPointer<QFile> tempFile1; + QString tempFile1CanonicalPath; QScopedPointer<QFile> tempFile2; + QString tempFile2CanonicalPath; QDir tempSubDir1; + QString tempSubDir1CanonicalPath; QDir tempSubSubDir; QScopedPointer<QFile> tempSubFile1; QScopedPointer<QFile> tempSubFile2; QDir tempSubDir2; + QString tempSubDir2CanonicalPath; QDir oldCurrentDir; }; @@ -88,11 +93,12 @@ void tst_QQuickFolderDialogImpl::initTestCase() QQmlDataTest::initTestCase(); QVERIFY(tempDir.isValid()); + tempDirCanonicalPath = QFileInfo(tempDir.path()).canonicalFilePath(); // QTEST_QUICKCONTROLS_MAIN constructs the test case object once, // and then calls qRun() for each style, and qRun() calls initTestCase(). // So, we need to check if we've already made the temporary directory. // Note that this is only necessary if the test is run with more than one style. - if (!QDir(tempDir.path()).isEmpty()) + if (!QDir(tempDirCanonicalPath).isEmpty()) return; /* @@ -107,39 +113,43 @@ void tst_QQuickFolderDialogImpl::initTestCase() ├── file1.txt └── file2.txt */ - tempSubDir1 = QDir(tempDir.path()); + tempSubDir1 = QDir(tempDirCanonicalPath); QVERIFY2(tempSubDir1.mkdir("sub-dir-1"), qPrintable(QString::fromLatin1( "Failed to make sub-directory \"sub-dir-1\" in %1. Permissions are: %2") - .arg(tempDir.path(), QDebug::toString(QFileInfo(tempDir.path()).permissions())))); + .arg(tempDirCanonicalPath, QDebug::toString(QFileInfo(tempDirCanonicalPath).permissions())))); QVERIFY(tempSubDir1.cd("sub-dir-1")); + tempSubDir1CanonicalPath = tempSubDir1.canonicalPath(); + QVERIFY(!tempSubDir1CanonicalPath.isEmpty()); - tempSubSubDir = QDir(tempSubDir1.path()); + tempSubSubDir = QDir(tempSubDir1CanonicalPath); QVERIFY2(tempSubSubDir.mkdir("sub-sub-dir"), qPrintable(QString::fromLatin1( "Failed to make sub-directory \"sub-sub-dir\" in %1. Permissions are: %2") - .arg(tempSubDir1.path(), QDebug::toString(QFileInfo(tempSubDir1.path()).permissions())))); + .arg(tempSubDir1CanonicalPath, QDebug::toString(QFileInfo(tempSubDir1CanonicalPath).permissions())))); QVERIFY(tempSubSubDir.cd("sub-sub-dir")); - tempSubFile1.reset(new QFile(tempSubDir1.path() + "/sub-file1.txt")); + tempSubFile1.reset(new QFile(tempSubDir1CanonicalPath + "/sub-file1.txt")); QVERIFY(tempSubFile1->open(QIODevice::ReadWrite)); - tempSubFile2.reset(new QFile(tempSubDir1.path() + "/sub-file2.txt")); + tempSubFile2.reset(new QFile(tempSubDir1CanonicalPath + "/sub-file2.txt")); QVERIFY(tempSubFile2->open(QIODevice::ReadWrite)); - tempSubDir2 = QDir(tempDir.path()); + tempSubDir2 = QDir(tempDirCanonicalPath); QVERIFY2(tempSubDir2.mkdir("sub-dir-2"), qPrintable(QString::fromLatin1( "Failed to make sub-directory \"sub-dir-2\" in %1. Permissions are: %2") - .arg(tempDir.path(), QDebug::toString(QFileInfo(tempDir.path()).permissions())))); + .arg(tempDirCanonicalPath, QDebug::toString(QFileInfo(tempDirCanonicalPath).permissions())))); QVERIFY(tempSubDir2.cd("sub-dir-2")); + tempSubDir2CanonicalPath = tempSubDir2.canonicalPath(); + QVERIFY(!tempSubDir2CanonicalPath.isEmpty()); - tempFile1.reset(new QFile(tempDir.path() + "/file1.txt")); + tempFile1.reset(new QFile(tempDirCanonicalPath + "/file1.txt")); QVERIFY(tempFile1->open(QIODevice::ReadWrite)); - tempFile2.reset(new QFile(tempDir.path() + "/file2.txt")); + tempFile2.reset(new QFile(tempDirCanonicalPath + "/file2.txt")); QVERIFY(tempFile2->open(QIODevice::ReadWrite)); // Ensure that each test starts off in the temporary directory. oldCurrentDir = QDir::current(); - QDir::setCurrent(tempDir.path()); + QDir::setCurrent(tempDirCanonicalPath); } void tst_QQuickFolderDialogImpl::cleanupTestCase() @@ -171,9 +181,9 @@ void tst_QQuickFolderDialogImpl::defaults() QVERIFY(quickDialog); QTRY_VERIFY(quickDialog->isOpened()); QVERIFY(quickDialog); - COMPARE_URL(quickDialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1.path())); + COMPARE_URL(quickDialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1CanonicalPath)); COMPARE_URL(quickDialog->currentFolder(), QUrl::fromLocalFile(QDir().absolutePath())); - COMPARE_URL(dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1.path())); + COMPARE_URL(dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1CanonicalPath)); COMPARE_URL(dialog->currentFolder(), QUrl::fromLocalFile(QDir().absolutePath())); QCOMPARE(quickDialog->title(), QString()); } @@ -223,13 +233,13 @@ void tst_QQuickFolderDialogImpl::chooseFolderViaStandardButtons() QVERIFY(folderDialogListView); QQuickFileDialogDelegate *delegate = nullptr; QTRY_VERIFY(findViewDelegateItem(folderDialogListView, 1, delegate)); - COMPARE_URL(delegate->file(), QUrl::fromLocalFile(tempSubDir2.path())); + COMPARE_URL(delegate->file(), QUrl::fromLocalFile(tempSubDir2CanonicalPath)); QVERIFY(clickButton(delegate)); // currentFolder shouldn't change just from a single click. - COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempDir.path())); - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path())); - COMPARE_URL(dialogHelper.quickDialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir2.path())); - COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir2.path())); + COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempDirCanonicalPath)); + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDirCanonicalPath)); + COMPARE_URL(dialogHelper.quickDialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir2CanonicalPath)); + COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir2CanonicalPath)); // Only selectedFile-related signals should be emitted. QCOMPARE(signalHelper.dialogSelectedFolderChangedSpy.size(), 1); QCOMPARE(signalHelper.quickDialogSelectedFolderChangedSpy.size(), 1); @@ -243,8 +253,8 @@ void tst_QQuickFolderDialogImpl::chooseFolderViaStandardButtons() QQuickAbstractButton* openButton = findDialogButton(dialogButtonBox, "Open"); QVERIFY(openButton); QVERIFY(clickButton(openButton)); - COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir2.path())); - COMPARE_URL(dialogHelper.quickDialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir2.path())); + COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir2CanonicalPath)); + COMPARE_URL(dialogHelper.quickDialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir2CanonicalPath)); QCOMPARE(signalHelper.dialogSelectedFolderChangedSpy.size(), 1); QCOMPARE(signalHelper.quickDialogSelectedFolderChangedSpy.size(), 1); QCOMPARE(signalHelper.dialogCurrentFolderChangedSpy.size(), 0); @@ -259,11 +269,11 @@ void tst_QQuickFolderDialogImpl::bindCurrentFolder_data() QTest::addColumn<QUrl>("expectedFolder"); QTest::addColumn<QStringList>("expectedVisibleFiles"); - const auto currentDirUrl = QUrl::fromLocalFile(QDir::current().path()); - const auto tempSubDirUrl = QUrl::fromLocalFile(tempSubDir1.path()); + const auto currentDirUrl = QUrl::fromLocalFile(QDir::current().canonicalPath()); + const auto tempSubDirUrl = QUrl::fromLocalFile(tempSubDir1CanonicalPath); const auto tempSubFile1Url = QUrl::fromLocalFile(tempSubFile1->fileName()); - const QStringList currentDirFiles = { tempSubDir1.path(), tempSubDir2.path() }; + const QStringList currentDirFiles = { tempSubDir1CanonicalPath, tempSubDir2CanonicalPath }; const QStringList tempSubDirFiles = { tempSubSubDir.path() }; // Setting the folder to "sub-dir-1" should result in "sub-sub-dir" being visible. @@ -317,9 +327,9 @@ void tst_QQuickFolderDialogImpl::changeFolderViaDoubleClick() QVERIFY(folderDialogListView); QQuickFileDialogDelegate *delegate = nullptr; QTRY_VERIFY(findViewDelegateItem(folderDialogListView, 1, delegate)); - COMPARE_URL(delegate->file(), QUrl::fromLocalFile(tempSubDir2.path())) + COMPARE_URL(delegate->file(), QUrl::fromLocalFile(tempSubDir2CanonicalPath)) QVERIFY(doubleClickButton(delegate)); - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2.path())) + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2CanonicalPath)) COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl()); // selectedFolder is set to the folder when clicked and then set to an empty URL after // the double click. @@ -354,13 +364,13 @@ void tst_QQuickFolderDialogImpl::changeFolderViaTextEdit() QCOMPARE(breadcrumbBar->textField()->selectedText(), breadcrumbBar->textField()->text()); // Enter the path to the folder in the text edit. - enterText(dialogHelper.window(), tempSubDir2.path()); - QCOMPARE(breadcrumbBar->textField()->text(), tempSubDir2.path()); + enterText(dialogHelper.window(), tempSubDir2CanonicalPath); + QCOMPARE(breadcrumbBar->textField()->text(), tempSubDir2CanonicalPath); // Hit enter to accept. QTest::keyClick(dialogHelper.window(), Qt::Key_Return); - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2.path())); - COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2.path())); + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2CanonicalPath)); + COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2CanonicalPath)); // We changed into a directory with no folders, so the selected folder should be invalid. COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl()); COMPARE_URL(dialogHelper.quickDialog->selectedFolder(), QUrl()); @@ -382,19 +392,19 @@ void tst_QQuickFolderDialogImpl::changeFolderViaEnter() QTRY_VERIFY(dialogHelper.isQuickDialogOpen()); // The first delegate in the view should be selected and have focus. - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path())); + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDirCanonicalPath)); auto folderDialogListView = dialogHelper.quickDialog->findChild<QQuickListView*>("folderDialogListView"); QVERIFY(folderDialogListView); QQuickFileDialogDelegate *subDir1Delegate = nullptr; QTRY_VERIFY(findViewDelegateItem(folderDialogListView, 0, subDir1Delegate)); - COMPARE_URL(subDir1Delegate->file(), QUrl::fromLocalFile(tempSubDir1.path())); + COMPARE_URL(subDir1Delegate->file(), QUrl::fromLocalFile(tempSubDir1CanonicalPath)); QVERIFY(subDir1Delegate->hasActiveFocus()); // Select the delegate by pressing enter. const FolderDialogSignalHelper signalHelper(dialogHelper); QVERIFY2(signalHelper.errorMessage.isEmpty(), signalHelper.errorMessage); QTest::keyClick(dialogHelper.window(), Qt::Key_Return); - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir1.path())); + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir1CanonicalPath)); COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubSubDir.path())); QCOMPARE(signalHelper.dialogSelectedFolderChangedSpy.size(), 1); QCOMPARE(signalHelper.quickDialogSelectedFolderChangedSpy.size(), 1); @@ -448,7 +458,7 @@ void tst_QQuickFolderDialogImpl::goUp() { // Open the dialog, starting off in "sub-dir-1". FolderDialogTestHelper dialogHelper(this, "bindCurrentFolder.qml", {}, - {{ "initialFolder", QUrl::fromLocalFile(tempSubDir1.path()) }}); + {{ "initialFolder", QUrl::fromLocalFile(tempSubDir1CanonicalPath) }}); QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage()); QVERIFY(dialogHelper.waitForWindowActive()); QVERIFY(dialogHelper.openDialog()); @@ -462,9 +472,9 @@ void tst_QQuickFolderDialogImpl::goUp() if (QQuickTest::qIsPolishScheduled(barListView)) QVERIFY(QQuickTest::qWaitForPolish(barListView)); QVERIFY(clickButton(breadcrumbBar->upButton())); - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path())); + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDirCanonicalPath)); // The previous directory that we were in should now be selected (matches e.g. Windows and Ubuntu). - COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1.path())); + COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1CanonicalPath)); auto folderDialogListView = dialogHelper.quickDialog->findChild<QQuickListView*>("folderDialogListView"); QVERIFY(folderDialogListView); QQuickFileDialogDelegate *subDirDelegate = nullptr; @@ -474,17 +484,17 @@ void tst_QQuickFolderDialogImpl::goUp() // Go up a directory via the keyboard shortcut. const auto goUpKeySequence = QKeySequence(Qt::ALT | Qt::Key_Up); QTest::keySequence(dialogHelper.window(), goUpKeySequence); - QDir tempParentDir(tempDir.path()); + QDir tempParentDir(tempDirCanonicalPath); QVERIFY(tempParentDir.cdUp()); COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempParentDir.path())); - COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempDir.path())); + COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempDirCanonicalPath)); } void tst_QQuickFolderDialogImpl::goUpWhileTextEditHasFocus() { // Open the dialog, starting off in "sub-dir-1". FolderDialogTestHelper dialogHelper(this, "bindCurrentFolder.qml", {}, - {{ "initialFolder", QUrl::fromLocalFile(tempSubDir1.path()) }}); + {{ "initialFolder", QUrl::fromLocalFile(tempSubDir1CanonicalPath) }}); QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage()); QVERIFY(dialogHelper.waitForWindowActive()); QVERIFY(dialogHelper.openDialog()); @@ -499,7 +509,7 @@ void tst_QQuickFolderDialogImpl::goUpWhileTextEditHasFocus() QVERIFY(QQuickTest::qWaitForPolish(barListView)); QVERIFY(clickButton(breadcrumbBar->upButton())); // The path should have changed to the parent directory. - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path())); + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDirCanonicalPath)); // The text edit should be hidden when it loses focus. QVERIFY(!breadcrumbBar->textField()->hasActiveFocus()); QVERIFY(!breadcrumbBar->textField()->isVisible()); @@ -574,7 +584,7 @@ void tst_QQuickFolderDialogImpl::clickOnBreadcrumb() { // Open the dialog, starting off in "sub-dir-1". FolderDialogTestHelper dialogHelper(this, "bindCurrentFolder.qml", {}, - {{ "initialFolder", QUrl::fromLocalFile(tempSubDir1.path()) }}); + {{ "initialFolder", QUrl::fromLocalFile(tempSubDir1CanonicalPath) }}); QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage()); QVERIFY(dialogHelper.waitForWindowActive()); QVERIFY(dialogHelper.openDialog()); @@ -595,10 +605,10 @@ void tst_QQuickFolderDialogImpl::clickOnBreadcrumb() QTRY_VERIFY(findViewDelegateItem(breadcrumbBarListView, breadcrumbBarListView->count() - 3, breadcrumbDelegate)); QVERIFY(clickButton(breadcrumbDelegate)); - QCOMPARE(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempDir.path())); - QCOMPARE(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path())); - QCOMPARE(dialogHelper.quickDialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1.path())); - QCOMPARE(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1.path())); + QCOMPARE(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempDirCanonicalPath)); + QCOMPARE(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDirCanonicalPath)); + QCOMPARE(dialogHelper.quickDialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1CanonicalPath)); + QCOMPARE(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1CanonicalPath)); } void tst_QQuickFolderDialogImpl::keyAndShortcutHandling() @@ -771,13 +781,13 @@ void tst_QQuickFolderDialogImpl::itemsDisabledWhenNecessary() { // Open the dialog. FolderDialogTestHelper dialogHelper(this, "bindCurrentFolder.qml", {}, - {{ "initialFolder", QUrl::fromLocalFile(tempSubDir2.path()) }}); + {{ "initialFolder", QUrl::fromLocalFile(tempSubDir2CanonicalPath) }}); QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage()); QVERIFY(dialogHelper.waitForWindowActive()); QVERIFY(dialogHelper.openDialog()); QTRY_VERIFY(dialogHelper.isQuickDialogOpen()); - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2.path())); - COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2.path())); + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2CanonicalPath)); + COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2CanonicalPath)); // We opened it in a folder that has no files, so the Open button should be disabled. QVERIFY(dialogHelper.quickDialog->footer()); @@ -792,8 +802,8 @@ void tst_QQuickFolderDialogImpl::itemsDisabledWhenNecessary() QVERIFY(breadcrumbBar); QVERIFY(clickButton(breadcrumbBar->upButton())); QCOMPARE(openButton->isEnabled(), true); - COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path())); - COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempDir.path())); + COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDirCanonicalPath)); + COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempDirCanonicalPath)); // Get the text edit visible with Ctrl+L. The Open button should now be disabled. const auto editPathKeySequence = QKeySequence(Qt::CTRL | Qt::Key_L); diff --git a/tests/auto/quickwidgets/qquickwidget/BLACKLIST b/tests/auto/quickwidgets/qquickwidget/BLACKLIST index 095e9ee484..f5ca6141f6 100644 --- a/tests/auto/quickwidgets/qquickwidget/BLACKLIST +++ b/tests/auto/quickwidgets/qquickwidget/BLACKLIST @@ -3,3 +3,4 @@ opensuse-42.3 opensuse-leap [enterLeave] macos +windows diff --git a/tests/baseline/scenegraph/scenegrabber/CMakeLists.txt b/tests/baseline/scenegraph/scenegrabber/CMakeLists.txt index 1ace458afb..18c983f087 100644 --- a/tests/baseline/scenegraph/scenegrabber/CMakeLists.txt +++ b/tests/baseline/scenegraph/scenegrabber/CMakeLists.txt @@ -1,6 +1,12 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(qmlscenegrabber LANGUAGES C CXX) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + ##################################################################### ## qmlscenegrabber Binary: ##################################################################### diff --git a/tests/benchmarks/quickcontrols/creationtime/CMakeLists.txt b/tests/benchmarks/quickcontrols/creationtime/CMakeLists.txt index b719e8148f..f877fedb1f 100644 --- a/tests/benchmarks/quickcontrols/creationtime/CMakeLists.txt +++ b/tests/benchmarks/quickcontrols/creationtime/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_creationtime LANGUAGES C CXX ASM) + project(tst_creationtime LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/benchmarks/quickcontrols/objectcount/CMakeLists.txt b/tests/benchmarks/quickcontrols/objectcount/CMakeLists.txt index 65fdf74a2c..251b60059f 100644 --- a/tests/benchmarks/quickcontrols/objectcount/CMakeLists.txt +++ b/tests/benchmarks/quickcontrols/objectcount/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_objectcount LANGUAGES C CXX ASM) + project(tst_objectcount LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/buttons/CMakeLists.txt b/tests/manual/quickcontrols/buttons/CMakeLists.txt index 048645b43f..31d01abc7c 100644 --- a/tests/manual/quickcontrols/buttons/CMakeLists.txt +++ b/tests/manual/quickcontrols/buttons/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(buttons LANGUAGES C CXX ASM) + project(buttons LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/fonts/CMakeLists.txt b/tests/manual/quickcontrols/fonts/CMakeLists.txt index 476b7f1a7a..4ef977e518 100644 --- a/tests/manual/quickcontrols/fonts/CMakeLists.txt +++ b/tests/manual/quickcontrols/fonts/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(fonts LANGUAGES C CXX ASM) + project(fonts LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/gifs/CMakeLists.txt b/tests/manual/quickcontrols/gifs/CMakeLists.txt index 674806e145..deb982dc18 100644 --- a/tests/manual/quickcontrols/gifs/CMakeLists.txt +++ b/tests/manual/quickcontrols/gifs/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tst_gifs LANGUAGES C CXX ASM) + project(tst_gifs LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/headerview/CMakeLists.txt b/tests/manual/quickcontrols/headerview/CMakeLists.txt index fd00f693c8..1973f1a2fd 100644 --- a/tests/manual/quickcontrols/headerview/CMakeLists.txt +++ b/tests/manual/quickcontrols/headerview/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(headerview LANGUAGES C CXX ASM) + project(headerview LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/material/CMakeLists.txt b/tests/manual/quickcontrols/material/CMakeLists.txt index 8c18341bbe..232771b88e 100644 --- a/tests/manual/quickcontrols/material/CMakeLists.txt +++ b/tests/manual/quickcontrols/material/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(material LANGUAGES C CXX ASM) + project(material LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/qquickdialog/CMakeLists.txt b/tests/manual/quickcontrols/qquickdialog/CMakeLists.txt index 232dae7ffa..d2322ed934 100644 --- a/tests/manual/quickcontrols/qquickdialog/CMakeLists.txt +++ b/tests/manual/quickcontrols/qquickdialog/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(qquickdialog LANGUAGES C CXX ASM) + project(qquickdialog LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/screenshots/CMakeLists.txt b/tests/manual/quickcontrols/screenshots/CMakeLists.txt index 32d465b9d4..ece360c1c0 100644 --- a/tests/manual/quickcontrols/screenshots/CMakeLists.txt +++ b/tests/manual/quickcontrols/screenshots/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(screenshots LANGUAGES C CXX ASM) + project(screenshots LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/styles-cover-flow/CMakeLists.txt b/tests/manual/quickcontrols/styles-cover-flow/CMakeLists.txt index b2fa66bf44..8412eeab4d 100644 --- a/tests/manual/quickcontrols/styles-cover-flow/CMakeLists.txt +++ b/tests/manual/quickcontrols/styles-cover-flow/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(styles-cover-flow LANGUAGES C CXX ASM) + project(styles-cover-flow LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/styles/CMakeLists.txt b/tests/manual/quickcontrols/styles/CMakeLists.txt index 479fcfdc22..05aebfe89f 100644 --- a/tests/manual/quickcontrols/styles/CMakeLists.txt +++ b/tests/manual/quickcontrols/styles/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(styles LANGUAGES C CXX ASM) + project(styles LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/systemtrayicon/CMakeLists.txt b/tests/manual/quickcontrols/systemtrayicon/CMakeLists.txt index b8913ec986..4a415c767a 100644 --- a/tests/manual/quickcontrols/systemtrayicon/CMakeLists.txt +++ b/tests/manual/quickcontrols/systemtrayicon/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(systemtrayicon LANGUAGES C CXX ASM) + project(systemtrayicon LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/testbench/CMakeLists.txt b/tests/manual/quickcontrols/testbench/CMakeLists.txt index 9cbf26f324..5ed82ac800 100644 --- a/tests/manual/quickcontrols/testbench/CMakeLists.txt +++ b/tests/manual/quickcontrols/testbench/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(testbench LANGUAGES C CXX ASM) + project(testbench LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickcontrols/viewinqwidget/CMakeLists.txt b/tests/manual/quickcontrols/viewinqwidget/CMakeLists.txt index 7deba0df55..848d2171a0 100644 --- a/tests/manual/quickcontrols/viewinqwidget/CMakeLists.txt +++ b/tests/manual/quickcontrols/viewinqwidget/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(viewinqwidget LANGUAGES C CXX ASM) + project(viewinqwidget LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/quickdialogs/dialogs/CMakeLists.txt b/tests/manual/quickdialogs/dialogs/CMakeLists.txt index 65d641f333..d2a20d96e9 100644 --- a/tests/manual/quickdialogs/dialogs/CMakeLists.txt +++ b/tests/manual/quickdialogs/dialogs/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(dialogs LANGUAGES C CXX ASM) + project(dialogs LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/righttoleft/layoutdirection/CMakeLists.txt b/tests/manual/righttoleft/layoutdirection/CMakeLists.txt index 7c1e38e79a..f442f17012 100644 --- a/tests/manual/righttoleft/layoutdirection/CMakeLists.txt +++ b/tests/manual/righttoleft/layoutdirection/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(layoutdirection LANGUAGES C CXX ASM) + project(layoutdirection LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/righttoleft/layoutmirroring/CMakeLists.txt b/tests/manual/righttoleft/layoutmirroring/CMakeLists.txt index 69fb0a05a8..cc8a04693a 100644 --- a/tests/manual/righttoleft/layoutmirroring/CMakeLists.txt +++ b/tests/manual/righttoleft/layoutmirroring/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(layoutmirroring LANGUAGES C CXX ASM) + project(layoutmirroring LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/righttoleft/textalignment/CMakeLists.txt b/tests/manual/righttoleft/textalignment/CMakeLists.txt index fa0c90f79c..f04cb76184 100644 --- a/tests/manual/righttoleft/textalignment/CMakeLists.txt +++ b/tests/manual/righttoleft/textalignment/CMakeLists.txt @@ -3,7 +3,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(textalignment LANGUAGES C CXX ASM) + project(textalignment LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/tableview/abstracttablemodel/CMakeLists.txt b/tests/manual/tableview/abstracttablemodel/CMakeLists.txt index 7f49c14567..7c6c62d61c 100644 --- a/tests/manual/tableview/abstracttablemodel/CMakeLists.txt +++ b/tests/manual/tableview/abstracttablemodel/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tableview_abstracttablemodel LANGUAGES C CXX ASM) + project(tableview_abstracttablemodel LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/tableview/listmodel/CMakeLists.txt b/tests/manual/tableview/listmodel/CMakeLists.txt index 0f5c27ca87..ffadc2ea47 100644 --- a/tests/manual/tableview/listmodel/CMakeLists.txt +++ b/tests/manual/tableview/listmodel/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tableview_listmodel LANGUAGES C CXX ASM) + project(tableview_listmodel LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/tableview/storagemodel/CMakeLists.txt b/tests/manual/tableview/storagemodel/CMakeLists.txt index 11ca5971ba..589cf7f3bc 100644 --- a/tests/manual/tableview/storagemodel/CMakeLists.txt +++ b/tests/manual/tableview/storagemodel/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(tableview_storage LANGUAGES C CXX ASM) + project(tableview_storage LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/tableview/tablemodel/form/CMakeLists.txt b/tests/manual/tableview/tablemodel/form/CMakeLists.txt index 1943079f9f..f355677a44 100644 --- a/tests/manual/tableview/tablemodel/form/CMakeLists.txt +++ b/tests/manual/tableview/tablemodel/form/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(form LANGUAGES C CXX ASM) + project(form LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/tableview/tablemodel/json/CMakeLists.txt b/tests/manual/tableview/tablemodel/json/CMakeLists.txt index 279fae77b6..aeb6253447 100644 --- a/tests/manual/tableview/tablemodel/json/CMakeLists.txt +++ b/tests/manual/tableview/tablemodel/json/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(json LANGUAGES C CXX ASM) + project(json LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() diff --git a/tests/manual/treeview/sidebyside/CMakeLists.txt b/tests/manual/treeview/sidebyside/CMakeLists.txt index 818cb73bab..7907735cd7 100644 --- a/tests/manual/treeview/sidebyside/CMakeLists.txt +++ b/tests/manual/treeview/sidebyside/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) - project(treeview_sidebyside LANGUAGES C CXX ASM) + project(treeview_sidebyside LANGUAGES C CXX) find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) endif() |
