diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2018-02-15 14:10:20 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2018-02-15 14:10:20 +0000 |
commit | 471f8421bc4d75adc8e4a357d525ade9ede20e29 (patch) | |
tree | 4c4e132b5c218433ed2619de9c6f53b914103fe0 /tests | |
parent | 421dcfb5792a5ff5e5a9851e0c1edf6e87422680 (diff) | |
parent | 4d525de33e2ee55e69bb6c90fc11049a0f8b36b5 (diff) |
Merge "Merge remote-tracking branch 'origin/5.10' into 5.11" into refs/staging/5.11
Diffstat (limited to 'tests')
27 files changed, 1361 insertions, 21 deletions
diff --git a/tests/auto/bic/README b/tests/auto/bic/README new file mode 100644 index 0000000000..2bde3dd9b9 --- /dev/null +++ b/tests/auto/bic/README @@ -0,0 +1,13 @@ +This directory contains test data to be used by tst_bic to check that we don't +introduce binary incompatible changes between releases. The bic test is run +after every successful integration on Linux only. This data is generated after +each minor release. The generated BC files contain virtual tables, and the bic +test checks new content against the old data. + +See the following README for an explanation of how to generate this data: + +http://code.qt.io/cgit/qt/qtqa.git/tree/tests/postbuild/bic/README + +The test itself can be found here: + +http://code.qt.io/cgit/qt/qtqa.git/tree/tests/postbuild/bic diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index a7b02f3cca..2f5ff0022e 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -33,6 +33,7 @@ #include <QProcess> #include <QLibraryInfo> #include <QSysInfo> +#include <private/qqmlcomponent_p.h> class tst_qmlcachegen: public QObject { @@ -118,6 +119,16 @@ void tst_qmlcachegen::loadGeneratedFile() const QString cacheFilePath = testFilePath + QLatin1Char('c'); QVERIFY(QFile::exists(cacheFilePath)); + + { + QFile cache(cacheFilePath); + QVERIFY(cache.open(QIODevice::ReadOnly)); + const QV4::CompiledData::Unit *cacheUnit = reinterpret_cast<const QV4::CompiledData::Unit *>(cache.map(/*offset*/0, sizeof(QV4::CompiledData::Unit))); + QVERIFY(cacheUnit); + QVERIFY(cacheUnit->flags & QV4::CompiledData::Unit::StaticData); + QVERIFY(cacheUnit->flags & QV4::CompiledData::Unit::PendingTypeCompilation); + } + QVERIFY(QFile::remove(testFilePath)); QQmlEngine engine; @@ -125,6 +136,13 @@ void tst_qmlcachegen::loadGeneratedFile() QScopedPointer<QObject> obj(component.create()); QVERIFY(!obj.isNull()); QCOMPARE(obj->property("value").toInt(), 42); + + auto componentPrivate = QQmlComponentPrivate::get(&component); + QVERIFY(componentPrivate); + auto compilationUnit = componentPrivate->compilationUnit; + QVERIFY(compilationUnit); + QVERIFY(compilationUnit->data); + QVERIFY(!(compilationUnit->data->flags & QV4::CompiledData::Unit::StaticData)); } void tst_qmlcachegen::translationExpressionSupport() diff --git a/tests/auto/qml/qqmlecmascript/data/nans.qml b/tests/auto/qml/qqmlecmascript/data/nans.qml new file mode 100644 index 0000000000..ece69f2d79 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/nans.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +QtObject { + property var prop: undefined +} diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index 2db35d0219..8d89df31db 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -1663,7 +1663,8 @@ class SingletonWithEnum : public QObject Q_ENUMS(TestEnum) public: enum TestEnum { - TestValue = 42 + TestValue = 42, + TestValue_MinusOne = -1 }; }; diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index f48cb2743c..b7d5db9914 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -348,6 +348,7 @@ private slots: void forInIterator(); void localForInIterator(); void shadowedFunctionName(); + void anotherNaN(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -7922,6 +7923,15 @@ void tst_qqmlecmascript::singletonWithEnum() QVariant prop = obj->property("testValue"); QCOMPARE(prop.type(), QVariant::Int); QCOMPARE(prop.toInt(), int(SingletonWithEnum::TestValue)); + + { + QQmlExpression expr(qmlContext(obj.data()), obj.data(), "SingletonWithEnum.TestValue_MinusOne"); + bool valueUndefined = false; + QVariant result = expr.evaluate(&valueUndefined); + QVERIFY2(!expr.hasError(), qPrintable(expr.error().toString())); + QVERIFY(!valueUndefined); + QCOMPARE(result.toInt(), -1); + } } void tst_qqmlecmascript::lazyBindingEvaluation() @@ -8369,6 +8379,20 @@ void tst_qqmlecmascript::qtbug_60547() QCOMPARE(object->property("counter"), QVariant(int(1))); } +void tst_qqmlecmascript::anotherNaN() +{ + QQmlComponent component(&engine, testFileUrl("nans.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY2(!object.isNull(), qPrintable(component.errorString())); + object->setProperty("prop", std::numeric_limits<double>::quiet_NaN()); // don't crash + + std::uint64_t anotherNaN = 0xFFFFFF01000000F7ul; + double d; + std::memcpy(&d, &anotherNaN, sizeof(d)); + QVERIFY(std::isnan(d)); + object->setProperty("prop", d); // don't crash +} + void tst_qqmlecmascript::delayLoadingArgs() { QJSEngine engine; diff --git a/tests/auto/qml/qqmllanguage/data/invalidAlias.13.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidAlias.13.errors.txt new file mode 100644 index 0000000000..234753ad59 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/invalidAlias.13.errors.txt @@ -0,0 +1 @@ +6:5:Invalid alias target diff --git a/tests/auto/qml/qqmllanguage/data/invalidAlias.13.qml b/tests/auto/qml/qqmllanguage/data/invalidAlias.13.qml new file mode 100644 index 0000000000..4050c0a7ad --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/invalidAlias.13.qml @@ -0,0 +1,10 @@ +import QtQml 2.0 + +QtObject { + property alias dataValue: dataVal + + invalidAliasComponent { + id: dataVal + strValue: "value2" + } +} diff --git a/tests/auto/qml/qqmllanguage/data/invalidAliasComponent.qml b/tests/auto/qml/qqmllanguage/data/invalidAliasComponent.qml new file mode 100644 index 0000000000..a45b1806a3 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/invalidAliasComponent.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property string strValue: "value1" +} diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index dfc6509732..03d53b755d 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -279,6 +279,8 @@ private slots: void accessDeletedObject(); + void lowercaseTypeNames(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -521,6 +523,7 @@ void tst_qqmllanguage::errors_data() QTest::newRow("invalidAlias.10") << "invalidAlias.10.qml" << "invalidAlias.10.errors.txt" << false; QTest::newRow("invalidAlias.11") << "invalidAlias.11.qml" << "invalidAlias.11.errors.txt" << false; QTest::newRow("invalidAlias.12") << "invalidAlias.12.qml" << "invalidAlias.12.errors.txt" << false; + QTest::newRow("invalidAlias.13") << "invalidAlias.13.qml" << "invalidAlias.13.errors.txt" << false; QTest::newRow("invalidAttachedProperty.1") << "invalidAttachedProperty.1.qml" << "invalidAttachedProperty.1.errors.txt" << false; QTest::newRow("invalidAttachedProperty.2") << "invalidAttachedProperty.2.qml" << "invalidAttachedProperty.2.errors.txt" << false; @@ -4902,6 +4905,12 @@ void tst_qqmllanguage::accessDeletedObject() QVERIFY(!o.isNull()); } +void tst_qqmllanguage::lowercaseTypeNames() +{ + QCOMPARE(qmlRegisterType<QObject>("Test", 1, 0, "lowerCaseTypeName"), -1); + QCOMPARE(qmlRegisterSingletonType<QObject>("Test", 1, 0, "lowerCaseTypeName", nullptr), -1); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithStaticPlugin/qmldir b/tests/auto/qml/qqmlmoduleplugin/moduleWithStaticPlugin/qmldir new file mode 100644 index 0000000000..104c4bf673 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithStaticPlugin/qmldir @@ -0,0 +1,2 @@ +module moduleWithStaticPlugin +plugin secondStaticPlugin diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithWaitingPlugin/qmldir b/tests/auto/qml/qqmlmoduleplugin/moduleWithWaitingPlugin/qmldir new file mode 100644 index 0000000000..45a02b2ffe --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithWaitingPlugin/qmldir @@ -0,0 +1,2 @@ +module moduleWithWaitingPlugin +plugin pluginThatWaits diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp index edfbf57e76..85e4918b61 100644 --- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp @@ -29,6 +29,9 @@ #include <qdir.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> +#include <QtQml/qqmlextensionplugin.h> +#include <QtCore/qjsondocument.h> +#include <QtCore/qjsonarray.h> #include <QDebug> #if defined(Q_OS_MAC) @@ -73,12 +76,80 @@ private slots: void importsChildPlugin(); void importsChildPlugin2(); void importsChildPlugin21(); + void parallelPluginImport(); private: QString m_importsDirectory; QString m_dataImportsDirectory; }; +class PluginThatWaits : public QQmlExtensionPlugin +{ +public: + static QByteArray metaData; + + static QMutex initializeEngineEntered; + static QWaitCondition waitingForInitializeEngineEntry; + static QMutex leavingInitializeEngine; + static QWaitCondition waitingForInitializeEngineLeave; + + void registerTypes(const char *uri) override + { + qmlRegisterModule(uri, 1, 0); + } + + void initializeEngine(QQmlEngine *engine, const char *uri) override + { + initializeEngineEntered.lock(); + leavingInitializeEngine.lock(); + waitingForInitializeEngineEntry.wakeOne(); + initializeEngineEntered.unlock(); + waitingForInitializeEngineLeave.wait(&leavingInitializeEngine); + leavingInitializeEngine.unlock(); + } +}; +QByteArray PluginThatWaits::metaData; +QMutex PluginThatWaits::initializeEngineEntered; +QWaitCondition PluginThatWaits::waitingForInitializeEngineEntry; +QMutex PluginThatWaits::leavingInitializeEngine; +QWaitCondition PluginThatWaits::waitingForInitializeEngineLeave; + +class SecondStaticPlugin : public QQmlExtensionPlugin +{ +public: + static QByteArray metaData; + + void registerTypes(const char *uri) override + { + qmlRegisterModule(uri, 1, 0); + } +}; +QByteArray SecondStaticPlugin::metaData; + +template <typename PluginType> +void registerStaticPlugin(const char *uri) +{ + QStaticPlugin plugin; + plugin.instance = []() { + static PluginType plugin; + return static_cast<QObject*>(&plugin); + }; + + QJsonObject md; + md.insert(QStringLiteral("IID"), QQmlExtensionInterface_iid); + QJsonArray uris; + uris.append(uri); + md.insert(QStringLiteral("uri"), uris); + + PluginType::metaData.append(QLatin1String("QTMETADATA ")); + PluginType::metaData.append(QJsonDocument(md).toBinaryData()); + + plugin.rawMetaData = []() { + return PluginType::metaData.constData(); + }; + qRegisterStaticPluginFunction(plugin); +}; + void tst_qqmlmoduleplugin::initTestCase() { QQmlDataTest::initTestCase(); @@ -88,6 +159,9 @@ void tst_qqmlmoduleplugin::initTestCase() m_dataImportsDirectory = directory() + QStringLiteral("/imports"); QVERIFY2(QFileInfo(m_dataImportsDirectory).isDir(), qPrintable(QString::fromLatin1("Imports directory '%1' does not exist.").arg(m_dataImportsDirectory))); + + registerStaticPlugin<PluginThatWaits>("moduleWithWaitingPlugin"); + registerStaticPlugin<SecondStaticPlugin>("moduleWithStaticPlugin"); } #define VERIFY_ERRORS(errorfile) \ @@ -629,6 +703,51 @@ void tst_qqmlmoduleplugin::importsChildPlugin21() delete object; } +void tst_qqmlmoduleplugin::parallelPluginImport() +{ + QMutexLocker locker(&PluginThatWaits::initializeEngineEntered); + + QThread worker; + QObject::connect(&worker, &QThread::started, [&worker](){ + // Engines in separate threads are tricky, but as long as we do not create a graphical + // object and move objects created by the engines across thread boundaries, this is safe. + // At the same time this allows us to place the engine's loader thread into the position + // where, without the fix for this bug, the global lock is acquired. + QQmlEngine engineInThread; + + QQmlComponent component(&engineInThread); + component.setData("import moduleWithWaitingPlugin 1.0\nimport QtQml 2.0\nQtObject {}", + QUrl()); + + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + + worker.quit(); + }); + worker.start(); + + PluginThatWaits::waitingForInitializeEngineEntry.wait(&PluginThatWaits::initializeEngineEntered); + + { + // After acquiring this lock, the engine in the other thread as well as its type loader + // thread are blocked. However they should not hold the global plugin lock + // qmlEnginePluginsWithRegisteredTypes()->mutex in qqmllimports.cpp, allowing for the load + // of a component in a different engine with its own plugin to proceed. + QMutexLocker continuationLock(&PluginThatWaits::leavingInitializeEngine); + + QQmlEngine secondEngine; + QQmlComponent secondComponent(&secondEngine); + secondComponent.setData("import moduleWithStaticPlugin 1.0\nimport QtQml 2.0\nQtObject {}", + QUrl()); + QScopedPointer<QObject> o(secondComponent.create()); + QVERIFY(!o.isNull()); + + PluginThatWaits::waitingForInitializeEngineLeave.wakeOne(); + } + + worker.wait(); +} + QTEST_MAIN(tst_qqmlmoduleplugin) #include "tst_qqmlmoduleplugin.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.pro b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.pro index 43bd112415..118ca26ee9 100644 --- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.pro +++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.pro @@ -10,4 +10,12 @@ include (../../shared/util.pri) TESTDATA = data/* imports/* $$OUT_PWD/imports/* +waitingPlugin.files = moduleWithWaitingPlugin +waitingPlugin.prefix = /qt-project.org/imports/ +RESOURCES += waitingPlugin + +staticPlugin.files = moduleWithStaticPlugin +staticPlugin.prefix = /qt-project.org/imports/ +RESOURCES += staticPlugin + QT += core-private gui-private qml-private network testlib diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml new file mode 100644 index 0000000000..adb8332213 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/simpleTapAndDragHandlers.qml @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 + +Rectangle { + id: root + width: 900 + height: 850 + objectName: "root" + color: "#222222" + + Row { + objectName: "row" + anchors.fill: parent + spacing: 10 + Rectangle { + width: 50 + height: 50 + color: "aqua" + objectName: "dragAndTap" + DragHandler { + objectName: "drag" + } + TapHandler { + objectName: "tap" + gesturePolicy: TapHandler.DragThreshold + } + } + Rectangle { + width: 50 + height: 50 + color: "aqua" + objectName: "tapAndDrag" + TapHandler { + objectName: "tap" + gesturePolicy: TapHandler.DragThreshold + } + DragHandler { + objectName: "drag" + } + } + + Rectangle { + color: "aqua" + width: 50 + height: 50 + objectName: "dragAndTapNotSiblings" + DragHandler { + objectName: "drag" + } + Rectangle { + color: "blue" + width: 30 + height: 30 + anchors.centerIn: parent + TapHandler { + objectName: "tap" + gesturePolicy: TapHandler.DragThreshold + } + } + } + Rectangle { + color: "aqua" + width: 50 + height: 50 + objectName: "tapAndDragNotSiblings" + TapHandler { + objectName: "tap" + gesturePolicy: TapHandler.DragThreshold + } + Rectangle { + color: "blue" + x: 10 + y: 10 + width: 30 + height: 30 + DragHandler { + objectName: "drag" + } + } + } + + + } +} diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/qquickdraghandler.pro b/tests/auto/quick/pointerhandlers/qquickdraghandler/qquickdraghandler.pro index b50fe5ca6f..42c4e46c4f 100644 --- a/tests/auto/quick/pointerhandlers/qquickdraghandler/qquickdraghandler.pro +++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/qquickdraghandler.pro @@ -12,4 +12,10 @@ include (../../shared/util.pri) TESTDATA = data/* -# OTHER_FILES += data/foo.qml +OTHER_FILES += data/DragAnywhereSlider.qml \ + data/FlashAnimation.qml \ + data/Slider.qml \ + data/draggables.qml \ + data/grabberstate.qml \ + data/multipleSliders.qml \ + data/reparenting.qml \ diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp index 8dc035949e..f827b82205 100644 --- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. @@ -58,9 +58,12 @@ private slots: void touchDragMulti(); void touchDragMultiSliders_data(); void touchDragMultiSliders(); + void touchPassiveGrabbers_data(); + void touchPassiveGrabbers(); private: void createView(QScopedPointer<QQuickView> &window, const char *fileName); + QSet<QQuickPointerHandler *> passiveGrabbers(QQuickWindow *window, int pointId = 0); QTouchDevice *touchDevice; }; @@ -77,6 +80,24 @@ void tst_DragHandler::createView(QScopedPointer<QQuickView> &window, const char QVERIFY(window->rootObject() != 0); } +QSet<QQuickPointerHandler*> tst_DragHandler::passiveGrabbers(QQuickWindow *window, int pointId /*= 0*/) +{ + QSet<QQuickPointerHandler*> result; + QQuickWindowPrivate *winp = QQuickWindowPrivate::get(window); + if (QQuickPointerDevice* device = QQuickPointerDevice::touchDevice(touchDevice)) { + QQuickPointerEvent *pointerEvent = winp->pointerEventInstance(device); + for (int i = 0; i < pointerEvent->pointCount(); ++i) { + QQuickEventPoint *eventPoint = pointerEvent->point(i); + QVector<QPointer <QQuickPointerHandler> > passives = eventPoint->passiveGrabbers(); + if (!pointId || eventPoint->pointId() == pointId) { + for (auto it = passives.constBegin(); it != passives.constEnd(); ++it) + result << it->data(); + } + } + } + return result; +} + void tst_DragHandler::initTestCase() { // This test assumes that we don't get synthesized mouse events from QGuiApplication @@ -398,6 +419,68 @@ void tst_DragHandler::touchDragMultiSliders() touch.commit(); } +void tst_DragHandler::touchPassiveGrabbers_data() +{ + QTest::addColumn<QString>("itemName"); + QTest::addColumn<QStringList>("expectedPassiveGrabberNames"); + + QTest::newRow("Drag And Tap") << "dragAndTap" << QStringList({"drag", "tap"}); + QTest::newRow("Tap And Drag") << "tapAndDrag" << QStringList({"tap", "drag"}); + QTest::newRow("Drag And Tap (not siblings)") << "dragAndTapNotSiblings" << QStringList({"drag", "tap"}); + QTest::newRow("Tap And Drag (not siblings)") << "tapAndDragNotSiblings" << QStringList({"tap", "drag"}); +} + +void tst_DragHandler::touchPassiveGrabbers() +{ + QFETCH(QString, itemName); + QFETCH(QStringList, expectedPassiveGrabberNames); + + QScopedPointer<QQuickView> windowPtr; + createView(windowPtr, "simpleTapAndDragHandlers.qml"); + QQuickView * window = windowPtr.data(); + + QQuickItem *row2 = window->rootObject()->findChild<QQuickItem*>(itemName); + QSet<QQuickPointerHandler *> expectedPassiveGrabbers; + for (QString objectName : expectedPassiveGrabberNames) + expectedPassiveGrabbers << row2->findChild<QQuickPointerHandler*>(objectName); + + QPointF p1 = row2->mapToScene(row2->clipRect().center()); + QTest::QTouchEventSequence touch = QTest::touchEvent(window, touchDevice); + touch.press(1, p1.toPoint()).commit(); + QQuickTouchUtils::flush(window); + + QCOMPARE(passiveGrabbers(window), expectedPassiveGrabbers); + + QQuickDragHandler *dragHandler = nullptr; + for (QQuickPointerHandler *handler: expectedPassiveGrabbers) { + QCOMPARE(static_cast<QQuickSinglePointHandler *>(handler)->point().scenePressPosition(), p1); + QQuickDragHandler *dh = qmlobject_cast<QQuickDragHandler *>(handler); + if (dh) + dragHandler = dh; + } + QVERIFY(dragHandler); + QPointF initialPos = dragHandler->target()->position(); + + p1 += QPointF(50, 50); + touch.move(1, p1.toPoint()).commit(); + QQuickTouchUtils::flush(window); + QTRY_VERIFY(dragHandler->active()); + + p1 += QPointF(50, 50); + touch.move(1, p1.toPoint()).commit(); + QQuickTouchUtils::flush(window); + QPointF movementDelta = dragHandler->target()->position() - initialPos; + qCDebug(lcPointerTests) << "DragHandler moved the target by" << movementDelta; + QVERIFY(movementDelta.x() >= 100); + QVERIFY(movementDelta.y() >= 100); + + QTest::qWait(500); + + touch.release(1, p1.toPoint()); + touch.commit(); + QQuickTouchUtils::flush(window); +} + QTEST_MAIN(tst_DragHandler) #include "tst_qquickdraghandler.moc" diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp index cc39dd54f7..d38ae3190e 100644 --- a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. @@ -504,17 +504,18 @@ void tst_PointerHandlers::mouseEventDelivery() eventItem1->grabPointer = true; p1 = QPoint(20, 20); QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); - QTRY_COMPARE(eventItem1->eventList.size(), 2); + QTRY_COMPARE(eventItem1->eventList.size(), 3); QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::None, Qt::TouchPointPressed, QQuickEventPoint::GrabExclusive); QCOMPARE_EVENT(1, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, QQuickEventPoint::GrabExclusive); + QCOMPARE_EVENT(2, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, 0); p1 += QPoint(10, 0); QTest::mouseMove(window, p1); - QCOMPARE(eventItem1->eventList.size(), 3); - QCOMPARE_EVENT(2, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointMoved, QQuickEventPoint::GrabExclusive); + QCOMPARE(eventItem1->eventList.size(), 4); + QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointMoved, QQuickEventPoint::GrabExclusive); QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1); - QCOMPARE(eventItem1->eventList.size(), 5); - QCOMPARE_EVENT(3, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, QQuickEventPoint::GrabExclusive); - QCOMPARE_EVENT(4, Event::HandlerDestination, QEvent::None, Qt::TouchPointReleased, QQuickEventPoint::UngrabExclusive); + QCOMPARE(eventItem1->eventList.size(), 6); + QCOMPARE_EVENT(4, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointReleased, QQuickEventPoint::GrabExclusive); + QCOMPARE_EVENT(5, Event::HandlerDestination, QEvent::None, Qt::TouchPointReleased, QQuickEventPoint::UngrabExclusive); eventItem1->eventList.clear(); } diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml index 14a8d67300..219d4a70a8 100644 --- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml +++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttonOverrideHandler.qml @@ -38,6 +38,7 @@ Item { label: "Overridden" x: 10; y: 10; width: parent.width - 20; height: 40 TapHandler { + gesturePolicy: TapHandler.ReleaseWithinBounds objectName: "override" onTapped: button.tapped() } diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp index f458bdcf5b..783e4aab4c 100644 --- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp +++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp @@ -412,11 +412,11 @@ void tst_qquickimage::svg() component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickImage *obj = qobject_cast<QQuickImage*>(component.create()); QVERIFY(obj != 0); - QCOMPARE(int(obj->width()), 212); // round down: highdpi can give back fractional values + QCOMPARE(obj->width(), 300.0); QCOMPARE(obj->height(), 300.0); obj->setSourceSize(QSize(200,200)); - QCOMPARE(int(obj->width()), 141); // round down: highdpi can give back fractional values + QCOMPARE(obj->width(), 200.0); QCOMPARE(obj->height(), 200.0); delete obj; } diff --git a/tests/auto/quick/qquickloader/data/itemLoaderItemWindow.qml b/tests/auto/quick/qquickloader/data/itemLoaderItemWindow.qml new file mode 100644 index 0000000000..d4c5daecab --- /dev/null +++ b/tests/auto/quick/qquickloader/data/itemLoaderItemWindow.qml @@ -0,0 +1,27 @@ +import QtQuick 2.0 +import QtQuick.Window 2.1 + +Item { + width: 400 + height: 400 + objectName: "root Item" + + Loader { + sourceComponent: Rectangle { + objectName: "yellow rectangle" + x: 50; y: 50; width: 300; height: 300 + color: "yellow" + Window { + objectName: "red transient Window" + width: 100 + height: 100 + visible: true // makes it harder, because it wants to become visible before root has a window + color: "red" + title: "red" + flags: Qt.Dialog + onVisibilityChanged: console.log("visibility " + visibility) + onVisibleChanged: console.log("visible " + visible) + } + } + } +} diff --git a/tests/auto/quick/qquickloader/data/itemLoaderWindow.qml b/tests/auto/quick/qquickloader/data/itemLoaderWindow.qml new file mode 100644 index 0000000000..69421448e0 --- /dev/null +++ b/tests/auto/quick/qquickloader/data/itemLoaderWindow.qml @@ -0,0 +1,22 @@ +import QtQuick 2.0 +import QtQuick.Window 2.1 + +Item { + width: 400 + height: 400 + objectName: "root Item" + + Loader { + sourceComponent: Window { + objectName: "red transient Window" + width: 100 + height: 100 + visible: true // makes it harder, because it wants to become visible before root has a window + color: "red" + title: "red" + flags: Qt.Dialog + onVisibilityChanged: console.log("visibility " + visibility) + onVisibleChanged: console.log("visible " + visible) + } + } +} diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index e557b592ee..65493f52e2 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -32,11 +32,15 @@ #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> #include <QtQml/qqmlincubator.h> +#include <QtQuick/qquickview.h> #include <private/qquickloader_p.h> +#include <private/qquickwindowmodule_p.h> #include "testhttpserver.h" #include "../../shared/util.h" #include "../shared/geometrytestutil.h" +Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests") + class SlowComponent : public QQmlComponent { Q_OBJECT @@ -112,6 +116,8 @@ private slots: void parented(); void sizeBound(); void QTBUG_30183(); + void transientWindow(); + void nestedTransientWindow(); void sourceComponentGarbageCollection(); @@ -1159,6 +1165,86 @@ void tst_QQuickLoader::QTBUG_30183() QCOMPARE(rect->height(), 120.0); } +void tst_QQuickLoader::transientWindow() // QTBUG-52944 +{ + QQuickView view; + view.setSource(testFileUrl("itemLoaderWindow.qml")); + QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject()); + QVERIFY(root); + QQuickLoader *loader = root->findChild<QQuickLoader *>(); + QVERIFY(loader); + QTRY_COMPARE(loader->status(), QQuickLoader::Ready); + QQuickWindowQmlImpl *loadedWindow = qobject_cast<QQuickWindowQmlImpl *>(loader->item()); + QVERIFY(loadedWindow); + QCOMPARE(loadedWindow->visibility(), QWindow::Hidden); + + QElapsedTimer timer; + qint64 viewVisibleTime = -1; + qint64 loadedWindowVisibleTime = -1; + connect(&view, &QWindow::visibleChanged, + [&viewVisibleTime, &timer]() { viewVisibleTime = timer.elapsed(); } ); + connect(loadedWindow, &QQuickWindowQmlImpl::visibilityChanged, + [&loadedWindowVisibleTime, &timer]() { loadedWindowVisibleTime = timer.elapsed(); } ); + timer.start(); + view.show(); + + QTest::qWaitForWindowExposed(&view); + QTRY_VERIFY(loadedWindowVisibleTime >= 0); + QVERIFY(viewVisibleTime >= 0); + + // now that we're sure they are both visible, which one became visible first? + qCDebug(lcTests) << "transient Window became visible" << (loadedWindowVisibleTime - viewVisibleTime) << "ms after the root Item"; + QVERIFY((loadedWindowVisibleTime - viewVisibleTime) >= 0); + + QWindowList windows = QGuiApplication::topLevelWindows(); + QTRY_COMPARE(windows.size(), 2); + + // TODO Ideally we would now close the outer window and make sure the transient window closes too. + // It works during manual testing because of QWindowPrivate::maybeQuitOnLastWindowClosed() + // but quitting an autotest doesn't make sense. +} + +void tst_QQuickLoader::nestedTransientWindow() // QTBUG-52944 +{ + QQuickView view; + view.setSource(testFileUrl("itemLoaderItemWindow.qml")); + QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject()); + QVERIFY(root); + QQuickLoader *loader = root->findChild<QQuickLoader *>(); + QVERIFY(loader); + QTRY_COMPARE(loader->status(), QQuickLoader::Ready); + QQuickItem *loadedItem = qobject_cast<QQuickItem *>(loader->item()); + QVERIFY(loadedItem); + QQuickWindowQmlImpl *loadedWindow = loadedItem->findChild<QQuickWindowQmlImpl *>(); + QVERIFY(loadedWindow); + QCOMPARE(loadedWindow->visibility(), QWindow::Hidden); + + QElapsedTimer timer; + qint64 viewVisibleTime = -1; + qint64 loadedWindowVisibleTime = -1; + connect(&view, &QWindow::visibleChanged, + [&viewVisibleTime, &timer]() { viewVisibleTime = timer.elapsed(); } ); + connect(loadedWindow, &QQuickWindowQmlImpl::visibilityChanged, + [&loadedWindowVisibleTime, &timer]() { loadedWindowVisibleTime = timer.elapsed(); } ); + timer.start(); + view.show(); + + QTest::qWaitForWindowExposed(&view); + QTRY_VERIFY(loadedWindowVisibleTime >= 0); + QVERIFY(viewVisibleTime >= 0); + + // now that we're sure they are both visible, which one became visible first? + qCDebug(lcTests) << "transient Window became visible" << (loadedWindowVisibleTime - viewVisibleTime) << "ms after the root Item"; + QVERIFY((loadedWindowVisibleTime - viewVisibleTime) >= 0); + + QWindowList windows = QGuiApplication::topLevelWindows(); + QTRY_COMPARE(windows.size(), 2); + + // TODO Ideally we would now close the outer window and make sure the transient window closes too. + // It works during manual testing because of QWindowPrivate::maybeQuitOnLastWindowClosed() + // but quitting an autotest doesn't make sense. +} + void tst_QQuickLoader::sourceComponentGarbageCollection() { QQmlEngine engine; diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index 39a8909617..06b76d129c 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -6143,9 +6143,17 @@ void tst_qquicktextinput::keypress_inputMask_withValidator_data() KeyList keys; // inserting '1111.11' then two backspaces keys << Qt::Key_Home << "1111.11" << Qt::Key_Backspace << Qt::Key_Backspace; - QTest::newRow("backspaceWithRegExp") << QString("9999.99;_") << 0.0 << 0.0 << 0 + QTest::newRow("backspaceWithRegExp") << QString("9999;_") << 0.0 << 0.0 << 0 << QString("/^[-]?((\\.\\d+)|(\\d+(\\.\\d+)?))$/") - << keys << QString("1111.") << QString("1111.__"); + << keys << QString("11") << QString("11__"); + } + { + KeyList keys; + // inserting '99' - QTBUG-64616 + keys << Qt::Key_Home << "99"; + QTest::newRow("invalidTextWithRegExp") << QString("X9;_") << 0.0 << 0.0 << 0 + << QString("/[+-][0+9]/") + << keys << QString("") << QString("__"); } } diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index 666f80fce1..fe9e8bb1fa 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -292,6 +292,70 @@ protected: } }; +class MouseRecordingWindow : public QQuickWindow +{ +public: + explicit MouseRecordingWindow(QWindow *parent = nullptr) : QQuickWindow(parent) { } + +protected: + void mousePressEvent(QMouseEvent *event) override { + qCDebug(lcTests) << event; + m_mouseEvents << *event; + QQuickWindow::mousePressEvent(event); + } + void mouseMoveEvent(QMouseEvent *event) override { + qCDebug(lcTests) << event; + m_mouseEvents << *event; + QQuickWindow::mouseMoveEvent(event); + } + void mouseReleaseEvent(QMouseEvent *event) override { + qCDebug(lcTests) << event; + m_mouseEvents << *event; + QQuickWindow::mouseReleaseEvent(event); + } + +public: + QList<QMouseEvent> m_mouseEvents; +}; + +class MouseRecordingItem : public QQuickItem +{ +public: + MouseRecordingItem(bool acceptTouch, QQuickItem *parent = nullptr) + : QQuickItem(parent) + , m_acceptTouch(acceptTouch) + { + setSize(QSizeF(300, 300)); + setAcceptedMouseButtons(Qt::LeftButton); + } + +protected: + void touchEvent(QTouchEvent* event) override { + event->setAccepted(m_acceptTouch); + m_touchEvents << *event; + qCDebug(lcTests) << "accepted?" << event->isAccepted() << event; + } + void mousePressEvent(QMouseEvent *event) override { + qCDebug(lcTests) << event; + m_mouseEvents << *event; + } + void mouseMoveEvent(QMouseEvent *event) override { + qCDebug(lcTests) << event; + m_mouseEvents << *event; + } + void mouseReleaseEvent(QMouseEvent *event) override { + qCDebug(lcTests) << event; + m_mouseEvents << *event; + } + +public: + QList<QMouseEvent> m_mouseEvents; + QList<QTouchEvent> m_touchEvents; + +private: + bool m_acceptTouch; +}; + class tst_qquickwindow : public QQmlDataTest { Q_OBJECT @@ -330,6 +394,8 @@ private slots: void mergeTouchPointLists(); void mouseFromTouch_basic(); + void synthMouseFromTouch_data(); + void synthMouseFromTouch(); void clearWindow(); @@ -705,9 +771,8 @@ void tst_qquickwindow::touchEvent_propagation() // single touch to top item, should be received by middle item QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window); - QTest::qWait(50); + QTRY_COMPARE(middleItem->lastEvent.touchPoints.count(), 1); QVERIFY(topItem->lastEvent.touchPoints.isEmpty()); - QCOMPARE(middleItem->lastEvent.touchPoints.count(), 1); QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty()); COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos)))); @@ -716,9 +781,8 @@ void tst_qquickwindow::touchEvent_propagation() // touch top and middle items, middle item should get both events QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window) .press(1, pointInMiddleItem, window); - QTest::qWait(50); + QTRY_COMPARE(middleItem->lastEvent.touchPoints.count(), 2); QVERIFY(topItem->lastEvent.touchPoints.isEmpty()); - QCOMPARE(middleItem->lastEvent.touchPoints.count(), 2); QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty()); COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, (QList<QTouchEvent::TouchPoint>() << makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos)) @@ -736,10 +800,9 @@ void tst_qquickwindow::touchEvent_propagation() // touch top and middle items, bottom item should get all events QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window) .press(1, pointInMiddleItem, window); - QTest::qWait(50); + QTRY_COMPARE(bottomItem->lastEvent.touchPoints.count(), 2); QVERIFY(topItem->lastEvent.touchPoints.isEmpty()); QVERIFY(middleItem->lastEvent.touchPoints.isEmpty()); - QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 2); COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, (QList<QTouchEvent::TouchPoint>() << makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos)) << makeTouchPoint(bottomItem, bottomItem->mapFromItem(middleItem, pos)) ))); @@ -1132,6 +1195,45 @@ void tst_qquickwindow::mouseFromTouch_basic() delete item; } +void tst_qquickwindow::synthMouseFromTouch_data() +{ + QTest::addColumn<bool>("synthMouse"); // AA_SynthesizeMouseForUnhandledTouchEvents + QTest::addColumn<bool>("acceptTouch"); // QQuickItem::touchEvent: setAccepted() + + QTest::newRow("no synth, accept") << false << true; // suitable for touch-capable UIs + QTest::newRow("no synth, don't accept") << false << false; + QTest::newRow("synth and accept") << true << true; + QTest::newRow("synth, don't accept") << true << false; // the default +} + +void tst_qquickwindow::synthMouseFromTouch() +{ + QFETCH(bool, synthMouse); + QFETCH(bool, acceptTouch); + + QCoreApplication::setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, synthMouse); + QScopedPointer<MouseRecordingWindow> window(new MouseRecordingWindow); + QScopedPointer<MouseRecordingItem> item(new MouseRecordingItem(acceptTouch, nullptr)); + item->setParentItem(window->contentItem()); + window->resize(250, 250); + window->setPosition(100, 100); + window->setTitle(QTest::currentTestFunction()); + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window.data())); + + QPoint p1 = QPoint(20, 20); + QPoint p2 = QPoint(30, 30); + QTest::touchEvent(window.data(), touchDevice).press(0, p1, window.data()); + QTest::touchEvent(window.data(), touchDevice).move(0, p2, window.data()); + QTest::touchEvent(window.data(), touchDevice).release(0, p2, window.data()); + + QCOMPARE(item->m_touchEvents.count(), 3); + QCOMPARE(item->m_mouseEvents.count(), acceptTouch ? 0 : 3); + QCOMPARE(window->m_mouseEvents.count(), 0); + for (const QMouseEvent &ev : item->m_mouseEvents) + QCOMPARE(ev.source(), Qt::MouseEventSynthesizedByQt); +} + void tst_qquickwindow::clearWindow() { QQuickWindow *window = new QQuickWindow; diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp index 978608def2..51755c8502 100644 --- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp +++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp @@ -27,6 +27,7 @@ ****************************************************************************/ #include <qtest.h> +#include <qtesttouch.h> #include <QtTest/QSignalSpy> #include <QtQml/qqmlcomponent.h> #include <QtQml/qqmlcontext.h> @@ -38,11 +39,81 @@ #include <QtCore/QDebug> #include <QtQml/qqmlengine.h> +#include <QtCore/QLoggingCategory> + #include <QtWidgets/QBoxLayout> #include <QtWidgets/QLabel> #include <QtQuickWidgets/QQuickWidget> +Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests") + +class MouseRecordingQQWidget : public QQuickWidget +{ +public: + explicit MouseRecordingQQWidget(QWidget *parent = nullptr) : QQuickWidget(parent) { + setAttribute(Qt::WA_AcceptTouchEvents); + } + +protected: + void mousePressEvent(QMouseEvent *event) override { + qCDebug(lcTests) << event; + m_mouseEvents << *event; + QQuickWidget::mousePressEvent(event); + } + void mouseMoveEvent(QMouseEvent *event) override { + qCDebug(lcTests) << event; + m_mouseEvents << *event; + QQuickWidget::mouseMoveEvent(event); + } + void mouseReleaseEvent(QMouseEvent *event) override { + qCDebug(lcTests) << event; + m_mouseEvents << *event; + QQuickWidget::mouseReleaseEvent(event); + } + +public: + QList<QMouseEvent> m_mouseEvents; +}; + +class MouseRecordingItem : public QQuickItem +{ +public: + MouseRecordingItem(bool acceptTouch, QQuickItem *parent = nullptr) + : QQuickItem(parent) + , m_acceptTouch(acceptTouch) + { + setSize(QSizeF(300, 300)); + setAcceptedMouseButtons(Qt::LeftButton); + } + +protected: + void touchEvent(QTouchEvent* event) override { + event->setAccepted(m_acceptTouch); + m_touchEvents << *event; + qCDebug(lcTests) << "accepted?" << event->isAccepted() << event; + } + void mousePressEvent(QMouseEvent *event) override { + qCDebug(lcTests) << event; + m_mouseEvents << *event; + } + void mouseMoveEvent(QMouseEvent *event) override { + qCDebug(lcTests) << event; + m_mouseEvents << *event; + } + void mouseReleaseEvent(QMouseEvent *event) override { + qCDebug(lcTests) << event; + m_mouseEvents << *event; + } + +public: + QList<QMouseEvent> m_mouseEvents; + QList<QTouchEvent> m_touchEvents; + +private: + bool m_acceptTouch; +}; + class tst_qquickwidget : public QQmlDataTest { Q_OBJECT @@ -67,8 +138,12 @@ private slots: void shortcuts(); void enterLeave(); void mouseEventWindowPos(); -}; + void synthMouseFromTouch_data(); + void synthMouseFromTouch(); +private: + QTouchDevice *device = QTest::createTouchDevice(); +}; tst_qquickwidget::tst_qquickwidget() { @@ -503,6 +578,48 @@ void tst_qquickwidget::mouseEventWindowPos() QTRY_VERIFY(rootItem->property("wasMoved").toBool()); } +void tst_qquickwidget::synthMouseFromTouch_data() +{ + QTest::addColumn<bool>("synthMouse"); // AA_SynthesizeMouseForUnhandledTouchEvents + QTest::addColumn<bool>("acceptTouch"); // QQuickItem::touchEvent: setAccepted() + + QTest::newRow("no synth, accept") << false << true; // suitable for touch-capable UIs + QTest::newRow("no synth, don't accept") << false << false; + QTest::newRow("synth and accept") << true << true; + QTest::newRow("synth, don't accept") << true << false; // the default +} + +void tst_qquickwidget::synthMouseFromTouch() +{ + QFETCH(bool, synthMouse); + QFETCH(bool, acceptTouch); + + QCoreApplication::setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, synthMouse); + QWidget window; + window.setAttribute(Qt::WA_AcceptTouchEvents); + QScopedPointer<MouseRecordingQQWidget> childView(new MouseRecordingQQWidget(&window)); + MouseRecordingItem *item = new MouseRecordingItem(acceptTouch, nullptr); + childView->setContent(QUrl(), nullptr, item); + window.resize(300, 300); + childView->resize(300, 300); + window.show(); + QVERIFY(QTest::qWaitForWindowActive(&window)); + QVERIFY(childView->quickWindow()->isVisible()); + QVERIFY(item->isVisible()); + + QPoint p1 = QPoint(20, 20); + QPoint p2 = QPoint(30, 30); + QTest::touchEvent(&window, device).press(0, p1, &window); + QTest::touchEvent(&window, device).move(0, p2, &window); + QTest::touchEvent(&window, device).release(0, p2, &window); + + QCOMPARE(item->m_touchEvents.count(), 3); + QCOMPARE(item->m_mouseEvents.count(), acceptTouch ? 0 : 3); + QCOMPARE(childView->m_mouseEvents.count(), 0); + for (const QMouseEvent &ev : item->m_mouseEvents) + QCOMPARE(ev.source(), Qt::MouseEventSynthesizedByQt); +} + QTEST_MAIN(tst_qquickwidget) #include "tst_qquickwidget.moc" diff --git a/tests/manual/imagehandler/large.svg b/tests/manual/imagehandler/large.svg new file mode 100644 index 0000000000..99b3b67616 --- /dev/null +++ b/tests/manual/imagehandler/large.svg @@ -0,0 +1,462 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + width="128" + height="128" + viewBox="0 0 105.427 137.439" + id="Livello_1" + xml:space="preserve" + style="overflow:visible"><defs + id="defs2727"><linearGradient + x1="26.294399" + y1="11.6704" + x2="71.901901" + y2="133.0273" + id="linearGradient3352" + xlink:href="#XMLID_34_" + gradientUnits="userSpaceOnUse" /><linearGradient + x1="36.838902" + y1="7.7075" + x2="82.446297" + y2="129.0645" + id="linearGradient3354" + xlink:href="#XMLID_34_" + gradientUnits="userSpaceOnUse" /><linearGradient + x1="33.882301" + y1="23.583" + x2="39.972198" + y2="23.583" + id="XMLID_34_" + gradientUnits="userSpaceOnUse"> + <stop + id="stop2672" + style="stop-color:#ff5d5d;stop-opacity:1" + offset="0" /> + <stop + id="stop2674" + style="stop-color:#e20800;stop-opacity:1" + offset="1" /> + </linearGradient><linearGradient + x1="33.882301" + y1="23.583" + x2="39.972198" + y2="23.583" + id="linearGradient3368" + xlink:href="#XMLID_34_" + gradientUnits="userSpaceOnUse" /><linearGradient + x1="54.356899" + y1="1.124" + x2="99.964401" + y2="122.481" + id="linearGradient3370" + xlink:href="#XMLID_34_" + gradientUnits="userSpaceOnUse" /><linearGradient + x1="15.8457" + y1="15.5972" + x2="61.453098" + y2="136.9541" + id="linearGradient3376" + xlink:href="#XMLID_34_" + gradientUnits="userSpaceOnUse" /><linearGradient + x1="43.438" + y1="5.2275" + x2="89.045403" + y2="126.5845" + id="linearGradient3382" + xlink:href="#XMLID_34_" + gradientUnits="userSpaceOnUse" /><linearGradient + x1="8.1176996" + y1="14.9019" + x2="70.759598" + y2="117.2331" + id="linearGradient3792" + xlink:href="#XMLID_30_" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9991,-4.18e-2,4.18e-2,0.9991,-2.4309,1.195)" /><linearGradient + x1="10.5708" + y1="10.1548" + x2="73.2117" + y2="112.4844" + id="linearGradient3794" + xlink:href="#XMLID_30_" + gradientUnits="userSpaceOnUse" /><linearGradient + x1="6.2178001" + y1="72.223602" + x2="79.360802" + y2="72.223602" + id="XMLID_26_" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,2.1512354)"> + <stop + id="stop2578" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2580" + style="stop-color:#eeeeec;stop-opacity:1" + offset="1" /> + </linearGradient><filter + id="filter5869"><feGaussianBlur + id="feGaussianBlur5871" + stdDeviation="1.2254964" + inkscape:collect="always" /></filter><filter + id="filter5873"><feGaussianBlur + id="feGaussianBlur5875" + stdDeviation="1.3615922" + inkscape:collect="always" /></filter><filter + id="filter2854"><feGaussianBlur + id="feGaussianBlur2856" + stdDeviation="0.8944793" + inkscape:collect="always" /></filter></defs> +<filter + id="AI_Sfocatura_1"> + <feGaussianBlur + id="feGaussianBlur2545" + stdDeviation="1" /> +</filter> +<g + transform="translate(-3.2052027,3.2058836)" + id="g2547"> + <g + transform="matrix(0.9982563,0,0,0.9982563,-1.5492234e-2,0.2232388)" + id="g2549"> + <g + id="g2551"> + <linearGradient + x1="6.2178001" + y1="68.029297" + x2="79.360802" + y2="68.029297" + id="XMLID_24_" + gradientUnits="userSpaceOnUse"> + <stop + id="stop2554" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2556" + style="stop-color:#eeeeec;stop-opacity:1" + offset="1" /> + </linearGradient> + <path + d="M 9.542,121.224 C 7.713,121.224 6.217,119.728 6.217,117.9 L 6.217,18.16 C 6.217,16.331 7.713,14.835 9.542,14.835 L 76.036,14.835 C 77.864,14.835 79.36,16.331 79.36,18.16 L 79.36,117.9 C 79.36,119.728 77.864,121.224 76.036,121.224 L 9.542,121.224 z" + id="path2558" + style="fill:url(#XMLID_24_)" /> + </g> + <g + id="g2560"> + <linearGradient + x1="10.5718" + y1="15.3989" + x2="73.212097" + y2="117.7277" + id="XMLID_25_" + gradientUnits="userSpaceOnUse"> + <stop + id="stop2563" + style="stop-color:#77b753;stop-opacity:1" + offset="0" /> + <stop + id="stop2565" + style="stop-color:#00892c;stop-opacity:1" + offset="1" /> + </linearGradient> + <path + d="M 11.204,18.159 C 10.29,18.159 9.542,18.907 9.542,19.821 L 9.542,116.237 C 9.542,117.151 10.29,117.899 11.204,117.899 L 74.375,117.899 C 75.289,117.899 76.037,117.151 76.037,116.237 L 76.037,19.821 C 76.037,18.907 75.289,18.159 74.375,18.159 L 11.204,18.159 z" + id="path2567" + style="fill:url(#XMLID_25_)" /> + </g> + </g> + <g + transform="matrix(0.9982563,0,0,0.9982563,1.05825,0.2232388)" + id="g2569"> + <path + d="M 11.639,126.468 C 9.811,126.468 8.314,124.972 8.314,123.143 L 8.314,23.403 C 8.314,21.574 9.811,20.078 11.639,20.078 L 78.134,20.078 C 79.962,20.078 81.458,21.574 81.458,23.403 L 81.458,123.143 C 81.458,124.972 79.962,126.468 78.134,126.468 L 23.696022,126.468 L 11.639,126.468 z" + transform="matrix(1.041449,0,0,1,-4.451967,3.1512354)" + id="path2575" + style="opacity:0.6;filter:url(#filter2854)" /><path + d="M 9.542,127.56924 C 7.714,127.56924 6.218,126.07324 6.218,124.24624 L 6.218,24.505236 C 6.218,22.677236 7.714,21.181236 9.542,21.181236 L 76.037,21.181236 C 77.865,21.181236 79.361,22.677236 79.361,24.505236 L 79.361,124.24624 C 79.361,126.07324 77.865,127.56924 76.037,127.56924 L 9.542,127.56924 z" + id="path2582" + style="fill:url(#XMLID_26_)" /> + <g + transform="translate(0,2.1512354)" + id="g2584"> + <g + transform="matrix(1.0276326,0,0,1,-2.2508995,0)" + id="g2586" + style="opacity:0.5;filter:url(#AI_Sfocatura_1)"> + <path + d="M 11.639,123.321 C 9.811,123.321 8.314,121.824 8.314,119.997 L 81.458,119.997 C 81.458,121.824 79.962,123.321 78.134,123.321 L 11.639,123.321 z" + id="path2588" /> + </g> + <linearGradient + x1="6.2178001" + y1="69.078102" + x2="79.360802" + y2="69.078102" + id="XMLID_27_" + gradientUnits="userSpaceOnUse"> + <stop + id="stop2591" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2593" + style="stop-color:#eeeeec;stop-opacity:1" + offset="1" /> + </linearGradient> + <path + d="M 9.542,122.272 C 7.714,122.272 6.218,120.776 6.218,118.947 L 6.218,19.207 C 6.218,17.378 7.714,15.882 9.542,15.882 L 76.037,15.882 C 77.865,15.882 79.361,17.378 79.361,19.207 L 79.361,118.947 C 79.361,120.776 77.865,122.272 76.037,122.272 L 9.542,122.272 z" + id="path2595" + style="fill:url(#XMLID_27_)" /> + </g> + <g + transform="translate(0,3.2268531)" + id="g2597"> + <g + transform="matrix(1.0368435,0,0,1,-3.0011994,-1.0756177)" + id="g2599" + style="opacity:0.5;filter:url(#AI_Sfocatura_1)"> + <path + d="M 11.639,120.175 C 9.811,120.175 8.314,118.679 8.314,116.85 L 81.458,116.85 C 81.458,118.679 79.962,120.175 78.134,120.175 L 11.639,120.175 z" + id="path2601" /> + </g> + <linearGradient + x1="6.2178001" + y1="65.931602" + x2="79.360802" + y2="65.931602" + id="XMLID_28_" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,-1.0756177)"> + <stop + id="stop2604" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2606" + style="stop-color:#eeeeec;stop-opacity:1" + offset="1" /> + </linearGradient> + <path + d="M 9.542,118.05038 C 7.714,118.05038 6.218,116.55438 6.218,114.72638 L 6.218,14.986382 C 6.218,13.157382 7.714,11.661382 9.542,11.661382 L 76.037,11.661382 C 77.865,11.661382 79.361,13.157382 79.361,14.986382 L 79.361,114.72638 C 79.361,116.55438 77.865,118.05038 76.037,118.05038 L 9.542,118.05038 z" + id="path2608" + style="fill:url(#XMLID_28_)" /> + </g> + <g + transform="translate(0,1.8317954)" + id="g2610"> + <g + transform="matrix(1.0184218,0,0,1.0158314,-1.4821779,-1.8527316)" + id="g2612" + style="opacity:0.5;filter:url(#AI_Sfocatura_1)"> + <path + d="M 10.639,117.029 C 8.811,117.029 7.314,115.532 7.314,113.704 L 7.314,13.964 C 7.314,12.135 8.811,10.639 10.639,10.639 L 77.134,10.639 C 78.962,10.639 80.458,12.135 80.458,13.964 L 80.458,113.704 C 80.458,115.532 78.962,117.029 77.134,117.029 L 10.639,117.029 z" + id="path2614" /> + </g> + <linearGradient + x1="6.2178001" + y1="62.785599" + x2="79.360802" + y2="62.785599" + id="XMLID_29_" + gradientUnits="userSpaceOnUse"> + <stop + id="stop2617" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2619" + style="stop-color:#eeeeec;stop-opacity:1" + offset="1" /> + </linearGradient> + <path + d="M 9.542,115.98 C 7.714,115.98 6.218,114.483 6.218,112.656 L 6.218,12.916 C 6.218,11.087 7.714,9.591 9.542,9.591 L 76.037,9.591 C 77.865,9.591 79.361,11.087 79.361,12.916 L 79.361,112.657 C 79.361,114.484 77.865,115.981 76.037,115.981 L 9.542,115.981 L 9.542,115.98 z" + id="path2621" + style="fill:url(#XMLID_29_)" /> + <linearGradient + x1="10.5708" + y1="10.1548" + x2="73.2117" + y2="112.4844" + id="XMLID_30_" + gradientUnits="userSpaceOnUse"> + <stop + id="stop2624" + style="stop-color:#73bdf2;stop-opacity:1" + offset="0" /> + <stop + id="stop2626" + style="stop-color:#3592ee;stop-opacity:1" + offset="1" /> + </linearGradient> + <path + d="M 11.204,12.916 C 10.289,12.916 9.541,13.664 9.541,14.578 L 9.541,110.994 C 9.541,111.909 10.289,112.657 11.204,112.657 L 74.373,112.657 C 75.288,112.657 76.036,111.909 76.036,110.994 L 76.036,14.578 C 76.036,13.664 75.288,12.916 74.373,12.916 L 11.204,12.916 L 11.204,12.916 z" + id="path2628" + style="fill:url(#linearGradient3794)" /> + </g> + </g> + <g + transform="matrix(0.9961334,-6.5068755e-2,6.5068755e-2,0.9961334,-5.7493275,-6.3015051)" + id="g2630"> + <g + transform="matrix(1.0311837,0,0,1.0154411,-2.8218065,-1.9088007)" + id="g2632" + style="opacity:0.6;filter:url(#filter5869)"> + <path + d="M 10.744,123.615 C 8.917,123.691 7.36,122.259 7.283,120.432 L 3.118,20.779 C 3.042,18.952 4.474,17.395 6.301,17.319 L 72.737,14.542 C 74.563,14.465 76.121,15.898 76.198,17.725 L 80.363,117.377 C 80.439,119.204 79.007,120.761 77.181,120.839 L 10.744,123.615 z" + id="path2634" /> + </g> + <g + id="g2636"> + + <linearGradient + x1="3.7607" + y1="67.532204" + x2="76.909698" + y2="67.532204" + id="XMLID_31_" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9991,-4.18e-2,4.18e-2,0.9991,-2.4309,1.195)"> + <stop + id="stop2639" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2641" + style="stop-color:#eeeeec;stop-opacity:1" + offset="1" /> + </linearGradient> + <path + d="M 9.695,121.518 C 7.868,121.595 6.311,120.163 6.234,118.335 L 2.069,18.682 C 1.993,16.855 3.425,15.298 5.252,15.222 L 71.688,12.444 C 73.514,12.368 75.072,13.8 75.149,15.627 L 79.314,115.28 C 79.391,117.106 77.959,118.663 76.131,118.741 L 9.695,121.518 z" + id="path2643" + style="fill:url(#XMLID_31_)" /> + </g> + <path + d="M 7.051,18.474 C 6.138,18.513 5.422,19.291 5.46,20.204 L 9.486,116.535 C 9.525,117.448 10.303,118.164 11.217,118.126 L 74.331,115.489 C 75.244,115.451 75.96,114.672 75.922,113.759 L 71.897,17.427 C 71.859,16.513 71.08,15.797 70.167,15.836 L 7.051,18.474 z" + id="path2652" + style="fill:url(#linearGradient3792);fill-opacity:1" /> + <path + d="M 9.5625,22.375 C 10.84375,52.927083 12.125,83.479167 13.40625,114.03125 C 32.885417,113.21875 52.364583,112.40625 71.84375,111.59375 C 70.5625,81.041667 69.28125,50.489583 68,19.9375 C 48.520833,20.75 29.041667,21.5625 9.5625,22.375 z" + id="path4189" + style="opacity:0.6;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:1.00000001, 1.00000001;stroke-dashoffset:0;stroke-opacity:1" /></g> + <g + transform="matrix(0.9982563,0,0,0.9982563,10.72193,-5.1454722)" + id="g2654"> + <g + transform="translate(-4.2156998e-8,1.0756177)" + id="g2656" + style="opacity:0.6;filter:url(#filter5873)"> + <path + d="M 10.854785,112.52047 C 9.0174891,112.09656 7.8676311,110.2731 8.2990859,108.46891 L 31.839177,9.9940152 C 32.271664,8.1888112 34.127539,7.0580233 35.964835,7.481942 L 102.78149,22.901224 C 104.61776,23.325142 105.76865,25.149615 105.33616,26.954819 L 81.79607,125.42768 C 81.364615,127.23289 79.507708,128.36368 77.671444,127.93976 L 10.854785,112.52047 z" + id="path2658" /> + </g> + <g + id="g2660"> + + <linearGradient + x1="16.688499" + y1="-8.9546003" + x2="94.108398" + y2="105.6356" + id="XMLID_33_" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9735,0.2287,-0.2287,0.9735,14.4454,7.996)"> + <stop + id="stop2663" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2665" + style="stop-color:#eeeeec;stop-opacity:1" + offset="1" /> + </linearGradient> + <path + d="M 12.707,111.688 C 10.927,111.271 9.813,109.472 10.231,107.692 L 33.037,10.593 C 33.455,8.813 35.254,7.698 37.034,8.116 L 101.767,23.32 C 103.546,23.738 104.661,25.537 104.243,27.317 L 81.436,124.415 C 81.019,126.195 79.219,127.31 77.44,126.892 L 12.707,111.688 z" + id="path2667" + style="fill:url(#XMLID_33_)" /> + </g> + <path + d="M 33.925,25.17 L 35.435,25.3 C 35.369,25.76 35.413,26.134 35.567,26.422 C 35.721,26.71 35.941,26.887 36.226,26.954 C 36.538,27.027 36.832,26.947 37.114,26.715 C 37.396,26.483 37.594,26.116 37.712,25.615 C 37.821,25.149 37.805,24.759 37.661,24.445 C 37.517,24.132 37.298,23.939 37.004,23.87 C 36.811,23.825 36.571,23.817 36.281,23.846 L 36.797,22.386 C 37.187,22.487 37.522,22.455 37.801,22.292 C 38.076,22.127 38.26,21.847 38.353,21.451 C 38.431,21.12 38.41,20.843 38.291,20.618 C 38.172,20.392 37.984,20.25 37.729,20.19 C 37.473,20.13 37.226,20.187 36.987,20.358 C 36.749,20.531 36.562,20.825 36.427,21.24 L 35.104,20.624 C 35.455,19.78 35.886,19.208 36.401,18.909 C 36.915,18.61 37.492,18.536 38.131,18.686 C 38.85,18.855 39.36,19.244 39.663,19.853 C 39.967,20.462 40.045,21.076 39.9,21.695 C 39.802,22.113 39.618,22.468 39.35,22.758 C 39.081,23.049 38.726,23.276 38.287,23.439 C 38.699,23.661 38.996,24.004 39.18,24.471 C 39.362,24.937 39.383,25.471 39.242,26.073 C 39.036,26.949 38.604,27.613 37.948,28.064 C 37.29,28.515 36.601,28.655 35.88,28.486 C 35.189,28.323 34.661,27.944 34.297,27.347 C 33.931,26.751 33.808,26.025 33.925,25.17 z" + id="path2676" + style="fill:url(#linearGradient3368);fill-opacity:1" /> + <linearGradient + x1="26.294399" + y1="11.6704" + x2="71.901901" + y2="133.0273" + id="XMLID_35_" + gradientUnits="userSpaceOnUse"> + <stop + id="stop2679" + style="stop-color:#ff8080;stop-opacity:1" + offset="0" /> + <stop + id="stop2681" + style="stop-color:#e20800;stop-opacity:1" + offset="1" /> + </linearGradient> + <path + d="M 32.977,38.964 C 33.619,37.58 34.903,36.55 35.811,35.945 C 36.752,35.319 37.49,34.55 37.729,33.53 C 38.094,31.979 36.471,30.257 34.621,31.997 C 33.74,29.616 31.507,30.433 31.143,31.984 C 30.903,33.003 31.223,34.019 31.786,35 C 32.329,35.946 33.021,37.439 32.977,38.964 z" + id="path2683" + style="fill:url(#linearGradient3352);fill-opacity:1" /> + <path + d="M 80.223,109.559 L 78.711,109.43 C 78.779,108.969 78.734,108.595 78.58,108.308 C 78.426,108.02 78.205,107.842 77.922,107.776 C 77.61,107.703 77.315,107.782 77.033,108.014 C 76.751,108.246 76.553,108.614 76.433,109.114 C 76.324,109.581 76.341,109.97 76.484,110.284 C 76.629,110.598 76.849,110.79 77.142,110.859 C 77.335,110.904 77.576,110.913 77.865,110.883 L 77.349,112.343 C 76.958,112.242 76.624,112.274 76.345,112.439 C 76.07,112.603 75.886,112.883 75.792,113.279 C 75.714,113.609 75.735,113.887 75.854,114.112 C 75.973,114.339 76.161,114.481 76.416,114.541 C 76.672,114.602 76.918,114.545 77.156,114.372 C 77.394,114.2 77.582,113.906 77.717,113.49 L 79.039,114.106 C 78.689,114.95 78.258,115.521 77.742,115.82 C 77.228,116.119 76.652,116.193 76.013,116.043 C 75.294,115.874 74.783,115.486 74.48,114.876 C 74.175,114.268 74.097,113.653 74.244,113.034 C 74.342,112.616 74.525,112.262 74.795,111.971 C 75.063,111.681 75.418,111.453 75.857,111.289 C 75.445,111.069 75.146,110.725 74.964,110.259 C 74.78,109.793 74.761,109.259 74.902,108.657 C 75.109,107.78 75.541,107.117 76.197,106.666 C 76.855,106.216 77.543,106.075 78.265,106.244 C 78.956,106.406 79.484,106.786 79.849,107.382 C 80.217,107.978 80.34,108.704 80.223,109.559 z" + id="path2694" + style="fill:#e20800;fill-opacity:1" /><path + d="M 81.063,95.83 C 80.422,97.214 79.138,98.244 78.23,98.85 C 77.29,99.477 76.55,100.246 76.311,101.264 C 75.947,102.815 77.57,104.536 79.419,102.797 C 80.301,105.178 82.533,104.361 82.898,102.811 C 83.138,101.791 82.819,100.776 82.255,99.795 C 81.711,98.849 81.021,97.355 81.063,95.83 z" + id="path2701" + style="fill:url(#linearGradient3382);fill-opacity:1" /> + <linearGradient + x1="54.356899" + y1="1.124" + x2="99.964401" + y2="122.481" + id="XMLID_39_" + gradientUnits="userSpaceOnUse"> + <stop + id="stop2704" + style="stop-color:#ff8080;stop-opacity:1" + offset="0" /> + <stop + id="stop2706" + style="stop-color:#e20800;stop-opacity:1" + offset="1" /> + </linearGradient> + <path + d="M 63.174,42.222 C 64.361,39.656 66.742,37.748 68.427,36.625 C 70.171,35.463 71.54,34.04 71.985,32.15 C 72.66,29.274 69.651,26.081 66.22,29.307 C 64.585,24.892 60.448,26.406 59.772,29.281 C 59.329,31.172 59.921,33.055 60.965,34.873 C 61.97,36.628 63.253,39.396 63.174,42.222 z" + id="path2708" + style="fill:url(#linearGradient3370);fill-opacity:1" /> + <linearGradient + x1="36.838902" + y1="7.7075" + x2="82.446297" + y2="129.0645" + id="XMLID_40_" + xlink:href="#XMLID_39_" + gradientUnits="userSpaceOnUse"> + <stop + id="stop2711" + style="stop-color:#ff8080;stop-opacity:1" + offset="0" /> + <stop + id="stop2713" + style="stop-color:#e20800;stop-opacity:1" + offset="1" /> + </linearGradient> + <path + d="M 55.486,74.959 C 56.672,72.393 59.054,70.485 60.737,69.362 C 62.481,68.2 63.851,66.777 64.296,64.886 C 64.97,62.01 61.962,58.818 58.532,62.043 C 56.897,57.628 52.759,59.142 52.082,62.018 C 51.638,63.908 52.23,65.792 53.275,67.609 C 54.281,69.364 55.565,72.132 55.486,74.959 z" + id="path2715" + style="fill:url(#linearGradient3354);fill-opacity:1" /> + <path + d="M 51.37,92.488 C 50.182,95.054 47.801,96.961 46.117,98.084 C 44.373,99.246 43.004,100.67 42.559,102.561 C 41.884,105.436 44.893,108.627 48.323,105.404 C 49.958,109.82 54.096,108.304 54.772,105.428 C 55.217,103.538 54.623,101.655 53.579,99.836 C 52.573,98.082 51.291,95.314 51.37,92.488 z" + id="path2724" + style="fill:url(#linearGradient3376);fill-opacity:1" /> + </g> +</g> +</svg> diff --git a/tests/manual/imagehandler/main.qml b/tests/manual/imagehandler/main.qml new file mode 100644 index 0000000000..55e5b89cae --- /dev/null +++ b/tests/manual/imagehandler/main.qml @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import QtQuick.Window 2.0 + +Window { + id: root + width: 480 + height: 480 + visible: true + Image { + id: svgImage + source: "large.svg" + height: parent.height - column.height + width: parent.width + sourceSize.height: height + sourceSize.width: width + } + ListModel { + id: imageFillModeModel + ListElement { text: "Stretch"; fillMode: Image.Stretch } + ListElement { text: "Preserve Aspect Fit"; fillMode: Image.PreserveAspectFit } + ListElement { text: "Preserve Aspect Crop"; fillMode: Image.PreserveAspectCrop } + ListElement { text: "Tile"; fillMode: Image.Tile } + ListElement { text: "Tile Vertically"; fillMode: Image.TileVertically } + ListElement { text: "Tile Horizontally"; fillMode: Image.TileHorizontally } + ListElement { text: "Pad"; fillMode: Image.Pad } + } + Column { + id: column + height: 75 + anchors.bottom: parent.bottom + Text { + text: "Click the options below to change the fill mode" + font.pointSize: 16 + } + + Row { + id: checkBoxesRow + width: parent.width + Repeater { + model: imageFillModeModel + Rectangle { + color: "lightGreen" + height: 50 + width: 100 + Text { + text: model.text + wrapMode: Text.Wrap + font.pointSize: 16 + anchors.fill: parent + MouseArea { + anchors.fill: parent + onClicked: { + svgImage.fillMode = model.fillMode + if (svgImage.fillMode === Image.Tile || svgImage.fillMode === Image.TileHorizontally || + svgImage.fillMode === Image.TileVertically) + svgImage.sourceSize.height = svgImage.sourceSize.width = 300 + else { + svgImage.sourceSize.height = svgImage.height + svgImage.sourceSize.width = svgImage.width + } + } + } + } + } + } + } + } +} |