diff options
Diffstat (limited to 'tests')
42 files changed, 802 insertions, 166 deletions
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations index 75fdd1cb0c..7c671040a3 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -249,8 +249,6 @@ built-ins/String/prototype/toLocaleLowerCase/special_casing_conditional.js fails built-ins/String/prototype/toLowerCase/Final_Sigma_U180E.js fails built-ins/String/prototype/toLowerCase/special_casing_conditional.js fails built-ins/TypedArray/prototype/constructor.js fails -built-ins/TypedArray/prototype/fill/fill-values-conversion-operations-consistent-nan.js fails -built-ins/TypedArray/prototype/slice/bit-precision.js fails built-ins/TypedArray/prototype/sort/arraylength-internal.js fails built-ins/TypedArray/prototype/sort/comparefn-call-throws.js fails built-ins/TypedArray/prototype/sort/comparefn-calls.js fails diff --git a/tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml b/tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml new file mode 100644 index 0000000000..bbf978936f --- /dev/null +++ b/tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml @@ -0,0 +1,12 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick + +Rectangle { + enum AxisAlignment { + Bottom = 0, + Left = 1, + Right = 2 + } +} diff --git a/tests/auto/qml/qmlformat/data/enumWithValues.qml b/tests/auto/qml/qmlformat/data/enumWithValues.qml new file mode 100644 index 0000000000..2dbe7fbac5 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/enumWithValues.qml @@ -0,0 +1,12 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick + +Rectangle{ +enum AxisAlignment{ +Bottom = 0, +Left = 1, +Right = 2 +} +} diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp index 5050444796..5e3c8cbd9d 100644 --- a/tests/auto/qml/qmlformat/tst_qmlformat.cpp +++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp @@ -366,6 +366,9 @@ void TestQmlformat::testFormat_data() QTest::newRow("javascriptBlock") << "javascriptBlock.qml" << "javascriptBlock.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("enumWithValues") + << "enumWithValues.qml" + << "enumWithValues.formatted.qml" << QStringList{} << RunOption::OnCopy; } void TestQmlformat::testFormat() diff --git a/tests/auto/qml/qmllint/data/something.qml b/tests/auto/qml/qmllint/data/something.qml new file mode 100644 index 0000000000..38998f606d --- /dev/null +++ b/tests/auto/qml/qmllint/data/something.qml @@ -0,0 +1,2 @@ +import ModuleInImportPath +A {} diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index d16d9cb2a1..dcff6af431 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -97,10 +97,13 @@ private Q_SLOTS: void testLineEndings(); void ignoreSettingsNotCommandLineOptions(); + void backslashedQmldirPath(); + #if QT_CONFIG(library) void testPlugin(); void quickPlugin(); #endif + private: enum DefaultImportOption { NoDefaultImports, UseDefaultImports }; enum ContainOption { StringNotContained, StringContained }; @@ -2153,5 +2156,14 @@ void TestQmllint::ignoreSettingsNotCommandLineOptions() QCOMPARE(output, QString()); } +void TestQmllint::backslashedQmldirPath() +{ + const QString qmldirPath + = testFile(u"ImportPath/ModuleInImportPath/qmldir"_s).replace('/', QDir::separator()); + const QString output = runQmllint( + testFile(u"something.qml"_s), true, QStringList{ u"-i"_s, qmldirPath }); + QVERIFY(output.isEmpty()); +} + QTEST_MAIN(TestQmllint) #include "tst_qmllint.moc" diff --git a/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired1.qml b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired1.qml new file mode 100644 index 0000000000..f549e851a3 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired1.qml @@ -0,0 +1,6 @@ +pragma Singleton +import QtQml + +QtObject { + required property int i +} diff --git a/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired2.qml b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired2.qml new file mode 100644 index 0000000000..1f9e7e3a42 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired2.qml @@ -0,0 +1,8 @@ +pragma Singleton +import QtQml + +QtObject { + property QtObject o: QtObject { + required property int i + } +} diff --git a/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/qmldir b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/qmldir new file mode 100644 index 0000000000..46e397ca76 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/qmldir @@ -0,0 +1,4 @@ +module SingletonWithRequiredProperties + +singleton SingletonWithRequired1 1.0 SingletonWithRequired1.qml +singleton SingletonWithRequired2 1.0 SingletonWithRequired2.qml diff --git a/tests/auto/qml/qqmllanguage/data/nestedVectors.qml b/tests/auto/qml/qqmllanguage/data/nestedVectors.qml new file mode 100644 index 0000000000..0bcea52133 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/nestedVectors.qml @@ -0,0 +1,27 @@ +import Test +import QtQml + +NestedVectors { + id: self + + property var list1 + + Component.onCompleted: { + list1 = self.getList() + + let list2 = [] + let data1 = [] + data1.push(2) + data1.push(3) + data1.push(4) + + let data2 = [] + data2.push(5) + data2.push(6) + + list2.push(data1) + list2.push(data2) + + self.setList(list2) + } +} diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index ffff0a6979..2fce6567be 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -174,6 +174,7 @@ void registerTypes() qmlRegisterTypesAndRevisions<NonSingleton>("EnumScopeTest", 1); qmlRegisterTypesAndRevisions<EnumProviderSingletonQml>("EnumScopeTest", 1); + qmlRegisterTypesAndRevisions<NestedVectors>("Test", 1); } QVariant myCustomVariantTypeConverter(const QString &data) diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index bcf02c1cf9..6d5c9b5b38 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -2942,4 +2942,36 @@ public: } }; +class NestedVectors : public QObject +{ + Q_OBJECT + QML_ELEMENT +public: + NestedVectors(QObject *parent = nullptr) : QObject(parent) + { + std::vector<int> data; + data.push_back(1); + data.push_back(2); + data.push_back(3); + m_list.push_back(data); + data.clear(); + data.push_back(4); + data.push_back(5); + m_list.push_back(data); + } + + Q_INVOKABLE std::vector<std::vector<int>> getList() + { + return m_list; + } + + Q_INVOKABLE void setList(std::vector<std::vector<int>> list) + { + m_list = list; + } + +private: + std::vector<std::vector<int>> m_list; +}; + #endif // TESTTYPES_H diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 7231b977ce..aca6029bf8 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -249,6 +249,8 @@ private slots: void compositeSingletonSelectors(); void compositeSingletonRegistered(); void compositeSingletonCircular(); + void compositeSingletonRequiredProperties(); + void compositeSingletonRequiredProperties_data(); void singletonsHaveContextAndEngine(); @@ -454,6 +456,8 @@ private slots: void typedObjectList(); + void nestedVectors(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -4907,6 +4911,36 @@ void tst_qqmllanguage::compositeSingletonCircular() QCOMPARE(o->property("value").toInt(), 2); } +void tst_qqmllanguage::compositeSingletonRequiredProperties() +{ + QFETCH(QString, warning); + QFETCH(QString, singletonName); + QQmlEngine engine; + engine.addImportPath(dataDirectory()); + { + QTest::ignoreMessage(QtMsgType::QtWarningMsg, qPrintable(warning)); + std::unique_ptr<QObject> singleton {engine.singletonInstance<QObject *>( + "SingletonWithRequiredProperties", + singletonName + )}; + QVERIFY(!singleton); + } +} + +void tst_qqmllanguage::compositeSingletonRequiredProperties_data() +{ + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("singletonName"); + + QString warning1 = testFileUrl("SingletonWithRequiredProperties/SingletonWithRequired1.qml").toString() + + ":5:5: Required property i was not initialized"; + QString warning2 = testFileUrl("SingletonWithRequiredProperties/SingletonWithRequired2.qml").toString() + + ":6:9: Required property i was not initialized"; + + QTest::addRow("toplevelRequired") << warning1 << "SingletonWithRequired1"; + QTest::addRow("subObjectRequired") << warning2 << "SingletonWithRequired2"; +} + void tst_qqmllanguage::singletonsHaveContextAndEngine() { QObject *qmlSingleton = nullptr; @@ -8655,6 +8689,26 @@ void tst_qqmllanguage::typedObjectList() QVERIFY(list.at(&list, 0) != nullptr); } +void tst_qqmllanguage::nestedVectors() +{ + QQmlEngine e; + QQmlComponent c(&e, testFileUrl("nestedVectors.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + NestedVectors *n = qobject_cast<NestedVectors *>(o.data()); + QVERIFY(n); + + const std::vector<std::vector<int>> expected1 { { 1, 2, 3 }, { 4, 5 } }; + const QVariant list1 = n->property("list1"); + QCOMPARE(list1.metaType(), QMetaType::fromType<std::vector<std::vector<int>>>()); + QCOMPARE(list1.value<std::vector<std::vector<int>>>(), expected1); + + const std::vector<std::vector<int>> expected2 { { 2, 3, 4 }, { 5, 6 } }; + QCOMPARE(n->getList(), expected2); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/qml/qv4estable/tst_qv4estable.cpp b/tests/auto/qml/qv4estable/tst_qv4estable.cpp index 45df62b23e..7d137ae7d2 100644 --- a/tests/auto/qml/qv4estable/tst_qv4estable.cpp +++ b/tests/auto/qml/qv4estable/tst_qv4estable.cpp @@ -18,7 +18,7 @@ void tst_qv4estable::checkRemoveAvoidsHeapBufferOverflow() QV4::ESTable estable; // Fill the ESTable with values so it is at max capacity. - QCOMPARE_EQ(estable.m_capacity, 8); + QCOMPARE_EQ(estable.m_capacity, 8U); for (uint i = 0; i < estable.m_capacity; ++i) { estable.set(QV4::Value::fromUInt32(i), QV4::Value::fromUInt32(i)); } @@ -27,8 +27,8 @@ void tst_qv4estable::checkRemoveAvoidsHeapBufferOverflow() for (uint i = 0; i < estable.m_capacity; ++i) { QVERIFY(estable.m_keys[i].sameValueZero(QV4::Value::fromUInt32(i))); } - QCOMPARE_EQ(estable.m_capacity, 8); - QCOMPARE_EQ(estable.m_size, 8); + QCOMPARE_EQ(estable.m_capacity, 8U); + QCOMPARE_EQ(estable.m_size, 8U); // Remove the first item from the set to verify that asan does not trip. // Relies on the CI platform propagating asan flag to all tests. diff --git a/tests/auto/qmldom/domdata/domitem/crashes/lambda.qml b/tests/auto/qmldom/domdata/domitem/crashes/lambda.qml new file mode 100644 index 0000000000..85f696f9c8 --- /dev/null +++ b/tests/auto/qmldom/domdata/domitem/crashes/lambda.qml @@ -0,0 +1,7 @@ +import QtQuick.Controls + +Action { + onTriggered: foo(Bla.Bar, function() { + console.log("Hello") + }) +} diff --git a/tests/auto/qmldom/domdata/domitem/crashes/templateStrings.qml b/tests/auto/qmldom/domdata/domitem/crashes/templateStrings.qml new file mode 100644 index 0000000000..feb5646496 --- /dev/null +++ b/tests/auto/qmldom/domdata/domitem/crashes/templateStrings.qml @@ -0,0 +1,10 @@ +import QtQuick + + +Item { + property string verbatim1: 'A "verbatim" string!' + property string verbatim2: "A 'verbatim' string\u2757" + property string verbatim3: `400 + 300 is ${400 + 300}. + +mutliline` +} diff --git a/tests/auto/qmldom/domitem/tst_qmldomitem.h b/tests/auto/qmldom/domitem/tst_qmldomitem.h index 184dc8e5a9..367387168c 100644 --- a/tests/auto/qmldom/domitem/tst_qmldomitem.h +++ b/tests/auto/qmldom/domitem/tst_qmldomitem.h @@ -2813,6 +2813,12 @@ private slots: QTest::addRow("inactiveVisitorMarkerCrash") << baseDir + u"/inactiveVisitorMarkerCrash.qml"_s; + + QTest::addRow("templateStrings") + << baseDir + u"/crashes/templateStrings.qml"_s; + + QTest::addRow("lambda") + << baseDir + u"/crashes/lambda.qml"_s; } void crashes() { diff --git a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml index 03c186fdb4..d31a0b0fb8 100644 --- a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml +++ b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml @@ -1579,6 +1579,49 @@ Item { compare(rootRect.item1.width, 100) } + //--------------------------- + // Layout with negative size + Component { + id: negativeSize_Component + Item { + id: rootItem + width: 0 + height: 0 + // default width x height: (0 x 0) + RowLayout { + spacing: 0 + anchors.fill: parent + anchors.leftMargin: 1 // since parent size == (0 x 0), it causes layout size + anchors.bottomMargin: 1 // to become (-1, -1) + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + } + } + } + + function test_negativeSize() { + let rootItem = createTemporaryObject(negativeSize_Component, container) + let rowLayout = rootItem.children[0] + let item = rowLayout.children[0] + + const arr = [7, 1, 7, 0] + arr.forEach((n) => { + rootItem.width = n + rootItem.height = n + + // n === 0 is special: It will cause the layout to have a + // negative size. In this case it will simply not rearrange its + // child (and leave it at its previous size, 6) + const expectedItemExtent = n === 0 ? 6 : n - 1 + + compare(item.width, expectedItemExtent) + compare(item.height, expectedItemExtent) + }); + } + + //--------------------------- Component { id: rowlayoutWithTextItems_Component diff --git a/tests/auto/quick/qquicktextedit/data/hAlignVisual.qml b/tests/auto/quick/qquicktextedit/data/hAlignVisual.qml index 1280a655f0..f532a9aa36 100644 --- a/tests/auto/quick/qquicktextedit/data/hAlignVisual.qml +++ b/tests/auto/quick/qquicktextedit/data/hAlignVisual.qml @@ -4,11 +4,11 @@ Rectangle { width: 200 height: 100 - Text { - objectName: "textItem" + TextEdit { + objectName: "textEditItem" text: "AA\nBBBBBBB\nCCCCCCCCCCCCCCCC" anchors.centerIn: parent - horizontalAlignment: Text.AlignLeft + horizontalAlignment: TextEdit.AlignLeft font.pointSize: 12 font.family: "Times New Roman" } diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index 6442c49212..a4e6cc3a31 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -245,7 +245,6 @@ private: void simulateKey(QWindow *, int key, Qt::KeyboardModifiers modifiers = {}); bool isMainFontFixed(); - static bool hasWindowActivation(); QStringList standard; QStringList richText; @@ -986,8 +985,8 @@ void tst_qquicktextedit::hAlignVisual() view.showNormal(); QVERIFY(QTest::qWaitForWindowExposed(&view)); - QQuickText *text = view.rootObject()->findChild<QQuickText*>("textItem"); - QVERIFY(text != nullptr); + QQuickTextEdit *text = view.rootObject()->findChild<QQuickTextEdit*>("textEditItem"); + QVERIFY(text); // Try to check whether alignment works by checking the number of black // pixels in the thirds of the grabbed image. @@ -1014,7 +1013,7 @@ void tst_qquicktextedit::hAlignVisual() } { // HCenter Align - text->setHAlign(QQuickText::AlignHCenter); + text->setHAlign(QQuickTextEdit::AlignHCenter); QImage image = view.grabWindow(); const int left = numberOfNonWhitePixels(centeredSection1, centeredSection2, image); const int mid = numberOfNonWhitePixels(centeredSection2, centeredSection3, image); @@ -1024,7 +1023,7 @@ void tst_qquicktextedit::hAlignVisual() } { // Right Align - text->setHAlign(QQuickText::AlignRight); + text->setHAlign(QQuickTextEdit::AlignRight); QImage image = view.grabWindow(); const int left = numberOfNonWhitePixels(centeredSection1, centeredSection2, image); const int mid = numberOfNonWhitePixels(centeredSection2, centeredSection3, image); @@ -1036,36 +1035,36 @@ void tst_qquicktextedit::hAlignVisual() text->setWidth(200); { - // Left Align + // Right Align QImage image = view.grabWindow(); - int x = qCeil(text->implicitWidth() * view.devicePixelRatio()); - int left = numberOfNonWhitePixels(0, x, image); - int right = numberOfNonWhitePixels(x, image.width() - x, image); - QVERIFY2(left > 0, msgNotGreaterThan(left, 0).constData()); - QCOMPARE(right, 0); + const int x = image.width() - qCeil(text->implicitWidth() * view.devicePixelRatio()); + const int left = numberOfNonWhitePixels(0, x, image); + const int right = numberOfNonWhitePixels(x, image.width() - x, image); + QCOMPARE(left, 0); + QVERIFY2(right > 0, msgNotGreaterThan(left, 0).constData()); } { // HCenter Align - text->setHAlign(QQuickText::AlignHCenter); + text->setHAlign(QQuickTextEdit::AlignHCenter); QImage image = view.grabWindow(); - int x1 = qFloor(image.width() - text->implicitWidth() * view.devicePixelRatio()) / 2; - int x2 = image.width() - x1; - int left = numberOfNonWhitePixels(0, x1, image); - int mid = numberOfNonWhitePixels(x1, x2 - x1, image); - int right = numberOfNonWhitePixels(x2, image.width() - x2, image); + const int x1 = qFloor(image.width() - text->implicitWidth() * view.devicePixelRatio()) / 2; + const int x2 = image.width() - x1; + const int left = numberOfNonWhitePixels(0, x1, image); + const int mid = numberOfNonWhitePixels(x1, x2 - x1, image); + const int right = numberOfNonWhitePixels(x2, image.width(), image); QCOMPARE(left, 0); QVERIFY2(mid > 0, msgNotGreaterThan(left, 0).constData()); QCOMPARE(right, 0); } { - // Right Align - text->setHAlign(QQuickText::AlignRight); + // Left Align + text->setHAlign(QQuickTextEdit::AlignLeft); QImage image = view.grabWindow(); - int x = image.width() - qCeil(text->implicitWidth() * view.devicePixelRatio()); - int left = numberOfNonWhitePixels(0, x, image); - int right = numberOfNonWhitePixels(x, image.width() - x, image); - QCOMPARE(left, 0); - QVERIFY2(right > 0, msgNotGreaterThan(left, 0).constData()); + const int x = qCeil(text->implicitWidth() * view.devicePixelRatio()); + const int left = numberOfNonWhitePixels(0, x, image); + const int right = numberOfNonWhitePixels(x, image.width() - x, image); + QVERIFY2(left > 0, msgNotGreaterThan(left, 0).constData()); + QCOMPARE(right, 0); } } @@ -3397,11 +3396,6 @@ bool tst_qquicktextedit::isMainFontFixed() return ret; } -bool tst_qquicktextedit::hasWindowActivation() -{ - return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)); -} - void tst_qquicktextedit::textInput() { QQuickView view(testFileUrl("inputMethodEvent.qml")); @@ -6651,8 +6645,8 @@ void tst_qquicktextedit::touchscreenDoesNotSelect() void tst_qquicktextedit::touchscreenSetsFocusAndMovesCursor() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION + QQuickView window; QVERIFY(QQuickTest::showView(window, testFileUrl("twoInAColumn.qml"))); window.requestActivate(); diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index b7e689e147..8f8442544f 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -6,6 +6,7 @@ #include <QtQuickTestUtils/private/qmlutils_p.h> #include <QtQuickTestUtils/private/testhttpserver_p.h> #include <QtQuickTestUtils/private/viewtestutils_p.h> +#include <QtQuickTestUtils/private/visualtestutils_p.h> #include <private/qinputmethod_p.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> @@ -213,7 +214,6 @@ private: #if QT_CONFIG(shortcut) void simulateKeys(QWindow *window, const QKeySequence &sequence); #endif - static bool hasWindowActivation(); QQmlEngine engine; QStringList standard; @@ -239,11 +239,6 @@ void tst_qquicktextinput::simulateKeys(QWindow *window, const QList<Key> &keys) } } -bool tst_qquicktextinput::hasWindowActivation() -{ - return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)); -} - #if QT_CONFIG(shortcut) void tst_qquicktextinput::simulateKeys(QWindow *window, const QKeySequence &sequence) @@ -7201,8 +7196,8 @@ void tst_qquicktextinput::touchscreenDoesNotSelect() void tst_qquicktextinput::touchscreenSetsFocusAndMovesCursor() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION + QQuickView window; QVERIFY(QQuickTest::showView(window, testFileUrl("twoInAColumn.qml"))); window.requestActivate(); diff --git a/tests/auto/quick/qquickwindow/data/visibilityDoesntClobberWindowState.qml b/tests/auto/quick/qquickwindow/data/visibilityDoesntClobberWindowState.qml new file mode 100644 index 0000000000..af899ec5dd --- /dev/null +++ b/tests/auto/quick/qquickwindow/data/visibilityDoesntClobberWindowState.qml @@ -0,0 +1,5 @@ +import QtQuick + +Window { + +} diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index adfc2668a5..97ae290e40 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -549,6 +549,8 @@ private slots: void visibleVsVisibility_data(); void visibleVsVisibility(); + void visibilityDoesntClobberWindowState(); + void eventTypes(); private: @@ -4139,6 +4141,40 @@ void tst_qquickwindow::visibleVsVisibility() QCOMPARE(window->isVisible(), expectVisible); } +void tst_qquickwindow::visibilityDoesntClobberWindowState() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("visibilityDoesntClobberWindowState.qml")); + QObject *created = component.create(); + QScopedPointer<QObject> cleanup(created); + QVERIFY(created); + + QQuickWindow *window = qobject_cast<QQuickWindow*>(created); + QVERIFY(window); + + window->showMaximized(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + QCOMPARE(window->windowState(), Qt::WindowMaximized); + + window->setProperty("visible", false); + window->setProperty("visible", true); + + QVERIFY(QTest::qWaitForWindowExposed(window)); + QCOMPARE(window->windowState(), Qt::WindowMaximized); + + EventFilter eventFilter; + window->installEventFilter(&eventFilter); + window->setProperty("visibility", QWindow::FullScreen); + QTRY_VERIFY(eventFilter.events.contains(QEvent::WindowStateChange)); + QCOMPARE(window->windowState(), Qt::WindowFullScreen); + + eventFilter.events.clear(); + window->setWindowState(Qt::WindowMaximized); + QTRY_VERIFY(eventFilter.events.contains(QEvent::WindowStateChange)); + QTRY_COMPARE(window->windowState(), Qt::WindowMaximized); +} + void tst_qquickwindow::eventTypes() { QQmlEngine engine; diff --git a/tests/auto/quickcontrols/controls/data/combobox/shader.frag b/tests/auto/quickcontrols/controls/data/combobox/shader.frag new file mode 100644 index 0000000000..fbbef218e6 --- /dev/null +++ b/tests/auto/quickcontrols/controls/data/combobox/shader.frag @@ -0,0 +1,19 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#version 440 + +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; +layout(binding = 1) uniform sampler2D source; // this item + +layout(std140, binding = 0) uniform buf { + float qt_Opacity; // inherited opacity of this item +}; + + +void main() { + vec4 p = texture(source, qt_TexCoord0); + lowp float g = dot(p.xyz, vec3(0.344, 0.5, 0.156)); + fragColor = vec4(g, g, g, p.a) * qt_Opacity; +} diff --git a/tests/auto/quickcontrols/controls/data/combobox/shader.frag.qsb b/tests/auto/quickcontrols/controls/data/combobox/shader.frag.qsb Binary files differnew file mode 100644 index 0000000000..b86ce9a76e --- /dev/null +++ b/tests/auto/quickcontrols/controls/data/combobox/shader.frag.qsb diff --git a/tests/auto/quickcontrols/controls/data/tst_combobox.qml b/tests/auto/quickcontrols/controls/data/tst_combobox.qml index 9f852e29e4..4dfe53fcb0 100644 --- a/tests/auto/quickcontrols/controls/data/tst_combobox.qml +++ b/tests/auto/quickcontrols/controls/data/tst_combobox.qml @@ -74,16 +74,7 @@ TestCase { objectName: "ShaderFX" width: rect.width height: rect.height - fragmentShader: " - uniform lowp sampler2D source; // this item - uniform lowp float qt_Opacity; // inherited opacity of this item - varying highp vec2 qt_TexCoord0; - void main() { - lowp vec4 p = texture2D(source, qt_TexCoord0); - lowp float g = dot(p.xyz, vec3(0.344, 0.5, 0.156)); - gl_FragColor = vec4(g, g, g, p.a) * qt_Opacity; - }" - + fragmentShader: "combobox/shader.frag.qsb" } } } @@ -2004,11 +1995,16 @@ TestCase { compare(currentIndexSpy.count, 1) } + readonly property font testFont: ({ + family: "Arial", + pixelSize: 12 + }) + Component { - id: appFontTextFieldComponent + id: fixedFontTextFieldComponent TextField { objectName: "appFontTextField" - font: Qt.application.font + font: testCase.testFont // We don't want the background's implicit width to interfere with our tests, // which are about implicit width of the contentItem of ComboBox, which is by default TextField. background: null @@ -2016,14 +2012,14 @@ TestCase { } Component { - id: appFontContentItemComboBoxComponent + id: fixedFontContentItemComboBoxComponent ComboBox { // Override the contentItem so that the font doesn't vary between styles. contentItem: TextField { objectName: "appFontContentItemTextField" // We do this just to be extra sure that the font never comes from the control, - // as we want it to match that of the TextField in the appFontTextFieldComponent. - font: Qt.application.font + // as we want it to match that of the TextField in the fixedFontTextFieldComponent. + font: testCase.testFont background: null } } @@ -2077,14 +2073,14 @@ TestCase { function test_implicitContentWidthPolicy_ContentItemImplicitWidth() { // Set ContentItemImplicitWidth and ensure that implicitContentWidth is as wide as the current item // by comparing it against the implicitWidth of an identical TextField - let control = createTemporaryObject(appFontContentItemComboBoxComponent, testCase, { + let control = createTemporaryObject(fixedFontContentItemComboBoxComponent, testCase, { model: ["Short", "Kinda long"], implicitContentWidthPolicy: ComboBox.ContentItemImplicitWidth }) verify(control) compare(control.implicitContentWidthPolicy, ComboBox.ContentItemImplicitWidth) - let textField = createTemporaryObject(appFontTextFieldComponent, testCase) + let textField = createTemporaryObject(fixedFontTextFieldComponent, testCase) verify(textField) // Don't set any text on textField because we're not accounting for the widest // text here, so we want to compare it against an empty TextField. @@ -2103,14 +2099,14 @@ TestCase { } function test_implicitContentWidthPolicy_WidestText(data) { - let control = createTemporaryObject(appFontContentItemComboBoxComponent, testCase, { + let control = createTemporaryObject(fixedFontContentItemComboBoxComponent, testCase, { model: data.model, implicitContentWidthPolicy: ComboBox.WidestText }) verify(control) compare(control.implicitContentWidthPolicy, ComboBox.WidestText) - let textField = createTemporaryObject(appFontTextFieldComponent, testCase) + let textField = createTemporaryObject(fixedFontTextFieldComponent, testCase) verify(textField) textField.text = "Kinda long" // Note that we don't need to change the current index here, as the implicitContentWidth @@ -2137,7 +2133,7 @@ TestCase { // Changes in font should result in the implicitContentWidth being updated. textField.font.pixelSize *= 2 // We have to change the contentItem's font size manually since we break the - // style's binding to the control's font when we set Qt.application.font to it. + // style's binding to the control's font when we set the fixed font on it. control.contentItem.font.pixelSize *= 2 control.font.pixelSize *= 2 compare(Math.ceil(control.implicitContentWidth), Math.ceil(textField.implicitWidth)) @@ -2148,14 +2144,14 @@ TestCase { } function test_implicitContentWidthPolicy_WidestTextWhenCompleted(data) { - let control = createTemporaryObject(appFontContentItemComboBoxComponent, testCase, { + let control = createTemporaryObject(fixedFontContentItemComboBoxComponent, testCase, { model: data.model, implicitContentWidthPolicy: ComboBox.WidestTextWhenCompleted }) verify(control) compare(control.implicitContentWidthPolicy, ComboBox.WidestTextWhenCompleted) - let textField = createTemporaryObject(appFontTextFieldComponent, testCase) + let textField = createTemporaryObject(fixedFontTextFieldComponent, testCase) verify(textField) textField.text = "Kinda long" compare(Math.ceil(control.implicitContentWidth), Math.ceil(textField.implicitWidth)) diff --git a/tests/auto/quickcontrols/controls/data/tst_splitview.qml b/tests/auto/quickcontrols/controls/data/tst_splitview.qml index 1690691492..3f5975a437 100644 --- a/tests/auto/quickcontrols/controls/data/tst_splitview.qml +++ b/tests/auto/quickcontrols/controls/data/tst_splitview.qml @@ -74,20 +74,19 @@ TestCase { // Note that the indices mentioned here account for handles; they do not // match the indices reported by QQuickSplitView's logging categories. compare(item.x, expectedGeometry.x, "Mismatch in actual vs expected x value of " - + itemType + " at index " + typeSpecificIndex + context) + + itemType + " " + item + " at index " + typeSpecificIndex + context) compare(item.y, expectedGeometry.y, "Mismatch in actual vs expected y value of " - + itemType + " at index " + typeSpecificIndex + context) + + itemType + " " + item + " at index " + typeSpecificIndex + context) compare(item.width, expectedGeometry.width, "Mismatch in actual vs expected width value of " - + itemType + " at index " + typeSpecificIndex + context) + + itemType + " " + item + " at index " + typeSpecificIndex + context) compare(item.height, expectedGeometry.height, "Mismatch in actual vs expected height value of " - + itemType + " at index " + typeSpecificIndex + context) + + itemType + " " + item + " at index " + typeSpecificIndex + context) } } property real defaultHorizontalHandleWidth: 10 property real defaultVerticalHandleHeight: 10 - Component { id: signalSpyComponent SignalSpy {} @@ -96,14 +95,14 @@ TestCase { Component { id: handleComponent Rectangle { - objectName: "handle" + objectName: `handle ${x},${y} ${width}x${height} visible: ${visible}` implicitWidth: defaultHorizontalHandleWidth implicitHeight: defaultVerticalHandleHeight color: "#444" Text { - objectName: "handleText_" + text - text: parent.x + "," + parent.y + " " + parent.width + "x" + parent.height + objectName: text + "_Text" + text: parent.objectName color: "white" anchors.centerIn: parent rotation: 90 @@ -2676,4 +2675,88 @@ TestCase { verify(!firstHandle.SplitHandle.pressed) compare(firstItem.width, 125) } + + Component { + id: hiddenItemComponent + + SplitView { + anchors.fill: parent + handle: handleComponent + orientation: Qt.Horizontal + + component SplitItem: Rectangle { + objectName: labelText + + SplitView.preferredWidth: 50 + SplitView.fillHeight: true + + required property string labelText + + Text { + anchors.fill: parent + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: `${parent.labelText} - width: ${parent.width.toFixed(2)}` + } + } + + SplitItem { + color: "blue" + labelText: "View 1" + } + SplitItem { + color: "red" + labelText: "View 2 (hidden)" + visible: false + } + SplitItem { + color: "purple" + labelText: "View 3" + } + SplitItem { + color: "yellow" + labelText: "View 4" + } + } + } + + function test_resizeHiddenItem() { + let control = createTemporaryObject(hiddenItemComponent, testCase) + verify(control) + + const standardItemWidth = 50 + let expectedGeometries = [ + // First item. + { x: 0, y: 0, width: standardItemWidth, height: control.height }, + // First handle. + { x: standardItemWidth, y: 0, width: defaultHorizontalHandleWidth, height: control.height }, + // The second item and its handle are hidden. + { hidden: true }, + { hidden: true }, + // Third item. + { x: standardItemWidth + defaultHorizontalHandleWidth, y: 0, width: standardItemWidth, height: control.height }, + // Third handle. + { x: (standardItemWidth * 2) + defaultHorizontalHandleWidth, y: 0, width: defaultHorizontalHandleWidth, height: control.height }, + // Fourth item. + { x: (standardItemWidth * 2) + (defaultHorizontalHandleWidth * 2), y: 0, + width: control.width - (standardItemWidth * 2) - (defaultHorizontalHandleWidth * 2), height: control.height } + ] + compareSizes(control, expectedGeometries, "before dragging handle") + + // Drag the third handle to the right. + let handles = findHandles(control) + let thirdHandle = handles[2] + // The third (index 4 here) item should get one pixel bigger, and the fourth one pixel smaller. + ++expectedGeometries[4].width + ++expectedGeometries[5].x // handle + ++expectedGeometries[6].x + --expectedGeometries[6].width + // Use individual events rather than mouseDrag because that will move it past the drag threshold, + // which we don't want, since we only want to move by 1 pixel. + mousePress(thirdHandle) + mouseMove(thirdHandle, thirdHandle.width / 2 + 1, thirdHandle.height / 2, 16) + mouseRelease(thirdHandle) + compareSizes(control, expectedGeometries, "after dragging handle") + } } diff --git a/tests/auto/quickcontrols/focus/tst_focus.cpp b/tests/auto/quickcontrols/focus/tst_focus.cpp index c6a82ebaba..34305bc599 100644 --- a/tests/auto/quickcontrols/focus/tst_focus.cpp +++ b/tests/auto/quickcontrols/focus/tst_focus.cpp @@ -29,6 +29,7 @@ public: tst_focus(); private slots: + void init() override; void initTestCase() override; void navigation_data(); @@ -50,8 +51,14 @@ tst_focus::tst_focus() { } +void tst_focus::init() +{ + QTest::failOnWarning(QRegularExpression(".?")); +} + void tst_focus::initTestCase() { + SKIP_IF_NO_WINDOW_ACTIVATION QQuickStyle::setStyle("Basic"); QQmlDataTest::initTestCase(); } diff --git a/tests/auto/quickcontrols/palette/data/comboBoxPopupWithApplicationWindow.qml b/tests/auto/quickcontrols/palette/data/comboBoxPopupWithApplicationWindow.qml new file mode 100644 index 0000000000..436d3cdad6 --- /dev/null +++ b/tests/auto/quickcontrols/palette/data/comboBoxPopupWithApplicationWindow.qml @@ -0,0 +1,32 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls + +ApplicationWindow { + width: 400 + height: 400 + + property alias topLevelComboBox: topLevelComboBox + property alias popup: popup + property alias comboBoxInPopup: comboBoxInPopup + + ComboBox { + id: topLevelComboBox + model: ["ONE", "TWO", "THREE"] + } + + Popup { + id: popup + width: 200 + height: 200 + visible: true + palette.window: "red" + + ComboBox { + id: comboBoxInPopup + model: ["ONE", "TWO", "THREE"] + } + } +} diff --git a/tests/auto/quickcontrols/palette/data/comboBoxPopupWithWindow.qml b/tests/auto/quickcontrols/palette/data/comboBoxPopupWithWindow.qml new file mode 100644 index 0000000000..d806f30d01 --- /dev/null +++ b/tests/auto/quickcontrols/palette/data/comboBoxPopupWithWindow.qml @@ -0,0 +1,33 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Window +import QtQuick.Controls + +Window { + width: 400 + height: 400 + + property alias topLevelComboBox: topLevelComboBox + property alias popup: popup + property alias comboBoxInPopup: comboBoxInPopup + + ComboBox { + id: topLevelComboBox + model: ["ONE", "TWO", "THREE"] + } + + Popup { + id: popup + width: 200 + height: 200 + visible: true + palette.window: "red" + + ComboBox { + id: comboBoxInPopup + model: ["ONE", "TWO", "THREE"] + } + } +} diff --git a/tests/auto/quickcontrols/palette/tst_palette.cpp b/tests/auto/quickcontrols/palette/tst_palette.cpp index 5109ad0f8f..75ee023bb7 100644 --- a/tests/auto/quickcontrols/palette/tst_palette.cpp +++ b/tests/auto/quickcontrols/palette/tst_palette.cpp @@ -7,9 +7,11 @@ #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> #include <QtQuickTestUtils/private/qmlutils_p.h> +#include <QtQuickTestUtils/private/visualtestutils_p.h> #include <QtQuickControlsTestUtils/private/controlstestutils_p.h> #include <QtQuick/private/qquickitem_p.h> #include <QtQuickTemplates2/private/qquickapplicationwindow_p.h> +#include <QtQuickTemplates2/private/qquickcombobox_p.h> #include <QtQuickTemplates2/private/qquickcontrol_p.h> #include <QtQuickTemplates2/private/qquickcontrol_p_p.h> #include <QtQuickTemplates2/private/qquickpopup_p.h> @@ -19,6 +21,7 @@ #include <QtQuickControls2/qquickstyle.h> #include <QSignalSpy> +using namespace QQuickVisualTestUtils; using namespace QQuickControlsTestUtils; class tst_palette : public QQmlDataTest @@ -52,6 +55,9 @@ private slots: void resetColor(); void updateBindingPalette(); + + void comboBoxPopup_data(); + void comboBoxPopup(); }; tst_palette::tst_palette() @@ -551,6 +557,61 @@ void tst_palette::updateBindingPalette() QCOMPARE(windowPalette->buttonText(), customPalette->buttonText()); } +void tst_palette::comboBoxPopup_data() +{ + QTest::addColumn<QString>("style"); + QTest::addColumn<QString>("qmlFilePath"); + + QTest::newRow("Window, Basic") << "Basic" << "comboBoxPopupWithWindow.qml"; + QTest::newRow("ApplicationWindow, Basic") << "Basic" << "comboBoxPopupWithApplicationWindow.qml"; + QTest::newRow("Window, Fusion") << "Fusion" << "comboBoxPopupWithWindow.qml"; + QTest::newRow("ApplicationWindow, Fusion") << "Fusion" << "comboBoxPopupWithApplicationWindow.qml"; +} + +// Unlike regular popups, which should inherit their palette from the window and not the parent popup, +// combo box popups should inherit their palette from the combo box itself. +void tst_palette::comboBoxPopup() +{ + QFETCH(QString, style); + QFETCH(QString, qmlFilePath); + + qmlClearTypeRegistrations(); + QQuickStyle::setStyle(style); + + QQuickApplicationHelper helper(this, qmlFilePath); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + const auto *windowPalette = window->property("palette").value<QQuickPalette *>(); + QVERIFY(windowPalette); + + const auto *popup = window->property("popup").value<QQuickPopup *>(); + QVERIFY(popup); + const auto *popupBackground = popup->background(); + QCOMPARE(popupBackground->property("color"), QColorConstants::Red); + QCOMPARE(popupBackground->property("palette").value<QQuickPalette*>()->toQPalette().window().color(), + QColorConstants::Red); + + // This has the default palette. + const auto *topLevelComboBox = window->property("topLevelComboBox").value<QQuickComboBox *>(); + QVERIFY(topLevelComboBox); + const auto *topLevelComboBoxBackground = topLevelComboBox->popup()->background(); + QCOMPARE_NE(topLevelComboBoxBackground->property("color"), QColorConstants::Red); + QCOMPARE_NE(topLevelComboBoxBackground->property("palette").value<QQuickPalette*>()->toQPalette().window().color(), + QColorConstants::Red); + + // The popup that this combo box is in has its window role set to red, + // so the combo box's popup background should be red too. + const auto *comboBoxInPopup = window->property("comboBoxInPopup").value<QQuickComboBox *>(); + QVERIFY(comboBoxInPopup); + const auto *comboBoxInPopupBackground = comboBoxInPopup->popup()->background(); + QCOMPARE(comboBoxInPopupBackground->property("color"), QColorConstants::Red); + QCOMPARE(comboBoxInPopupBackground->property("palette").value<QQuickPalette*>()->toQPalette().window().color(), + QColorConstants::Red); +} + QTEST_MAIN(tst_palette) #include "tst_palette.moc" diff --git a/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp b/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp index ff0b4418d2..1d25ffeed6 100644 --- a/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp +++ b/tests/auto/quickcontrols/qquickapplicationwindow/tst_qquickapplicationwindow.cpp @@ -278,6 +278,10 @@ void tst_QQuickApplicationWindow::implicitFill() void tst_QQuickApplicationWindow::attachedProperties() { + if (QGuiApplication::platformName().startsWith(QLatin1String("eglfs"), Qt::CaseInsensitive)) + { + QSKIP("This test uses multiple windows and it crashes on EGLFS because of that"); + } QQmlEngine engine; QQmlComponent component(&engine); component.loadUrl(testFileUrl("attachedProperties.qml")); diff --git a/tests/auto/quickcontrols/qquickdrawer/tst_qquickdrawer.cpp b/tests/auto/quickcontrols/qquickdrawer/tst_qquickdrawer.cpp index cefb494c6f..80e5bcd0d7 100644 --- a/tests/auto/quickcontrols/qquickdrawer/tst_qquickdrawer.cpp +++ b/tests/auto/quickcontrols/qquickdrawer/tst_qquickdrawer.cpp @@ -1051,8 +1051,7 @@ void tst_QQuickDrawer::interactive_data() void tst_QQuickDrawer::interactive() { - if (!(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QFETCH(QString, source); QQuickControlsApplicationHelper helper(this, source); diff --git a/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp b/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp index a80aec5ca1..d101f50a7e 100644 --- a/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp +++ b/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp @@ -87,9 +87,6 @@ private slots: void customMenuCullItems(); void customMenuUseRepeaterAsTheContentItem(); void invalidUrlInImgTag(); - -private: - static bool hasWindowActivation(); }; tst_QQuickMenu::tst_QQuickMenu() @@ -97,11 +94,6 @@ tst_QQuickMenu::tst_QQuickMenu() { } -bool tst_QQuickMenu::hasWindowActivation() -{ - return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)); -} - void tst_QQuickMenu::defaults() { QQuickControlsApplicationHelper helper(this, QLatin1String("applicationwindow.qml")); @@ -146,8 +138,7 @@ void tst_QQuickMenu::count() void tst_QQuickMenu::mouse() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION if ((QGuiApplication::platformName() == QLatin1String("offscreen")) || (QGuiApplication::platformName() == QLatin1String("minimal"))) @@ -278,8 +269,7 @@ void tst_QQuickMenu::pressAndHold() void tst_QQuickMenu::contextMenuKeyboard() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) QSKIP("This platform only allows tab focus for text controls"); @@ -468,8 +458,7 @@ void tst_QQuickMenu::contextMenuKeyboard() // QTBUG-70181 void tst_QQuickMenu::disabledMenuItemKeyNavigation() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) QSKIP("This platform only allows tab focus for text controls"); @@ -535,8 +524,7 @@ void tst_QQuickMenu::disabledMenuItemKeyNavigation() void tst_QQuickMenu::mnemonics() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION #ifdef Q_OS_MACOS QSKIP("Mnemonics are not used on macOS"); @@ -593,8 +581,7 @@ void tst_QQuickMenu::mnemonics() void tst_QQuickMenu::menuButton() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) QSKIP("This platform only allows tab focus for text controls"); @@ -648,8 +635,7 @@ void tst_QQuickMenu::addItem() void tst_QQuickMenu::menuSeparator() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, QLatin1String("menuSeparator.qml")); QVERIFY2(helper.ready, helper.failureMessage()); @@ -1037,8 +1023,7 @@ void tst_QQuickMenu::actions() #if QT_CONFIG(shortcut) void tst_QQuickMenu::actionShortcuts() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, QLatin1String("actionShortcuts.qml")); QVERIFY2(helper.ready, helper.failureMessage()); @@ -1332,8 +1317,7 @@ void tst_QQuickMenu::subMenuKeyboard_data() void tst_QQuickMenu::subMenuKeyboard() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QFETCH(bool, cascade); QFETCH(bool, mirrored); @@ -1461,8 +1445,7 @@ void tst_QQuickMenu::subMenuDisabledKeyboard_data() // QTBUG-69540 void tst_QQuickMenu::subMenuDisabledKeyboard() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QFETCH(bool, cascade); QFETCH(bool, mirrored); @@ -2050,8 +2033,7 @@ void tst_QQuickMenu::menuItemWidthAfterRetranslate() void tst_QQuickMenu::giveMenuItemFocusOnButtonPress() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, QLatin1String("giveMenuItemFocusOnButtonPress.qml")); QVERIFY2(helper.ready, helper.failureMessage()); diff --git a/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp b/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp index 63dec4dc6a..671f79ec43 100644 --- a/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp +++ b/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp @@ -39,8 +39,6 @@ private slots: void hoverAfterClosingWithEscape(); private: - static bool hasWindowActivation(); - QScopedPointer<QPointingDevice> touchScreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice()); }; @@ -55,11 +53,6 @@ tst_qquickmenubar::tst_qquickmenubar() qputenv("QML_NO_TOUCH_COMPRESSION", "1"); } -bool tst_qquickmenubar::hasWindowActivation() -{ - return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)); -} - void tst_qquickmenubar::delegate() { QQmlApplicationEngine engine(testFileUrl("empty.qml")); @@ -75,8 +68,7 @@ void tst_qquickmenubar::delegate() void tst_qquickmenubar::mouse() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION if ((QGuiApplication::platformName() == QLatin1String("offscreen")) || (QGuiApplication::platformName() == QLatin1String("minimal"))) @@ -287,8 +279,7 @@ void tst_qquickmenubar::touch() void tst_qquickmenubar::keys() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQmlApplicationEngine engine(testFileUrl("menubar.qml")); @@ -479,8 +470,7 @@ void tst_qquickmenubar::keys() void tst_qquickmenubar::mnemonics() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION #if defined(Q_OS_MACOS) or defined(Q_OS_WEBOS) QSKIP("Mnemonics are not used on this platform"); diff --git a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp index e774d055e1..159f8ca1ac 100644 --- a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp +++ b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp @@ -108,7 +108,6 @@ private slots: void noDimmer(); private: - static bool hasWindowActivation(); QScopedPointer<QPointingDevice> touchScreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice()); }; @@ -132,11 +131,6 @@ void tst_QQuickPopup::visible_data() QTest::newRow("ApplicationWindow") << "applicationwindow.qml"; } -bool tst_QQuickPopup::hasWindowActivation() -{ - return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)); -} - void tst_QQuickPopup::visible() { QFETCH(QString, source); @@ -515,8 +509,7 @@ void tst_QQuickPopup::closePolicy_data() void tst_QQuickPopup::closePolicy() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QFETCH(QString, source); QFETCH(const QPointingDevice *, device); @@ -658,8 +651,7 @@ void tst_QQuickPopup::closePolicy_grabberInside() void tst_QQuickPopup::activeFocusOnClose1() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Test that a popup that never sets focus: true (e.g. ToolTip) doesn't affect // the active focus item when it closes. @@ -704,8 +696,7 @@ void tst_QQuickPopup::activeFocusOnClose1() void tst_QQuickPopup::activeFocusOnClose2() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Test that a popup that sets focus: true but relinquishes focus (e.g. by // calling forceActiveFocus() on another item) before it closes doesn't @@ -746,8 +737,7 @@ void tst_QQuickPopup::activeFocusOnClose2() void tst_QQuickPopup::activeFocusOnClose3() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Test that a closing popup that had focus doesn't steal focus from // another popup that the focus was transferred to. @@ -782,8 +772,7 @@ void tst_QQuickPopup::activeFocusOnClose3() void tst_QQuickPopup::activeFocusOnClosingSeveralPopups() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Test that active focus isn't lost when multiple popup closing simultaneously QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusOnClosingSeveralPopups.qml")); @@ -834,8 +823,7 @@ void tst_QQuickPopup::activeFocusOnClosingSeveralPopups() void tst_QQuickPopup::activeFocusAfterExit() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Test that after closing a popup the highest one in z-order receives it instead. QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusAfterExit.qml")); @@ -886,8 +874,7 @@ void tst_QQuickPopup::activeFocusAfterExit() void tst_QQuickPopup::activeFocusOnDelayedEnter() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Test that after opening two popups, first of which has an animation, does not cause // the first one to receive focus after the animation stops. @@ -915,8 +902,7 @@ void tst_QQuickPopup::activeFocusOnDelayedEnter() // key events due to having active focus. void tst_QQuickPopup::activeFocusDespiteLowerStackingOrder() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusOnClose3.qml")); QVERIFY2(helper.ready, helper.failureMessage()); @@ -957,8 +943,7 @@ void tst_QQuickPopup::activeFocusDespiteLowerStackingOrder() void tst_QQuickPopup::activeFocusItemAfterWindowInactive() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusAfterWindowInactive.qml")); QVERIFY2(helper.ready, helper.failureMessage()); @@ -1440,8 +1425,7 @@ void tst_QQuickPopup::componentComplete() void tst_QQuickPopup::closeOnEscapeWithNestedPopups() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Tests the scenario in the Gallery example, where there are nested popups that should // close in the correct order when the Escape key is pressed. @@ -1510,8 +1494,7 @@ void tst_QQuickPopup::closeOnEscapeWithNestedPopups() void tst_QQuickPopup::closeOnEscapeWithVisiblePopup() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, QStringLiteral("closeOnEscapeWithVisiblePopup.qml")); QVERIFY2(helper.ready, helper.failureMessage()); @@ -1621,8 +1604,7 @@ void tst_QQuickPopup::qquickview() // QTBUG-73447 void tst_QQuickPopup::disabledPalette() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, "disabledPalette.qml"); QVERIFY2(helper.ready, helper.failureMessage()); @@ -1661,8 +1643,7 @@ void tst_QQuickPopup::disabledPalette() void tst_QQuickPopup::disabledParentPalette() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, "disabledPalette.qml"); QVERIFY2(helper.ready, helper.failureMessage()); @@ -1770,8 +1751,7 @@ void tst_QQuickPopup::setOverlayParentToNull() void tst_QQuickPopup::tabFence() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) QSKIP("This platform only allows tab focus for text controls"); @@ -1883,8 +1863,7 @@ void tst_QQuickPopup::centerInOverlayWithinStackViewItem() void tst_QQuickPopup::destroyDuringExitTransition() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, "destroyDuringExitTransition.qml"); QVERIFY2(helper.ready, helper.failureMessage()); diff --git a/tests/auto/quickcontrols/qquicktextarea/tst_qquicktextarea.cpp b/tests/auto/quickcontrols/qquicktextarea/tst_qquicktextarea.cpp index a576bb7941..75e2550d7a 100644 --- a/tests/auto/quickcontrols/qquicktextarea/tst_qquicktextarea.cpp +++ b/tests/auto/quickcontrols/qquicktextarea/tst_qquicktextarea.cpp @@ -12,6 +12,7 @@ #include <QtQuick/qquickview.h> #include <QtQuickTestUtils/private/qmlutils_p.h> #include <QtQuickTestUtils/private/viewtestutils_p.h> +#include <QtQuickTestUtils/private/visualtestutils_p.h> #include <QtQuickTemplates2/private/qquicktextarea_p.h> #include <QtQuickControlsTestUtils/private/qtest_quickcontrols_p.h> @@ -29,7 +30,6 @@ private slots: void touchscreenSetsFocusAndMovesCursor(); private: - static bool hasWindowActivation(); QScopedPointer<QPointingDevice> touchDevice = QScopedPointer<QPointingDevice>(QTest::createTouchDevice()); }; @@ -102,8 +102,7 @@ void tst_QQuickTextArea::touchscreenDoesNotSelect() void tst_QQuickTextArea::touchscreenSetsFocusAndMovesCursor() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION qunsetenv("QT_QUICK_CONTROLS_TEXT_SELECTION_BEHAVIOR"); QQuickView window; @@ -158,11 +157,6 @@ void tst_QQuickTextArea::touchscreenSetsFocusAndMovesCursor() QCOMPARE_GT(top->selectedText().size(), 0); } -bool tst_QQuickTextArea::hasWindowActivation() -{ - return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)); -} - QTEST_QUICKCONTROLS_MAIN(tst_QQuickTextArea) #include "tst_qquicktextarea.moc" diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp index 0067c716e0..3d5cb6e3b0 100644 --- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp +++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp @@ -14,6 +14,7 @@ #include <QtQuick/private/qquicktaphandler_p.h> #include <QtQuickTemplates2/private/qquickbutton_p.h> #include <QtQuickTestUtils/private/qmlutils_p.h> +#include <QtQuickTestUtils/private/visualtestutils_p.h> #include <QtGui/QWindow> #include <QtGui/QScreen> #include <QtGui/QImage> @@ -991,8 +992,7 @@ void tst_qquickwidget::focusOnClickInProxyWidget() void tst_qquickwidget::focusPreserved() { - if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) - QSKIP("Window Activation is not supported."); + SKIP_IF_NO_WINDOW_ACTIVATION if (QGuiApplication::platformName() == "android") QSKIP("Test doesn't exit cleanly on Android and generates many warnings - QTBUG-112696"); diff --git a/tests/baseline/controls/data/textarea/textarea.qml b/tests/baseline/controls/data/textarea/textarea.qml index e34709c6cf..57b57606b4 100644 --- a/tests/baseline/controls/data/textarea/textarea.qml +++ b/tests/baseline/controls/data/textarea/textarea.qml @@ -8,11 +8,13 @@ ColumnLayout { TextArea { text: "TextArea\n...\n...\n...\n..." + cursorVisible: false } TextArea { placeholderText: "TextArea\n...\n...\n..." enabled: false + cursorVisible: false } TextArea { @@ -24,6 +26,7 @@ ColumnLayout { TextArea { text: "TextArea\n...\n...\n...\n..." LayoutMirroring.enabled: true + cursorVisible: false } } diff --git a/tests/baseline/controls/data/textfield/textfield.qml b/tests/baseline/controls/data/textfield/textfield.qml index bc0b1f215f..00b00913f8 100644 --- a/tests/baseline/controls/data/textfield/textfield.qml +++ b/tests/baseline/controls/data/textfield/textfield.qml @@ -9,21 +9,25 @@ ColumnLayout { TextField { placeholderText: qsTr("Enter text") enabled: false + cursorVisible: false } TextField { placeholderText: qsTr("Enter text") placeholderTextColor: "red" + cursorVisible: false } TextField { placeholderText: qsTr("Enter text") focus: true + cursorVisible: false } TextField { placeholderText: qsTr("Enter text") LayoutMirroring.enabled: true + cursorVisible: false } TextField { @@ -31,5 +35,6 @@ ColumnLayout { + "sed do eiusmod tempor incididunt utlabore et dolore magna" + "aliqua.Ut enim ad minim veniam, quis nostrud exercitation" + "ullamco laboris nisi ut aliquip ex ea commodo consequat.") + cursorVisible: false } } diff --git a/tests/baseline/scenegraph/data/shape/shape_updatecolor.qml b/tests/baseline/scenegraph/data/shape/shape_updatecolor.qml new file mode 100644 index 0000000000..32cc73ad45 --- /dev/null +++ b/tests/baseline/scenegraph/data/shape/shape_updatecolor.qml @@ -0,0 +1,77 @@ +import QtQuick +import QtQuick.Shapes + +Item { + width: 320 + height: 800 + + ListModel { + id: renderers + ListElement { renderer: Shape.GeometryRenderer } + ListElement { renderer: Shape.CurveRenderer } + } + + Row { + Repeater { + model: renderers + Column { + Shape { + preferredRendererType: renderer + width: 160 + height: 150 + + ShapePath { + strokeColor: "transparent" + fillColor: "red" + + startX: 10; startY: 10 + PathLine { relativeX: 140; relativeY: 0 } + PathLine { relativeX: 0; relativeY: 100 } + PathLine { relativeX: -140; relativeY: 0 } + PathLine { relativeX: 0; relativeY: -100 } + } + } + + Shape { + preferredRendererType: renderer + width: 160 + height: 150 + + ShapePath { + strokeColor: "transparent" + fillColor: "red" + + startX: 10; startY: 10 + 1 * 140 + PathLine { relativeX: 140; relativeY: 0 } + PathLine { relativeX: 0; relativeY: 100 } + PathLine { relativeX: -140; relativeY: 0 } + PathLine { relativeX: 0; relativeY: -100 } + } + } + + Shape { + preferredRendererType: renderer + width: 160 + height: 150 + Timer { + interval: 100 + running: true + onTriggered: s.fillColor = Qt.rgba(0, 1, 0, 1) + } + + ShapePath { + id: s + strokeColor: "transparent" + fillColor: "red" + + startX: 10; startY: 10 + 2 * 140 + PathLine { relativeX: 140; relativeY: 0 } + PathLine { relativeX: 0; relativeY: 100 } + PathLine { relativeX: -140; relativeY: 0 } + PathLine { relativeX: 0; relativeY: -100 } + } + } + } + } + } +} diff --git a/tests/baseline/scenegraph/data/shape/shape_updategradient.qml b/tests/baseline/scenegraph/data/shape/shape_updategradient.qml new file mode 100644 index 0000000000..f1fa0f0f3d --- /dev/null +++ b/tests/baseline/scenegraph/data/shape/shape_updategradient.qml @@ -0,0 +1,105 @@ +import QtQuick +import QtQuick.Shapes + +Item { + width: 320 + height: 800 + + ListModel { + id: renderers + ListElement { renderer: Shape.GeometryRenderer } + ListElement { renderer: Shape.CurveRenderer } + } + + RadialGradient { + id: radialGradient + centerX: 80 + centerY: 75 + centerRadius: centerY + focalX: centerX + focalY: centerY + GradientStop { position: 0; color: "black" } + GradientStop { position: .5; color: "cyan" } + GradientStop { position: 1; color: "black" } + } + + Row { + Repeater { + model: renderers + Column { + Shape { + preferredRendererType: renderer + width: 160 + height: 150 + + ShapePath { + strokeColor: "transparent" + fillGradient: LinearGradient { + y1: 50; y2: 80 + GradientStop { position: 0; color: "black" } + GradientStop { position: 1; color: "cyan" } + } + fillTransform: PlanarTransform.fromAffineMatrix(0.8, 0.2, 0.3, 1.5, 20, -50 + startY) + + startX: 10; startY: 10 + PathLine { relativeX: 140; relativeY: 0 } + PathLine { relativeX: 0; relativeY: 100 } + PathLine { relativeX: -140; relativeY: 0 } + PathLine { relativeX: 0; relativeY: -100 } + } + } + + Shape { + preferredRendererType: renderer + width: 160 + height: 150 + + ShapePath { + strokeColor: "transparent" + fillGradient: LinearGradient { + y1: 50; y2: 80 + GradientStop { position: 0; color: "black" } + GradientStop { position: 1; color: "cyan" } + } + fillTransform: PlanarTransform.fromAffineMatrix(0.8, 0.2, 0.3, 1.5, 20, -50 + startY) + + startX: 10; startY: 10 + 1 * 140 + PathLine { relativeX: 140; relativeY: 0 } + PathLine { relativeX: 0; relativeY: 100 } + PathLine { relativeX: -140; relativeY: 0 } + PathLine { relativeX: 0; relativeY: -100 } + } + } + + Shape { + preferredRendererType: renderer + width: 160 + height: 150 + Timer { + interval: 100 + running: true + onTriggered: s.fillGradient = radialGradient + } + + ShapePath { + id: s + strokeColor: "transparent" + fillGradient: LinearGradient { + y1: 50; y2: 80 + GradientStop { position: 0; color: "black" } + GradientStop { position: 1; color: "cyan" } + } + fillTransform: PlanarTransform.fromAffineMatrix(0.8, 0.2, 0.3, 1.5, 20, -50 + startY) + + + startX: 10; startY: 10 + 2 * 140 + PathLine { relativeX: 140; relativeY: 0 } + PathLine { relativeX: 0; relativeY: 100 } + PathLine { relativeX: -140; relativeY: 0 } + PathLine { relativeX: 0; relativeY: -100 } + } + } + } + } + } +} |