aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/core/qqmlsettings/CMakeLists.txt2
-rw-r--r--tests/auto/core/qqmlstandardpaths/CMakeLists.txt2
-rw-r--r--tests/auto/core/qqmlsysteminformation/CMakeLists.txt2
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp29
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp2
-rw-r--r--tests/auto/qml/qml/tst_qml.cpp35
-rw-r--r--tests/auto/qml/qmlcachegen/data/crashes/buggyFixSuggestion.qml25
-rw-r--r--tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp57
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Categorizer.qml60
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/mergeSideEffects.qml20
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp48
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp4
-rw-r--r--tests/auto/qml/qmllint/data/InlineComponentSearchInfiniteLoop_Main.qml6
-rw-r--r--tests/auto/qml/qmllint/data/InlineComponentSearchInfiniteLoop_Other.qml8
-rw-r--r--tests/auto/qml/qmllint/data/locationUnqualifiedLookupAssign.qml7
-rw-r--r--tests/auto/qml/qmllint/data/requiredPropertyInGroupedPropertyScope.qml10
-rw-r--r--tests/auto/qml/qmllint/tst_qmllint.cpp17
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.cpp2
-rw-r--r--tests/auto/qml/qqmlbinding/data/bindingInDeadContext.qml18
-rw-r--r--tests/auto/qml/qqmlbinding/data/deleteStashedObject.qml51
-rw-r--r--tests/auto/qml/qqmlbinding/data/multiValueTypeBinding.qml16
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp72
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp3
-rw-r--r--tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp10
-rw-r--r--tests/auto/qml/qqmlecmascript/data/jittedJavaScriptExpressionDoesNotCrashOnExceptionBeingThrown.qml40
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp35
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp4
-rw-r--r--tests/auto/qml/qqmllanguage/data/WithInline.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.11.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.11.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/urlWithFragment.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp14
-rw-r--r--tests/auto/qml/qqmllistmodel/data/valuesOfInnerList.qml17
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp19
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.errors.txt1
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.qml3
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp22
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp12
-rw-r--r--tests/auto/qml/qqmlsettings/data/coexistence/Core.qml5
-rw-r--r--tests/auto/qml/qqmlsettings/data/coexistence/Labs.qml8
-rw-r--r--tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp13
-rw-r--r--tests/auto/qml/qqmltablemodel/data/TestModel.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/TestUtils.js20
-rw-r--r--tests/auto/qml/qqmltypeloader/data/qobjectSingletonUser.qml7
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp61
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp2
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp2
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/BLACKLIST4
-rw-r--r--tests/auto/quick/pointerhandlers/mousearea_interop/tst_mousearea_interop.cpp9
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp11
-rw-r--r--tests/auto/quick/qquickanimations/data/animationInstantiator.qml40
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp11
-rw-r--r--tests/auto/quick/qquickapplication/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp3
-rw-r--r--tests/auto/quick/qquicklistview/BLACKLIST3
-rw-r--r--tests/auto/quick/qquickloader/data/invalidateContext.qml28
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp56
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/data/inFlickableWithScale.qml27
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp30
-rw-r--r--tests/auto/quick/qquickshape/data/changeElementsImperatively.qml21
-rw-r--r--tests/auto/quick/qquickshape/tst_qquickshape.cpp8
-rw-r--r--tests/auto/quick/qquicktext/BLACKLIST3
-rw-r--r--tests/auto/quick/qquicktextedit/data/readOnly.qml30
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp42
-rw-r--r--tests/auto/quick/qquicktreeview/data/editdelegate.qml91
-rw-r--r--tests/auto/quick/qquicktreeview/testmodel.cpp9
-rw-r--r--tests/auto/quick/qquicktreeview/testmodel.h3
-rw-r--r--tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp334
-rw-r--r--tests/auto/quickcontrols/accessibility/data/accessibleName/button.qml10
-rw-r--r--tests/auto/quickcontrols/accessibility/data/accessibleName/button2.qml10
-rw-r--r--tests/auto/quickcontrols/accessibility/data/accessibleName/button3.qml11
-rw-r--r--tests/auto/quickcontrols/accessibility/tst_accessibility.cpp41
-rw-r--r--tests/auto/quickcontrols/controls/basic/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/fusion/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/imagine/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/ios/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/macos/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/material/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/universal/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/controls/windows/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/cursor/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/customization/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/designer/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/focus/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/font/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/palette/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/platform/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/pointerhandlers/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/pressandhold/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp2
-rw-r--r--tests/auto/quickcontrols/qquickcolor/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickcontainer/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickcontainer/data/skipReorderContentModelItem.qml57
-rw-r--r--tests/auto/quickcontrols/qquickcontainer/tst_qquickcontainer.cpp31
-rw-r--r--tests/auto/quickcontrols/qquickcontrol/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickdrawer/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickheaderview/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickiconimage/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickiconlabel/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickiconlabel/data/childPaintOrder.qml32
-rw-r--r--tests/auto/quickcontrols/qquickiconlabel/tst_qquickiconlabel.cpp20
-rw-r--r--tests/auto/quickcontrols/qquickimaginestyle/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickmaterialstyle/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml29
-rw-r--r--tests/auto/quickcontrols/qquickmaterialstyleconf/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/animationOnHeight.qml70
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/customMenuUseRepeaterAsTheContentItem.qml1
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/shortcutInNestedSubMenuAction.qml30
-rw-r--r--tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp38
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/data/clearMenus.qml35
-rw-r--r--tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp11
-rw-r--r--tests/auto/quickcontrols/qquickninepatchimage/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickoverlay/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickpopup/data/propagateTouchEvents.qml17
-rw-r--r--tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp38
-rw-r--r--tests/auto/quickcontrols/qquickstyle/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquicktextarea/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquicktextfield/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquicktreeviewdelegate/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickuniversalstyle/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickuniversalstyleconf/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/revisions/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/sanity/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/snippets/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/styleimports/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/styleimportscompiletimematerial/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/styleimportscompiletimeqmlonly/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/translation/CMakeLists.txt2
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp231
-rw-r--r--tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp110
-rw-r--r--tests/auto/quickwidgets/qquickwidget/BLACKLIST1
138 files changed, 2238 insertions, 267 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