From 6a19f2b5a8a14857eeb3c0f53cdb98c51526cbe5 Mon Sep 17 00:00:00 2001 From: "deepin-community-bot[bot]" <156989552+deepin-community-bot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 02:37:15 -0400 Subject: [PATCH] feat: update qt6-declarative to 6.6.2+dfsg-2 --- .QT-ENTERPRISE-LICENSE-AGREEMENT | 2353 ++--------------- .cmake.conf | 2 +- .tag | 2 +- debian/changelog | 45 +- debian/control | 47 +- debian/libqt6qml6.symbols | 2 +- debian/libqt6qmlcompiler6.symbols | 2 +- debian/libqt6qmlmodels6.symbols | 2 +- debian/libqt6qmlworkerscript6.install | 1 + .../libqt6qmlworkerscript6.lintian-overrides | 3 + debian/libqt6qmlworkerscript6.symbols | 9 + debian/libqt6quick6.symbols | 13 +- debian/libqt6quickcontrols2-6.symbols | 2 +- debian/libqt6quickshapes6.install | 1 + debian/libqt6quickshapes6.lintian-overrides | 3 + debian/libqt6quickshapes6.symbols | 19 + debian/libqt6quicktemplates2-6.symbols | 2 +- debian/libqt6quicktest6.symbols | 2 +- debian/libqt6quickwidgets6.symbols | 2 +- ...nction-for-properties-of-QQuickPalet.patch | 351 --- ...0002-Rename-accent-color-in-QPalette.patch | 41 - ...n-0003-Palette-Remove-redundant-code.patch | 85 - ...when-toggling-rendernode-based-items.patch | 71 - ...e-paste-action-if-clipboard-has-text.patch | 35 - debian/patches/series | 7 - debian/qml6-module-qtqml-workerscript.install | 1 - ...odule-qtqml-workerscript.lintian-overrides | 3 - debian/qml6-module-qtquick-shapes.install | 1 - ...l6-module-qtquick-shapes.lintian-overrides | 3 - ...clarative-doc-html.doc-base.qtlabsplatform | 2 +- .../qt6-declarative-doc-html.doc-base.qtqml | 2 +- ...eclarative-doc-html.doc-base.qtqmlcompiler | 2 +- ...t6-declarative-doc-html.doc-base.qtqmlcore | 2 +- ...-declarative-doc-html.doc-base.qtqmlmodels | 2 +- ...t6-declarative-doc-html.doc-base.qtqmltest | 2 +- ...rative-doc-html.doc-base.qtqmlworkerscript | 2 +- ...rative-doc-html.doc-base.qtqmlxmllistmodel | 2 +- .../qt6-declarative-doc-html.doc-base.qtquick | 2 +- ...larative-doc-html.doc-base.qtquickcontrols | 2 +- ...clarative-doc-html.doc-base.qtquickdialogs | 2 +- dependencies.yaml | 10 +- .../helloworld/chapter1/CMakeLists.txt | 22 + .../helloworld/chapter1/helloplugin.cpp | 19 + .../helloworld/chapter1/helloplugin.h | 21 + .../tutorials/helloworld/chapter1/plugin.json | 13 + .../tutorials/helloworld/chapter1/test.qml | 24 + .../helloworld/chapter2/CMakeLists.txt | 22 + .../helloworld/chapter2/helloplugin.cpp | 56 + .../helloworld/chapter2/helloplugin.h | 21 + .../tutorials/helloworld/chapter2/plugin.json | 13 + .../tutorials/helloworld/chapter2/test.qml | 24 + .../helloworld/chapter3/CMakeLists.txt | 22 + .../helloworld/chapter3/helloplugin.cpp | 64 + .../helloworld/chapter3/helloplugin.h | 21 + .../tutorials/helloworld/chapter3/plugin.json | 13 + .../tutorials/helloworld/chapter3/test.qml | 26 + .../dialcontrol/doc/src/dialcontrol.qdoc | 2 +- .../flipable/doc/src/flipable.qdoc | 2 +- .../customitems/painteditem/CMakeLists.txt | 6 +- .../embeddedinwidgets/embeddedinwidgets.qrc | 2 +- .../components/QuadPieMenu.qml | 6 +- .../quick/quickwidgets/quickwidget/main.cpp | 18 +- .../doc/src/customgeometry.qdoc | 33 +- .../scenegraph/customrendernode/main.qml | 5 + examples/quick/shared/CMakeLists.txt | 6 +- examples/quick/shared/LauncherList.qml | 16 +- .../shared/QtBundleQmlModuleForMacOS.cmake | 11 +- .../quick/shared/SimpleLauncherDelegate.qml | 73 +- examples/quickcontrols/CMakeLists.txt | 2 +- .../attachedstyleproperties/CMakeLists.txt | 6 +- .../quickcontrols/contactlist/CMakeLists.txt | 4 +- .../contactlist/ContactDelegate.ui.qml | 17 +- .../contactlist/ContactDialog.qml | 8 +- .../contactlist/ContactForm.ui.qml | 2 +- .../{contactlist.qml => ContactList.qml} | 18 +- .../contactlist/ContactView.ui.qml | 9 +- .../contactlist/SectionDelegate.ui.qml | 6 +- .../quickcontrols/contactlist/contactlist.pro | 15 +- .../contactlist/contactmodel.cpp | 2 +- .../quickcontrols/contactlist/contactmodel.h | 4 +- .../designer/Backend/ContactModel.qml | 2 +- examples/quickcontrols/contactlist/main.cpp | 8 +- examples/quickcontrols/contactlist/qmldir | 8 + .../filesystemexplorer/CMakeLists.txt | 5 + .../qtquickcontrols-filesystemexplorer.qdoc | 4 +- .../filesystemexplorer/filesystemexplorer.pro | 4 + .../imagine/automotive/qtquickcontrols2.conf | 8 +- examples/quickcontrols/quickcontrols.pro | 5 +- .../quickcontrols/wearable/CMakeLists.txt | 6 +- .../quickcontrols/wearable/Wearable/Main.qml | 2 + src/3rdparty/masm/WeakRandom.h | 40 +- src/3rdparty/masm/config.h | 40 +- src/3rdparty/masm/qt_attribution.json | 26 +- src/3rdparty/masm/stubs/ExecutableAllocator.h | 40 +- src/3rdparty/masm/stubs/JSGlobalData.h | 40 +- src/3rdparty/masm/stubs/Options.cpp | 40 +- src/3rdparty/masm/stubs/Options.h | 40 +- src/3rdparty/masm/stubs/SuperSampler.h | 40 +- src/3rdparty/masm/stubs/WTFStubs.cpp | 40 +- src/3rdparty/masm/stubs/WTFStubs.h | 40 +- .../masm/stubs/runtime/ConcurrentJSLock.h | 40 +- src/3rdparty/masm/stubs/runtime/VM.h | 40 +- src/3rdparty/masm/stubs/wtf/FastAllocBase.h | 40 +- src/3rdparty/masm/stubs/wtf/FastMalloc.h | 40 +- src/3rdparty/masm/stubs/wtf/HashMap.h | 40 +- src/3rdparty/masm/stubs/wtf/HashSet.h | 40 +- src/3rdparty/masm/stubs/wtf/Noncopyable.h | 40 +- src/3rdparty/masm/stubs/wtf/Optional.h | 40 +- src/3rdparty/masm/stubs/wtf/OwnPtr.h | 40 +- src/3rdparty/masm/stubs/wtf/PassOwnPtr.h | 40 +- src/3rdparty/masm/stubs/wtf/PassRefPtr.h | 40 +- src/3rdparty/masm/stubs/wtf/RefCounted.h | 40 +- src/3rdparty/masm/stubs/wtf/RefPtr.h | 40 +- src/3rdparty/masm/stubs/wtf/TypeTraits.h | 40 +- src/3rdparty/masm/stubs/wtf/UnusedParam.h | 40 +- src/3rdparty/masm/stubs/wtf/Vector.h | 40 +- src/3rdparty/masm/stubs/wtf/text/CString.h | 40 +- .../masm/stubs/wtf/text/StringBuilder.h | 40 +- src/3rdparty/masm/stubs/wtf/text/WTFString.h | 40 +- src/3rdparty/masm/stubs/wtf/unicode/Unicode.h | 40 +- .../masm/stubs/yarr/YarrUnicodeProperties.cpp | 40 +- .../masm/wtf/OSAllocatorIntegrity.cpp | 42 +- src/qml/Qt6QmlDeploySupport.cmake | 10 + src/qml/Qt6QmlMacros.cmake | 203 +- .../doc/src/cppintegration/definetypes.qdoc | 2 +- .../cppintegration/extending-tutorial.qdoc | 21 +- src/qml/doc/src/qmlfunctions.qdoc | 5 +- .../qmllanguageref/documents/definetypes.qdoc | 53 +- .../syntax/objectattributes.qdoc | 2 +- src/qml/jsapi/qjsvalue.cpp | 12 +- src/qml/jsruntime/qv4engine.cpp | 48 +- src/qml/jsruntime/qv4engine_p.h | 1 + src/qml/jsruntime/qv4executableallocator_p.h | 2 +- .../qv4executablecompilationunit_p.h | 5 + src/qml/jsruntime/qv4jscall_p.h | 166 +- src/qml/jsruntime/qv4qmlcontext.cpp | 36 +- src/qml/jsruntime/qv4qobjectwrapper.cpp | 32 +- src/qml/qml/qqmlboundsignal.cpp | 2 +- src/qml/qml/qqmlcomponent_p.h | 5 +- src/qml/qml/qqmlextensionplugin.cpp | 16 +- src/qml/qml/qqmlmetaobject.cpp | 38 - src/qml/qml/qqmlmetaobject_p.h | 101 +- src/qml/qml/qqmlobjectcreator.cpp | 4 +- src/qml/qml/qqmlprivate.h | 4 +- src/qml/qml/qqmlpropertycachecreator_p.h | 11 +- src/qml/types/qqmlbind.cpp | 8 +- src/qml/types/qqmlconnections.cpp | 199 +- src/qml/types/qqmlconnections_p.h | 3 +- src/qmlcompiler/doc/qtqmlcompiler-index.qdoc | 44 +- src/qmlcompiler/doc/qtqmlcompiler.qdocconf | 2 + .../doc/src/qtqmlcompiler-module.qdoc | 5 +- src/qmlcompiler/doc/src/tutorial.qdoc | 229 ++ src/qmlcompiler/qqmljsbasicblocks.cpp | 43 +- src/qmlcompiler/qqmljsbasicblocks_p.h | 4 +- src/qmlcompiler/qqmljscodegenerator.cpp | 21 +- src/qmlcompiler/qqmljstyperesolver.cpp | 8 - src/qmldom/qqmldomreformatter.cpp | 41 +- src/qmlmodels/qqmldelegatemodel.cpp | 54 +- src/qmlmodels/qqmldelegatemodel_p_p.h | 7 +- src/qmltest/SignalSpy.qml | 33 +- src/qmltest/TestCase.qml | 13 +- src/qmltest/doc/src/qtquicktest-index.qdoc | 2 +- src/qmltest/doc/src/qtquicktest.qdoc | 6 +- .../qqmltoolingsettings.cpp | 4 +- src/qmltyperegistrar/qqmltyperegistrar.cpp | 7 +- src/quick/doc/snippets/qml/externaldrag.qml | 6 +- .../qml/treeview/qml-customdelegate.qml | 69 +- src/quick/doc/src/concepts/input/focus.qdoc | 4 +- src/quick/handlers/qquickpointerhandler.cpp | 3 + src/quick/handlers/qquickpointerhandler_p_p.h | 1 + .../handlers/qquicksinglepointhandler.cpp | 13 +- src/quick/handlers/qquicktaphandler.cpp | 42 +- src/quick/handlers/qquicktaphandler_p.h | 5 +- src/quick/items/qquickanimatedimage.cpp | 14 +- src/quick/items/qquickborderimage.cpp | 6 +- src/quick/items/qquickdrag.cpp | 3 +- src/quick/items/qquickimagebase.cpp | 9 +- src/quick/items/qquickitem.cpp | 14 +- src/quick/items/qquickitem.h | 4 + src/quick/items/qquicklistview.cpp | 8 +- src/quick/items/qquickpathview.cpp | 3 +- src/quick/items/qquicktableview.cpp | 37 +- src/quick/items/qquicktableview_p_p.h | 1 + src/quick/items/qquicktext.cpp | 76 +- src/quick/items/qquicktextedit.cpp | 85 +- src/quick/items/qquicktextedit_p.h | 1 + src/quick/items/qquicktextinput.cpp | 75 +- src/quick/items/qquicktextinput_p.h | 1 + src/quick/items/qquicktreeview.cpp | 67 +- src/quick/items/qquickwindow.cpp | 8 +- .../scenegraph/coreapi/qsgbatchrenderer.cpp | 7 +- src/quick/scenegraph/qsgdefaultglyphnode.cpp | 7 +- src/quick/scenegraph/qsgrenderloop.cpp | 11 + src/quick/util/qquickanimatorjob.cpp | 4 +- src/quick/util/qquickanimatorjob_p.h | 2 +- src/quick/util/qquickdeliveryagent.cpp | 18 +- src/quickcontrols/basic/Dial.qml | 7 +- src/quickcontrols/basic/Menu.qml | 4 +- .../qtquickcontrols-progressbar-custom.qml | 29 + .../qtquickcontrols-selectionrectangle.qml | 2 - .../src/qtquickcontrols-configuration.qdoc | 14 +- .../doc/src/qtquickcontrols-customize.qdoc | 3 + .../src/qtquickcontrols-fileselectors.qdoc | 13 +- .../doc/src/qtquickcontrols-material.qdoc | 4 + src/quickcontrols/fusion/Dial.qml | 7 +- src/quickcontrols/fusion/Menu.qml | 4 +- src/quickcontrols/fusion/TabButton.qml | 13 +- .../fusion/impl/qquickfusionbusyindicator.cpp | 13 +- src/quickcontrols/imagine/Dial.qml | 7 +- src/quickcontrols/imagine/Menu.qml | 4 +- .../imagine/qquickimaginetheme.cpp | 10 +- src/quickcontrols/ios/Menu.qml | 4 +- src/quickcontrols/material/Button.qml | 7 +- src/quickcontrols/material/Dial.qml | 7 +- src/quickcontrols/material/Dialog.qml | 5 +- src/quickcontrols/material/Menu.qml | 4 +- .../material/qquickmaterialstyle.cpp | 39 + .../material/qquickmaterialstyle_p.h | 8 + .../material/qquickmaterialtheme.cpp | 18 +- src/quickcontrols/universal/Dial.qml | 7 +- src/quickcontrols/universal/Menu.qml | 4 +- .../quickdialogs/qquickabstractdialog.cpp | 62 +- .../quickdialogs/qquickabstractdialog_p.h | 16 +- .../quickdialogs/qquickmessagedialog.cpp | 1 + .../qml/+Fusion/FileDialog.qml | 27 +- .../qml/+Fusion/FileDialogDelegate.qml | 2 +- .../qml/+Imagine/FileDialog.qml | 26 +- .../qml/+Imagine/FileDialogDelegate.qml | 2 +- .../qml/+Material/FileDialog.qml | 24 +- .../qml/+Material/FileDialogDelegate.qml | 2 +- .../qml/+Universal/FileDialog.qml | 27 +- .../qml/+Universal/FileDialogDelegate.qml | 2 +- .../quickdialogsquickimpl/qml/FileDialog.qml | 23 +- .../qml/FileDialogDelegate.qml | 2 +- .../qquickfiledialogdelegate.cpp | 11 + .../qquickfiledialogimpl.cpp | 79 +- .../qquickfiledialogimpl_p.h | 8 + .../qquickfiledialogimpl_p_p.h | 4 + .../controls/DefaultTextArea.qml | 4 +- src/quickshapes/qquickshape.cpp | 2 + src/quicktemplates/qquickabstractbutton.cpp | 2 +- .../qquickapplicationwindow.cpp | 7 +- src/quicktemplates/qquickdrawer.cpp | 93 +- src/quicktemplates/qquickdrawer_p_p.h | 8 +- src/quicktemplates/qquickoverlay.cpp | 2 +- src/quicktemplates/qquickpane.cpp | 17 +- src/quicktemplates/qquickpane_p_p.h | 1 + src/quicktemplates/qquickpopup.cpp | 28 +- src/quicktemplates/qquickpopup_p_p.h | 6 +- src/quicktemplates/qquickscrollview.cpp | 6 + .../qquickselectionrectangle.cpp | 22 +- src/quickwidgets/qquickwidget.cpp | 20 +- .../tst_qqmldebugtranslationclient.cpp | 2 - tests/auto/qml/qjsvalue/tst_qjsvalue.cpp | 19 + .../qml/qmlcppcodegen/data/CMakeLists.txt | 4 + .../qml/qmlcppcodegen/data/StoreMetaEnum.qml | 12 + tests/auto/qml/qmlcppcodegen/data/asCast.qml | 10 + .../qml/qmlcppcodegen/data/enumConversion.qml | 5 + .../auto/qml/qmlcppcodegen/data/failures.qml | 2 + .../qmlcppcodegen/data/reduceWithNullThis.qml | 18 + .../qml/qmlcppcodegen/data/renameAdjust.qml | 19 + .../qml/qmlcppcodegen/data/scopeIdLookup.qml | 20 + .../auto/qml/qmlcppcodegen/data/urlString.qml | 7 + .../qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 65 + .../data/arrayEndComma.formatted.qml | 4 + .../auto/qml/qmlformat/data/arrayEndComma.qml | 8 + .../data/dontRemoveComments.formatted.qml | 12 +- .../qml/qmlformat/data/dontRemoveComments.qml | 8 +- .../qmlformat/data/escapeChars.formatted.qml | 15 + tests/auto/qml/qmlformat/data/escapeChars.qml | 16 + .../data/objectDestructuring.formatted.qml | 38 +- tests/auto/qml/qmlformat/tst_qmlformat.cpp | 3 + tests/auto/qml/qmlsplitlib/CMakeLists.txt | 15 +- tests/auto/qml/qmlsplitlib/lib2.cpp | 5 + tests/auto/qml/qmlsplitlib/lib2.h | 30 + tests/auto/qml/qmlsplitlib/main2.qml | 8 + .../auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp | 13 + tests/auto/qml/qmltc/CMakeLists.txt | 3 + .../CMakeLists.txt | 28 + .../HelloExportedWorldNoFileName.qml | 5 + .../auto/qml/qmltc/QmltcTests/CMakeLists.txt | 1 + .../qmltc/QmltcTests/signalConnections.qml | 46 + tests/auto/qml/qmltc/tst_qmltc.cpp | 35 + tests/auto/qml/qmltc/tst_qmltc.h | 2 + .../qmltyperegistrar/tst_qmltyperegistrar.cpp | 4 +- .../qmltyperegistrar/tst_qmltyperegistrar.h | 2 +- .../data/clearCacheDuringInsertion.qml | 138 + .../tst_qqmldelegatemodel.cpp | 11 + .../qqmlecmascript/data/scriptConnect.8.qml | 21 + .../qqmlecmascript/data/scriptConnect.9.qml | 30 + .../data/scriptConnect.deletion.qml | 36 + .../data/scriptConnectSingleton.qml | 21 + .../data/scriptDisconnect.5.qml | 19 + .../qml/qqmlecmascript/tst_qqmlecmascript.cpp | 130 + .../reformatter/requiredReformatted2.qml | 4 +- .../auto/qmltest/selftests/tst_signalspy.qml | 53 + tests/auto/quick/CMakeLists.txt | 4 +- .../data/changingCursor.qml | 37 + .../qquickhoverhandler/data/hoverHandler.qml | 17 + .../tst_qquickhoverhandler.cpp | 72 + .../qquicktaphandler/data/Button.qml | 16 +- .../qquicktaphandler/data/buttons.qml | 12 +- .../data/nestedAndSibling.qml | 39 + .../qquicktaphandler/tst_qquicktaphandler.cpp | 273 +- .../tst_qquickanimatedimage.cpp | 31 + .../tst_qquickdeliveryagent.cpp | 6 +- .../tst_qquickdragattached.cpp | 10 +- .../quick/qquickimage/data/statusChanged.qml | 25 + .../quick/qquickimage/tst_qquickimage.cpp | 26 + .../data/changingOrientationWithListModel.qml | 47 + .../changingOrientationWithObjectModel.qml | 54 + .../qquicklistview2/tst_qquicklistview2.cpp | 37 + .../qquickmousearea/data/cursorUpdating.qml | 71 + .../qquickmousearea/tst_qquickmousearea.cpp | 38 + .../data/mousePressAfterFlick.qml | 61 + .../qquickpathview/tst_qquickpathview.cpp | 43 + tests/auto/quick/qquicktextedit/BLACKLIST | 7 - .../data/resizeTextEditPolish.qml | 42 + .../qquicktextedit/tst_qquicktextedit.cpp | 49 +- tests/auto/quickcontrols/CMakeLists.txt | 4 +- .../controls/data/tst_abstractbutton.qml | 137 +- .../controls/data/tst_action.qml | 18 +- .../controls/data/tst_actiongroup.qml | 66 +- .../controls/data/tst_busyindicator.qml | 33 +- .../controls/data/tst_button.qml | 64 +- .../controls/data/tst_buttongroup.qml | 74 +- .../controls/data/tst_calendarmodel.qml | 10 +- .../controls/data/tst_checkbox.qml | 46 +- .../controls/data/tst_checkdelegate.qml | 28 +- .../controls/data/tst_container.qml | 30 +- .../controls/data/tst_control.qml | 152 +- .../controls/data/tst_dayofweekrow.qml | 8 +- .../controls/data/tst_delaybutton.qml | 28 +- .../quickcontrols/controls/data/tst_dial.qml | 109 +- .../controls/data/tst_dialog.qml | 55 +- .../quickcontrols/controls/data/tst_frame.qml | 12 +- .../controls/data/tst_groupbox.qml | 12 +- .../controls/data/tst_itemdelegate.qml | 18 +- .../controls/data/tst_menuitem.qml | 24 +- .../controls/data/tst_monthgrid.qml | 46 +- .../quickcontrols/controls/data/tst_popup.qml | 2 + .../controls/data/tst_scrollview.qml | 32 + .../controls/data/tst_selectionrectangle.qml | 79 +- .../controls/data/tst_stackview.qml | 2 +- .../controls/data/tst_textarea.qml | 10 +- .../controls/data/tst_textfield.qml | 8 +- .../controls/data/tst_tooltip.qml | 61 +- .../palette/qtquickcontrols2.conf | 4 +- .../qquickiconimage/tst_qquickiconimage.cpp | 51 +- .../qtquickcontrols2.conf | 4 +- .../data/scrollableWithFixedHeight.qml | 27 + .../qquickmenu/tst_qquickmenu.cpp | 1 + .../data/applicationwindow-hover.qml | 16 +- .../qquickpopup/data/noDimmer.qml | 22 + .../qquickpopup/data/window-hover.qml | 15 +- .../qquickpopup/tst_qquickpopup.cpp | 33 +- .../qtquickcontrols2.conf | 4 +- .../data/colorDialogWithoutWindow.qml | 27 + .../colorDialogWithoutWindowVisibleTrue.qml | 28 + .../data/windowSwapping.qml | 58 + .../tst_qquickcolordialogimpl.cpp | 58 + .../tst_qquickfiledialogimpl.cpp | 134 + .../qquickwidget/data/tapHandler.qml | 11 + .../qquickwidget/tst_qquickwidget.cpp | 63 + .../imagine/musicplayer/qtquickcontrols2.conf | 8 +- .../material/pages/ButtonPage.qml | 8 +- tools/qmllint/main.cpp | 44 +- 367 files changed, 6329 insertions(+), 5424 deletions(-) create mode 100644 debian/libqt6qmlworkerscript6.install create mode 100644 debian/libqt6qmlworkerscript6.lintian-overrides create mode 100644 debian/libqt6qmlworkerscript6.symbols create mode 100644 debian/libqt6quickshapes6.install create mode 100644 debian/libqt6quickshapes6.lintian-overrides create mode 100644 debian/libqt6quickshapes6.symbols delete mode 100644 debian/patches/deepin-0001-Add-the-reset-function-for-properties-of-QQuickPalet.patch delete mode 100644 debian/patches/deepin-0002-Rename-accent-color-in-QPalette.patch delete mode 100644 debian/patches/deepin-0003-Palette-Remove-redundant-code.patch delete mode 100644 debian/patches/deepin-0004-Fix-corrupt-rendering-when-toggling-rendernode-based-items.patch delete mode 100644 debian/patches/deepin-0005-TextField-Only-enable-paste-action-if-clipboard-has-text.patch delete mode 100644 debian/patches/series delete mode 100644 debian/qml6-module-qtqml-workerscript.lintian-overrides delete mode 100644 debian/qml6-module-qtquick-shapes.lintian-overrides create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter1/CMakeLists.txt create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.cpp create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.h create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter1/plugin.json create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter1/test.qml create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter2/CMakeLists.txt create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.cpp create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.h create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter2/plugin.json create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter2/test.qml create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter3/CMakeLists.txt create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.cpp create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.h create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter3/plugin.json create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter3/test.qml rename examples/quickcontrols/contactlist/{contactlist.qml => ContactList.qml} (72%) create mode 100644 examples/quickcontrols/contactlist/qmldir create mode 100644 src/qmlcompiler/doc/src/tutorial.qdoc create mode 100644 tests/auto/qml/qmlcppcodegen/data/StoreMetaEnum.qml create mode 100644 tests/auto/qml/qmlcppcodegen/data/reduceWithNullThis.qml create mode 100644 tests/auto/qml/qmlcppcodegen/data/renameAdjust.qml create mode 100644 tests/auto/qml/qmlcppcodegen/data/scopeIdLookup.qml create mode 100644 tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml create mode 100644 tests/auto/qml/qmlformat/data/arrayEndComma.qml create mode 100644 tests/auto/qml/qmlformat/data/escapeChars.formatted.qml create mode 100644 tests/auto/qml/qmlformat/data/escapeChars.qml create mode 100644 tests/auto/qml/qmlsplitlib/lib2.cpp create mode 100644 tests/auto/qml/qmlsplitlib/lib2.h create mode 100644 tests/auto/qml/qmlsplitlib/main2.qml create mode 100644 tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/CMakeLists.txt create mode 100644 tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/HelloExportedWorldNoFileName.qml create mode 100644 tests/auto/qml/qmltc/QmltcTests/signalConnections.qml create mode 100644 tests/auto/qml/qqmldelegatemodel/data/clearCacheDuringInsertion.qml create mode 100644 tests/auto/qml/qqmlecmascript/data/scriptConnect.8.qml create mode 100644 tests/auto/qml/qqmlecmascript/data/scriptConnect.9.qml create mode 100644 tests/auto/qml/qqmlecmascript/data/scriptConnect.deletion.qml create mode 100644 tests/auto/qml/qqmlecmascript/data/scriptConnectSingleton.qml create mode 100644 tests/auto/qml/qqmlecmascript/data/scriptDisconnect.5.qml create mode 100644 tests/auto/qmltest/selftests/tst_signalspy.qml create mode 100644 tests/auto/quick/pointerhandlers/qquickhoverhandler/data/changingCursor.qml create mode 100644 tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverHandler.qml create mode 100644 tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml create mode 100644 tests/auto/quick/qquickimage/data/statusChanged.qml create mode 100644 tests/auto/quick/qquicklistview2/data/changingOrientationWithListModel.qml create mode 100644 tests/auto/quick/qquicklistview2/data/changingOrientationWithObjectModel.qml create mode 100644 tests/auto/quick/qquickmousearea/data/cursorUpdating.qml create mode 100644 tests/auto/quick/qquickpathview/data/mousePressAfterFlick.qml create mode 100644 tests/auto/quick/qquicktextedit/data/resizeTextEditPolish.qml create mode 100644 tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml create mode 100644 tests/auto/quickcontrols/qquickpopup/data/noDimmer.qml create mode 100644 tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindow.qml create mode 100644 tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindowVisibleTrue.qml create mode 100644 tests/auto/quickdialogs/qquickcolordialogimpl/data/windowSwapping.qml create mode 100644 tests/auto/quickwidgets/qquickwidget/data/tapHandler.qml diff --git a/.QT-ENTERPRISE-LICENSE-AGREEMENT b/.QT-ENTERPRISE-LICENSE-AGREEMENT index ff775f951..2d225ecf6 100644 --- a/.QT-ENTERPRISE-LICENSE-AGREEMENT +++ b/.QT-ENTERPRISE-LICENSE-AGREEMENT @@ -1,2091 +1,262 @@ -QT LICENSE AGREEMENT -Agreement version 4.4.1 - -This Qt License Agreement ("Agreement") is a legal agreement for the licensing -of Licensed Software (as defined below) between The Qt Company (as defined -below) and the Licensee who has accepted the terms of this Agreement by signing -this Agreement or by downloading or using the Licensed Software or in any other -appropriate means. - -Capitalized terms used herein are defined in Section 1. - -WHEREAS: - (A) Licensee wishes to use the Licensed Software for the purpose of - developing and distributing Applications and/or Devices (each as defined - below); - (B) The Qt Company is willing to grant the Licensee a right to use Licensed - Software for such a purpose pursuant to term and conditions of this - Agreement; and - (C) Parties wish to enable that their respective Affiliates also can sell - and purchase licenses to serve Licensee Affiliates' needs to use Licensed - Software pursuant to terms of the Agreement. Any such license purchases by - Licensee Affiliates from The Qt Company or its Affiliates will create - contractual relationship directly between the relevant The Qt Company and - the respective ordering Licensee Affiliate "Acceding Agreement"). - Accordingly, Licensee shall not be a party to any such Acceding Agreement, - and no rights or obligations are created to the Licensee thereunder but all - rights and obligations under such Acceding Agreement are vested and borne - solely by the ordering Licensee Affiliate and the relevant The Qt Company - as a contracting parties under such Acceding Agreement. - -NOW, THEREFORE, THE PARTIES HEREBY AGREE AS FOLLOWS: - -1. DEFINITIONS - -"Affiliate" of a Party shall mean an entity - (i) which is directly or indirectly controlling such Party; - (ii) which is under the same direct or indirect ownership or control as - such Party; or - (iii) which is directly or indirectly owned or controlled by such Party. -For these purposes, an entity shall be treated as being controlled by another -if that other entity has fifty percent (50 %) or more of the votes in such -entity, is able to direct its affairs and/or to control the composition of its -board of directors or equivalent body. - -"Add-on Products" shall mean The Qt Company's specific add-on software products -which are not licensed as part of The Qt Company's standard product offering, -but shall be included into the scope of Licensed Software only if so -specifically agreed between the Parties. - -"Agreement Term" shall mean the validity period of this Agreement, as set forth -in Section 12. - -"Applications" shall mean software products created using the Licensed -Software, which include the Redistributables, or part thereof. - -"Contractor(s)" shall mean third party consultants, distributors and -contractors performing services to the Licensee under applicable contractual -arrangement. - -"Customer(s)" shall mean Licensee's customers to whom Licensee, directly or -indirectly, distributes copies of the Redistributables as integrated or -incorporated into Applications or Devices. - -"Data Protection Legislation" shall mean the General Data Protection Regulation -(EU 2016/679) (GDPR) and any national implementing laws, regulations and -secondary legislation, as may be amended or updated from time to time, as well -as any other data protection laws or regulations applicable in relevant -territory. - -"Deployment Platforms" shall mean target operating systems and/or hardware -specified in the License Certificate, on which the Redistributables can be -distributed pursuant to the terms and conditions of this Agreement. - -"Designated User(s)" shall mean the employee(s) of Licensee or Licensee's -Affiliates acting within the scope of their employment or Licensee's -Contractors acting within the scope of their services on behalf of Licensee. - -"Development License" shall mean the license needed by the Licensee for each -Designated User to use the Licensed Software under the license grant described -in Section 3.1 of this Agreement. Development Licenses are available per -respective Licensed Software products, each product having its designated scope -and purpose of use. - -"Development License Term" shall mean the agreed validity period of the -Development License or QA Tools license during which time the relevant Licensed -Software product can be used pursuant to this Agreement. Agreed Development -License Term, as ordered and paid for by the Licensee, shall be memorialized in -the applicable License Certificate. - -"Development Platforms" shall mean those host operating systems specified in -the License Certificate, in which the Licensed Software can be used under the -Development License. - -"Devices" shall mean - (1) hardware devices or products that - i. are manufactured and/or distributed by the Licensee, its Affiliates, - Contractors or Customers, and - ii. incorporate, integrate or link to Applications such that - substantial functionality of such unit, when used by an End User, - is provided by Application(s) or otherwise depends on the Licensed - Software, regardless of whether the Application is developed by - Licensee or its Contractors; or - (2) Applications designed for the hardware devices specified in item (1). - - Devices covered by this Agreement shall be specified in Appendix 2 or in a - quote. - -"Distribution License(s)" shall mean a royalty-bearing license required for any -kind of sale, trade, exchange, loan, lease, rental or other distribution by or -on behalf of Licensee to a third party of Redistributables in connection with -Devices pursuant to license grant described in Section 3.3 of this Agreement. -Distribution Licensed are sold separately for each type of Device respectively -and cannot be used for any type of Devices at Licensee's discretion. - -"Distribution License Packs" shall mean set of prepaid Distribution Licenses -for distribution of Redistributables, as defined in The Qt Company's standard -price list, quote, Purchase Order confirmation or in an Appendix 2 hereto, as -the case may be. - -"End User" shall mean the final end user of the Application or a Device. - -"Evaluation License Term" shall mean a time period specified in the License -Certificate for the Licensee to use the relevant Licensed Software for -evaluation purposes according to Section 3.6 herein. - -"Intellectual Property Rights" shall mean patents (including utility models), -design patents, and designs (whether or not capable of registration), chip -topography rights and other like protection, copyrights, trademarks, service -marks, trade names, logos or other words or symbols and any other form of -statutory protection of any kind and applications for any of the foregoing as -well as any trade secrets. - -"License Certificate" shall mean a certificate generated by The Qt Company for -each Designated User respectively upon them downloading the Licensed Software, -which will be available under respective Designated User's Qt Account at -account.qt.io. License Certificates will specify relevant information -pertaining the Licensed Software purchased by Licensee and Designated User's -license to the Licensed Software. - -"License Fee" shall mean the fee charged to the Licensee for rights granted -under the terms of this Agreement. - -"Licensed Software" shall mean specified product of commercially licensed -version of Qt Software and/or QA Tools defined in Appendix 1 and/or Appendix 3, -which Licensee has purchased and which is provided to Licensee under the terms -of this Agreement. Licensed Software shall include corresponding online or -electronic documentation, associated media and printed materials, including the -source code (where applicable), example programs and the documentation. -Licensed Software does not include Third Party Software (as defined in Section -4) or Open Source Qt. The Qt Company may, in the course of its development -activities, at its free and absolute discretion and without any obligation to -send or publish any notifications to the Licensee or in general, make changes, -additions or deletions in the components and functionalities of the Licensed -Software, provided that no such changes, additions or deletions will affect -the already released version of the Licensed Software, but only upcoming -version(s). - -"Licensee" shall mean the individual or legal entity that is party to this -Agreement. - -"Licensee's Records" shall mean books and records that contain information -bearing on Licensee's compliance with this Agreement, Licensee's use of Open -Source Qt and/or the payments due to The Qt Company under this Agreement, -including, but not limited to user information, assembly logs, sales records -and distribution records. - -"Modified Software" shall have the meaning as set forth in Section 2.3. - -"Online Services" shall mean any services or access to systems made available -by The Qt Company to the Licensee over the Internet relating to the Licensed -Software or for the purpose of use by the Licensee of the Licensed Software or -Support. Use of any such Online Services is discretionary for the Licensee and -some of them may be subject to additional fees. - -"Open Source Qt" shall mean Qt Software available under the terms of the GNU -Lesser General Public License, version 2.1 or later ("LGPL") or the GNU General -Public License, version 2.0 or later ("GPL"). For clarity, Open Source Qt shall -not be provided, governed or used under this Agreement. - -"Party" or "Parties" shall mean Licensee and/or The Qt Company. - -"Permitted Software" shall mean (i) third party open source software products -that are generally available for public in source code form and free of any -charge under any of the licenses approved by Open Source Initiative as listed -on https://opensource.org/licenses, which may include parts of Open Source Qt -or be developed using Open Source Qt; and (ii) software The Qt Company has made -available via its Qt Marketplace online distribution channel. - -"Pre-Release Code" shall have the meaning as set forth in Section 4. - -"Prohibited Combination" shall mean any effort to use, combine, incorporate, -link or integrate Licensed Software with any software created with or -incorporating Open Source Qt, or use Licensed Software for creation of any such -software. - -"Purchase Order" shall have the meaning as set forth in Section 10.2. - -"QA Tools" shall mean software libraries and tools as defined in Appendix 1 -depending on which product(s) the Licensee has purchased under the Agreement. - -"Qt Software" shall mean the software libraries and tools of The Qt Company, -which The Qt Company makes available under commercial and/or open source -licenses. - -"Redistributables" shall mean the portions of the Licensed Software set forth -in Appendix 1 that may be distributed pursuant to the terms of this Agreement -in object code form only, including any relevant documentation. Where relevant, -any reference to Licensed Software in this Agreement shall include and refer -also to Redistributables. - -"Renewal Term" shall mean an extension of previous Development License Term as -agreed between the Parties. - -"Submitted Modified Software" shall have the meaning as set forth in Section -2.3. - -"Support" shall mean standard developer support that is provided by The Qt -Company to assist Designated Users in using the Licensed Software in accordance -with this Agreement and the Support Terms. - -"Support Terms" shall mean The Qt Company's standard support terms specified in -Appendix 9 hereto. - -"Taxes" shall have the meaning set forth in Section 10.5. - -"The Qt Company" shall mean: - (i) in the event Licensee is an individual residing in the United States or - a legal entity incorporated in the United States or having its - headquarters in the United States, The Qt Company Inc., a Delaware - corporation with its office at 3031 Tisch Way, 110 Plaza West, - San Jose, CA 95128, USA.; or - (ii) in the event the Licensee is an individual residing outside of the - United States or a legal entity incorporated outside of the United - States or having its registered office outside of the United States, - The Qt Company Ltd., a Finnish company with its registered office at - Miestentie 7, 02150 Espoo, Finland. - -"Third-Party Software" shall have the meaning set forth in Section 4. - -"Updates" shall mean a release or version of the Licensed Software containing -bug fixes, error corrections and other changes that are generally made -available to users of the Licensed Software that have contracted for Support. -Updates are generally depicted as a change to the digits following the decimal -in the Licensed Software version number. The Qt Company shall make Updates -available to the Licensee under the Support. Updates shall be considered as -part of the Licensed Software hereunder. - -"Upgrades" shall mean a release or version of the Licensed Software containing -enhancements and new features and are generally depicted as a change to the -first digit of the Licensed Software version number. In the event Upgrades are -provided to the Licensee under this Agreement, they shall be considered as part -of the Licensed Software hereunder. - -2. OWNERSHIP - -2.1. Ownership of The Qt Company - -The Licensed Software is protected by copyright laws and international -copyright treaties, as well as other intellectual property laws and treaties. -The Licensed Software is licensed, not sold. - -All of The Qt Company's Intellectual Property Rights are and shall remain the -exclusive property of The Qt Company or its licensors respectively. No rights -to The Qt Company's Intellectual Property Rights are assigned or granted to -Licensee under this Agreement, except when and to the extent expressly -specified herein. - -2.2. Ownership of Licensee - -All the Licensee's Intellectual Property Rights are and shall remain the -exclusive property of the Licensee or its licensors respectively. - -All Intellectual Property Rights to the Modified Software, Applications and -Devices shall remain with the Licensee and no rights thereto shall be granted -by the Licensee to The Qt Company under this Agreement (except as set forth in -Section 2.3 below). - -2.3. Modified Software - -Licensee may create bug-fixes, error corrections, patches or modifications to -the Licensed Software ("Modified Software"). Such Modified Software may break -the source or binary compatibility with the Licensed Software (including -without limitation through changing the application programming interfaces -("API") or by adding, changing or deleting any variable, method, or class -signature in the Licensed Software and/or any inter-process protocols, -services or standards in the Licensed Software libraries). To the extent that -Licensee's Modified Software so breaks source or binary compatibility with the -Licensed Software, Licensee acknowledges that The Qt Company's ability to -provide Support may be prevented or limited and Licensee's ability to make use -of Updates may be restricted. - -Licensee may, at its sole and absolute discretion, choose to submit Modified -Software to The Qt Company ("Submitted Modified Software") in connection with -Licensee's Support request, service request or otherwise. In the event -Licensee does so, then, Licensee hereby grants The Qt Company a sublicensable, -assignable, irrevocable, perpetual, worldwide, non-exclusive, royalty-free and -fully paid-up license, under all of Licensee's Intellectual Property Rights, to -reproduce, adapt, translate, modify, and prepare derivative works of, publicly -display, publicly perform, sublicense, make available and distribute such -Submitted Modified Software as The Qt Company sees fit at its free and absolute -discretion. - -3. LICENSES GRANTED - -3.1. Development with Licensed Software - -Subject to the terms of this Agreement, The Qt Company grants to Licensee a -worldwide, non-exclusive, non-transferable license, valid for each Development -License Term, to use, modify and copy the Licensed Software by Designated -Users on the Development Platforms for the sole purposes of designing, -developing, demonstrating and testing Application(s) and/or Devices, and to -provide thereto related support and other related services to Customers. Each -Application and/or Device can only include, incorporate or integrate -contributions by such Designated Users who are duly licensed for the applicable -Development Platform(s) and Deployment Platform(s) (i.e have a valid license -for the appropriate Licensed Software product). - -Licensee may install copies of the Licensed Software on five (5) computers per -Designated User, provided that only the Designated Users who have a valid -Development License may use the Licensed Software. - -Licensee may at any time designate another Designated User to replace a -then-current Designated User by notifying The Qt Company in writing, where such -replacement is due to termination of employment, change of job duties, long -time absence or other such permanent reason affecting Designated User's need -for Licensed Software. - -Upon expiry of the initially agreed Development License Term, the respective -Development License Term shall be automatically extended to one or more Renewal -Term(s), unless and until either Party notifies the other Party in writing, or -any other method acceptable to The Qt Company (it being specifically -acknowledged and understood that verbal notification is explicitly deemed -inadequate in all circumstances), that it does not wish to continue the -Development License Term, such notification to be provided to the other Party -no less than thirty (30) days before expiry of the respective Development -License Term. The Qt Company shall, in good time before the due date for the -above notification, remind the Licensee on the coming Renewal Term. Unless -otherwise agreed between the Parties, Renewal Term shall be 12 months. - -Any such Renewal Term shall be subject to License Fees agreed between the -Parties or, if no advance agreement exists, subject to The Qt Company's -standard list pricing applicable at the commencement date of any such -Renewal Term. - -The Qt Company may either request the Licensee to place a purchase order -corresponding to a quote by The Qt Company, or use Licensee's stored Credit -Card information in the Qt Account to automatically charge the Licensee for the -relevant Renewal Term. - -3.2. Distribution of Applications - -Subject to the terms of this Agreement, The Qt Company grants to Licensee a -worldwide, non-exclusive, non-transferable, revocable (for cause pursuant to -this Agreement), right and license, valid for the Agreement Term, to - (i) distribute, by itself or through its Contractors, Redistributables as - installed, incorporated or integrated into Applications for execution - on the Deployment Platforms, and - (ii) grant perpetual and irrevocable sublicenses to Redistributables, as - distributed hereunder, for Customers solely to the extent necessary in - order for the Customers to use the Applications for their respective - intended purposes. - -Right to distribute the Redistributables as part of an Application as provided -herein is not royalty-bearing but is conditional upon the Application having -been created, updated and maintained under a valid and duly paid Development -Licenses. - -3.3. Distribution of Devices - -Subject to the terms of this Agreement, The Qt Company grants to Licensee a -worldwide, non-exclusive, non-transferable, revocable (for cause pursuant to -this Agreement), right and license, valid for the Agreement Term, to - (i) distribute, by itself or through one or more tiers of Contractors, - Redistributables as installed, incorporated or integrated, or intended - to be installed, incorporated or integrated into Devices for execution - on the Deployment Platforms, and - (ii) grant perpetual and irrevocable sublicenses to Redistributables, as - distributed hereunder, for Customers solely to the extent necessary in - order for the Customers to use the Devices for their respective - intended purposes. - -Right to distribute the Devices as provided herein is conditional upon - (i) the Devices having been created, updated and maintained under a valid - and duly paid Development Licenses, and - (ii) the Licensee having acquired corresponding Distribution Licenses at - the time of distribution of any Devices to Customers. - -3.4. Further Requirements - -The licenses granted above in this Section 3 by The Qt Company to Licensee are -conditional and subject to Licensee's compliance with the following terms: - (i) Licensee acknowledges that The Qt Company has separate products of - Licensed Software for the purpose of Applications and Devices - respectively, where development and distribution of Devices is only - allowed using the correct designated product. Licensee shall make sure - and bear the burden of proof that Licensee is using a correct product - of Licensed Software entitling Licensee to development and distribution - of Devices; - (ii) Licensee shall not remove or alter any copyright, trademark or other - proprietary rights notice(s) contained in any portion of the Licensed - Software; - (iii) Applications must add primary and substantial functionality to the - Licensed Software so as not to compete with the Licensed Software; - (iv) Applications may not pass on functionality which in any way makes it - possible for others to create software with the Licensed Software; - provided however that Licensee may use the Licensed Software's - scripting and QML ("Qt Quick") functionality solely in order to enable - scripting, themes and styles that augment the functionality and - appearance of the Application(s) without adding primary and substantial - functionality to the Application(s); - (v) Licensee shall not use Licensed Software in any manner or for any - purpose that infringes, misappropriates or otherwise violates any - Intellectual property or right of any third party, or that violates any - applicable law; - (vi) Licensee shall not use The Qt Company's or any of its suppliers' - names, logos, or trademarks to market Applications, except that - Licensee may use "Built with Qt" logo to indicate that Application(s) - or Device(s) was developed using the Licensed Software; - (vii) Licensee shall not distribute, sublicense or disclose source code of - Licensed Software to any third party (provided however that Licensee - may appoint employee(s) of Contractors and Affiliates as Designated - Users to use Licensed Software pursuant to this Agreement). Such right - may be available for the Licensee subject to a separate software - development kit ("SDK") license agreement to be concluded with The Qt - Company; - (viii) Licensee shall not grant the Customers a right to (a) make copies of - the Redistributables except when and to the extent required to use the - Applications and/or Devices for their intended purpose, (b) modify the - Redistributables or create derivative works thereof, (c) decompile, - disassemble or otherwise reverse engineer Redistributables, or (d) - redistribute any copy or portion of the Redistributables to any third - party, except as part of the onward sale of the Application or Device - on which the Redistributables are installed; - (ix) Licensee shall not and shall cause that its Affiliates or Contractors - shall not use Licensed Software in any Prohibited Combination, unless - Licensee has received an advance written permission from The Qt Company - to do so. Absent such written permission, any and all distribution by - the Licensee during the Agreement Term of a hardware device or product - a) which incorporate or integrate any part of Licensed Software or Open - Source Qt; or b) where substantial functionality is provided by - software built with Licensed Software or Open Source Qt or otherwise - depends on the Licensed Software or Open Source Qt, shall be considered - to be Device distribution under this Agreement and shall be dependent - on Licensee's compliance thereof (including but not limited to - obligation to pay applicable License Fees for such distribution). - Notwithstanding what is provided above in this sub-section (ix), - Licensee is entitled to use and combine Licensed Software with any - Permitted Software; - (x) Licensee shall cause all of its Affiliates, Contractors and Customers - entitled to make use of the licenses granted under this Agreement, to - be contractually bound to comply with the relevant terms of this - Agreement and not to use the Licensed Software beyond the terms hereof - and for any purposes other than operating within the scope of their - services for Licensee. Licensee shall be responsible for any and all - actions and omissions of its Affiliates and Contractors relating to the - Licensed Software and use thereof (including but not limited to payment - of all applicable License Fees); - (xi) Except when and to the extent explicitly provided in this Section 3, - Licensee shall not transfer, publish, disclose, display or otherwise - make available the Licensed Software; and - (xii) Licensee shall not attempt or enlist a third party to conduct or - attempt to conduct any of the above. - -Above terms shall not be applicable if and to the extent they conflict with any -mandatory provisions of any applicable laws. - -Any use of Licensed Software beyond the provisions of this Agreement is -strictly prohibited and requires an additional license from The Qt Company. - -3.5 QA Tools License - -Subject to the terms of this Agreement, The Qt Company grants to Licensee a -worldwide, non-exclusive, non-transferable license, valid for the Development -License Term, to use the QA Tools for Licensee's internal business purposes in -the manner provided below and in Appendix 1 hereto. - -Licensee may modify the QA Tools except for altering or removing any details of -ownership, copyright, trademark or other property right connected with the QA -Tools. - -Licensee shall not distribute the QA Tools or any part thereof, modified or -unmodified, separately or as part of any software package, Application or -Device. - -Upon expiry of the initially agreed Development License Term, the respective -Development License Term shall be automatically extended to one or more Renewal -Term(s), unless and until either Party notifies the other Party in writing, or -any other method acceptable to The Qt Company (it being specifically -acknowledged and understood that verbal notification is explicitly deemed -inadequate in all circumstances), that it does not wish to continue the -Development License Term, such notification to be provided to the other Party -no less than thirty (30) days before expiry of the respective Development -License Term. The Qt Company shall, in good time before the due date for the -above notification, remind the Licensee on the coming Renewal Term. Unless -otherwise agreed between the Parties, Renewal Term shall be 12 months. - -Any such Renewal Term shall be subject to License Fees agreed between the -Parties or, if no advance agreement exists, subject to The Qt Company's -standard list pricing applicable at the commencement date of any such -Renewal Term. - -3.6 Evaluation License - -Subject to the terms of this Agreement, The Qt Company grants to Licensee a -worldwide, non-exclusive, non-transferable license, valid for the Evaluation -License Term to use the Licensed Software solely for the Licensee's internal -use to evaluate and determine whether the Licensed Software meets Licensee's -business requirements, specifically excluding any commercial use of the -Licensed Software or any derived work thereof. - -Upon the expiry of the Evaluation License Term, Licensee must either -discontinue use of the relevant Licensed Software or acquire a commercial -Development License or QA Tools License specified herein. - -4. THIRD-PARTY SOFTWARE - -The Licensed Software may provide links or access to third party libraries or -code (collectively "Third-Party Software") to implement various functions. -Third-Party Software does not, however, comprise part of the Licensed Software, -but is provided to Licensee complimentary and use thereof is discretionary for -the Licensee. Third-Party Software will be listed in the ".../src/3rdparty" -source tree delivered with the Licensed Software or documented in the Licensed -Software, as such may be amended from time to time. Licensee acknowledges that -use or distribution of Third-Party Software is in all respects subject to -applicable license terms of applicable third-party right holders. - -5. PRE-RELEASE CODE - -The Licensed Software may contain pre-release code and functionality, or sample -code marked or otherwise stated with appropriate designation such as -"Technology Preview", "Alpha", "Beta", "Sample", "Example" etc. -("Pre-Release Code"). - -Such Pre-Release Code may be present complimentary for the Licensee, in order -to provide experimental support or information for new platforms or -preliminary versions of one or more new functionalities or for other similar -reasons. The Pre-Release Code may not be at the level of performance and -compatibility of a final, generally available, product offering. The -Pre-Release Code may not operate correctly, may contain errors and may be -substantially modified by The Qt Company prior to the first commercial -product release, if any. The Qt Company is under no obligation to make -Pre-Release Code commercially available, or provide any Support or Updates -relating thereto. The Qt Company assumes no liability whatsoever regarding -any Pre-Release Code, but any use thereof is exclusively at Licensee's own risk -and expense. - -For clarity, unless Licensed Software specifies different license terms for the -respective Pre-Release Code, the Licensee is entitled to use such pre-release -code pursuant to Section 3, just like other Licensed Software. - -6. LIMITED WARRANTY AND WARRANTY DISCLAIMER - -The Qt Company hereby represents and warrants that (i) it has the power and -authority to grant the rights and licenses granted to Licensee under this -Agreement, and (ii) Licensed Software will operate materially in accordance -with its specifications. - -Except as set forth above, the Licensed Software is licensed to Licensee "as -is" and Licensee's exclusive remedy and The Qt Company's entire liability for -errors in the Licensed Software shall be limited, at The Qt Company's option, -to correction of the error, replacement of the Licensed Software or return of -the applicable fees paid for the defective Licensed Software for the time -period during which the License is not able to utilize the Licensed Software -under the terms of this Agreement. - -TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE QT COMPANY ON BEHALF OF -ITSELF AND ITS LICENSORS, SUPPLIERS AND AFFILIATES, DISCLAIMS ALL OTHER -WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND -NON-INFRINGEMENT WITH REGARD TO THE LICENSED SOFTWARE. THE QT COMPANY DOES NOT -WARRANT THAT THE LICENSED SOFTWARE WILL SATISFY LICENSEE'S REQUIREMENTS OR THAT -IT WILL OPERATE WITHOUT DEFECT OR ERROR OR THAT THE OPERATION THEREOF WILL BE -UNINTERRUPTED. - -7. LIMITATION OF LIABILITY - -EXCEPT FOR (I) CASES OF GROSS NEGLIGENCE OR INTENTIONAL MISCONDUCT, AND (II) -BREACH OF CONFIDENTIALITY, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, IN NO -EVENT SHALL EITHER PARTY BE LIABLE TO THE OTHER PARTY FOR ANY LOSS OF PROFIT, -LOSS OF DATA, LOSS OF BUSINESS OR GOODWILL OR ANY OTHER INDIRECT, SPECIAL, -CONSEQUENTIAL, INCIDENTAL OR PUNITIVE COST, DAMAGES OR EXPENSE OF ANY KIND, -HOWSOEVER ARISING UNDER OR IN CONNECTION WITH THIS AGREEMENT. - -EXCEPT FOR (I) CASES OF GROSS NEGLIGENCE OR INTENTIONAL MISCONDUCT, AND (II) -BREACH OF CONFIDENTIALITY, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, IN NO -EVENT SHALL EITHER PARTY'S TOTAL AGGREGATE LIABILITY UNDER THIS AGREEMENT -EXCEED THE AGGREGATE LICENSE FEES PAID OR PAYABLE TO THE QT COMPANY BY LICENSEE -DURING THE DEVELOPMENT LICENSE TERM DURING WHICH THE EVENT RESULTING IN SUCH -LIABILITY OCCURRED. - -THE PROVISIONS OF THIS SECTION 7 ALLOCATE THE RISKS UNDER THIS AGREEMENT -BETWEEN THE QT COMPANY AND LICENSEE AND THE PARTIES HAVE RELIED UPON THE -LIMITATIONS SET FORTH HEREIN IN DETERMINING WHETHER TO ENTER INTO THIS -AGREEMENT. - -NOTWITHSTANDING ANYTHING TO THE CONTRARY IN THIS AGREEMENT, LICENSEE SHALL -ALWAYS BE LIABLE TO PAY THE APPLICABLE LICENSE FEES CORRESPONDING TO ITS -ACTUAL USE OF LICENSED SOFTWARE. - -8. SUPPORT, UPDATES AND ONLINE SERVICES - -Upon due payment of the agreed License Fees the Licensee will be eligible to -receive Support and Updates and to use the Online Services during the agreed -Development License Term or other agreed fixed time period. Support is -provided according to agreed support level and subject to applicable -requirements and restrictions, as specified in the Support Terms. - -Unless otherwise decided by The Qt Company at its free and absolute discretion, -Upgrades will not be included in the Support but may be available subject to -additional fees. - -From time to time The Qt Company may change the Support Terms, provided that -during the respective ongoing Support period the level of Support may not be -reduced without the consent of the Licensee. - -Unless otherwise agreed, The Qt Company shall not be responsible for providing -any service or support to Customers. - -9. CONFIDENTIALITY - -Each Party acknowledges that during the Agreement Term each Party may receive -information about the other Party's business, business methods, business plans, -customers, business relations, technology, and other information, including the -terms of this Agreement, that is confidential and of great value to the other -Party, and the value of which would be significantly reduced if disclosed to -third parties ("Confidential Information"). Accordingly, when a Party (the -"Receiving Party") receives Confidential Information from the other Party (the -"Disclosing Party"), the Receiving Party shall only disclose such information -to employees and Contractors on a need to know basis, and shall cause its -employees and employees of its Affiliates to: (i) maintain any and all -Confidential Information in confidence; (ii) not disclose the Confidential -Information to a third party without the Disclosing Party's prior written -approval; and (iii) not, directly or indirectly, use the Confidential -Information for any purpose other than for exercising its rights and -fulfilling its responsibilities pursuant to this Agreement. Each Party shall -take reasonable measures to protect the Confidential Information of the other -Party, which measures shall not be less than the measures taken by such Party -to protect its own confidential and proprietary information. - -Obligation of confidentiality shall not apply to information that (i) is or -becomes generally known to the public through no act or omission of the -Receiving Party; (ii) was in the Receiving Party's lawful possession prior to -the disclosure hereunder and was not subject to limitations on disclosure or -use; (iii) is developed independently by employees or Contractors of the -Receiving Party or other persons working for the Receiving Party who have not -had access to the Confidential Information of the Disclosing Party, as proven -by the written records of the Receiving Party; (iv) is lawfully disclosed to -the Receiving Party without restrictions, by a third party not under an -obligation of confidentiality; or (v) the Receiving Party is legally compelled -to disclose, in which case the Receiving Party shall notify the Disclosing -Party of such compelled disclosure and assert the privileged and confidential -nature of the information and cooperate fully with the Disclosing Party to -limit the scope of disclosure and the dissemination of disclosed Confidential -Information to the minimum extent necessary. - -The obligations under this Section 9 shall continue to remain in force for a -period of five (5) years after the last disclosure, and, with respect to trade -secrets, for so long as such trade secrets are protected under applicable trade -secret laws. - -10. FEES, DELIVERY AND PAYMENT - -10.1. License Fees - -License Fees are described in The Qt Company's standard price list, quote or -Purchase Order confirmation or in an Appendix 2 hereto, as the case may be. - -Unless otherwise expressly provided in this Agreement, the License Fees shall -not be refunded or claimed as a credit in any event or for any reason -whatsoever. - -10.2. Ordering Licenses - -Licensee may purchase Development Licenses, Distribution Licenses and QA Tools -Licenses pursuant to agreed pricing terms or, if no specific pricing terms have -been agreed upon, at The Qt Company's standard pricing terms applicable at the -time of purchase. - -Unless expressly otherwise agreed, any price or other term quoted to the -Licensee or specified herein shall only be valid for the thirty (30) days from -the effective date of this Agreement, Appendix 2 or the date of the quote, as -applicable. - -Licensee shall submit all purchase orders for Development Licenses and -Distribution Licenses to The Qt Company by email or any other method acceptable -to The Qt Company (each such order is referred to herein as a "Purchase Order") -for confirmation, whereupon the Purchase Order shall become binding between the -Parties. - -Licensee acknowledges and agrees that all Purchase Orders for Licensed Software -the Licensee makes during the Agreement Term shall be governed exclusively -under the terms of this Agreement. - -10.3. Distribution License Packs - -Unless otherwise agreed, Distribution Licenses shall be purchased by way of -Distribution License Packs. - -Upon due payment of the ordered Distribution License Pack(s), the Licensee will -have an account of Distribution Licenses available for distributing the -Redistributables in accordance with this Agreement. - -Each time Licensee distributes a copy of Redistributables, then one -Distribution License is used, and Licensee's account of available Distribution -Licenses is decreased accordingly. - -Licensee may distribute copies of the Redistributables so long as Licensee has -Distribution Licenses remaining on its account. - -10.4. Payment Terms - -License Fees and any other charges under this Agreement shall be paid by -Licensee no later than thirty (30) days from the date of the applicable invoice -from The Qt Company. - -The Qt Company will submit an invoice to Licensee after the date of this -Agreement and/or after The Qt Company receives a Purchase Order from Licensee. - -A late payment charge of the lower of (a) one percent per month; or (b) the -interest rate stipulated by applicable law, shall be charged on any unpaid -balances that remain past due and which have not been disputed by the Licensee -in good faith. - -10.5. Taxes - -All License Fees and other charges payable hereunder are gross amounts but -exclusive of any value added tax, use tax, sales tax, withholding tax and other -taxes, duties or tariffs ("Taxes") levied directly for the sale, delivery or -use of Licensed Software hereunder pursuant to any applicable law. Such -applicable Taxes shall be paid by Licensee to The Qt Company, or, where -applicable, in lieu of payment of such Taxes to The Qt Company, Licensee shall -provide an exemption certificate to The Qt Company and any applicable -authority. - -11. RECORD-KEEPING AND REPORTING OBLIGATIONS; AUDIT RIGHTS - -11.1. Licensee's Record-keeping - -Licensee shall at all times during the Agreement Term and for a period of two -(2) years thereafter maintain Licensee's Records in an accurate and up-to-date -form. Licensee's Records shall be adequate to reasonably enable The Qt Company -to determine Licensee's compliance with the provisions of this Agreement. The -records shall conform to general good accounting practices. - -Licensee shall, within thirty (30) days from receiving The Qt Company's request -to that effect, deliver to The Qt Company a report based on Licensee's Records, -such report to contain information, in sufficient detail, on (i) number and -identity of users working with Licensed Software or Open Source Qt, (ii) copies -of Redistributables distributed by Licensee during the most recent calendar -quarter and/or any other term specified by The Qt Company, , and (iii) any -other information pertaining to Licensee's compliance with the terms of this -Agreement (like e.g. information on products and/or projects relating to use of -Distribution Licenses), as The Qt Company may reasonably require from time to -time. - -11.2. The Qt Company's Audit Rights - -The Qt Company or an independent auditor acting on behalf of The Qt Company's, -may, upon at least thirty (30) days' prior written notice and at its expense, -audit Licensee with respect to the Licensee's use of the Licensed Software, but -not more frequently than once during each 6-month period. Such audit may be -conducted by mail, electronic means or through an in-person visit to Licensee's -place of business. Any possible in-person audit shall be conducted during -regular business hours at Licensee's facilities and shall not unreasonably -interfere with Licensee's business activities and shall be limited in scope to -verify Licensee's compliance with the terms of this Agreement. The Qt Company -or the independent auditor acting on behalf of The Qt Company shall be entitled -to inspect Licensee's Records and conduct necessary interviews of Licensee's -relevant employees and Contractors. All such Licensee's Records and use thereof -shall be subject to an obligation of confidentiality under this Agreement. - -If an audit reveals that Licensee is using the Licensed Software beyond scope -of the licenses Licensee has paid for, Licensee shall pay to The Qt Company any -amounts owed for such unauthorized use within 30 days from receipt of the -corresponding invoice from The Qt Company. - -In addition, in the event the audit reveals a material violation of the terms -of this Agreement (without limitation, either (i) underpayment of more than 10 -% of License Fees or 10,000 euros (whichever is more) or (ii) distribution of -products, which include or result from Prohibited Combination, shall be deemed -a material violation for purposes of this section), then the Licensee shall -pay The Qt Company's reasonable cost of conducting such audit. - -12. TERM AND TERMINATION - -12.1. Agreement Term - -This Agreement shall enter into force upon due acceptance by both Parties and -remain in force until terminated pursuant to the terms of this Section 12 -("Agreement Term"). - -12.2. Termination for breach and suspension of rights -Either Party shall have the right to terminate this Agreement upon thirty (30) -days prior written notice if the other Party commits a material breach of any -obligation of this Agreement and fails to remedy such breach within such notice -period. - -Instead of termination, The Qt Company shall have the right to suspend or -withhold grants of all rights to the Licensed Software hereunder, including but -not limited to the Development Licenses, Distribution License, and Support, -should Licensee fail to make payment in timely fashion or otherwise violates or -is reasonably suspected to violate its obligations or terms of this Agreement, -and where such violation or breach is not cured within ten (10) business days -following The Qt Company's written notice thereof. - -12.3. Termination for insolvency - -Either Party shall have the right to terminate this Agreement immediately upon -written notice in the event that the other Party becomes insolvent, files for -any form of bankruptcy, makes any assignment for the benefit of creditors, has -a receiver, administrative receiver or officer appointed over the whole or a -substantial part of its assets, ceases to conduct business, or an act -equivalent to any of the above occurs under the laws of the jurisdiction of the -other Party. - -12.4. Parties' Rights and Duties upon Termination - -Upon expiry or termination of the Agreement, Licensee shall cease and shall -cause all Designated Users (including those of its Affiliates' and -Contractors') to cease using the Licensed Software under this Agreement. For -clarity, a Development License of a Designated User or a QA Tools License, and -all rights relating thereto, shall always terminate at the expiry of the -respective Development License Term, even if the Agreement continues to remain -in force. - -Upon such termination the Licensee shall destroy or return to The Qt Company -all copies of the Licensed Software and all related materials and will certify -the same by Licensee's duly authorized officer to The Qt Company upon its -request, provided however that Licensee may retain and exploit such copies of -the Licensed Software as it may reasonably require in providing continued -support to Customers. - -Except when this Agreement is terminated by The Qt Company due to Licensee's -material breach as set forth in Section 12.2, the Licensee may continue -distribution of Applications and Devices under the terms of this Agreement -despite the termination of this Agreement. In such event the terms hereof will -continue to be applicable and govern any such distribution of Applications and -Devices beyond the expiry or termination of this Agreement. In case of -termination by The Qt Company due to Licensee's material breach, Licensee must -cease any distribution of Applications and Devices at the date of termination -of this Agreement. - -Expiry or termination of this Agreement for any reason whatsoever shall not -relieve Licensee of its obligation to pay any License Fees accrued or payable -to The Qt Company prior to the effective date of termination, and Licensee pay -to The Qt Company all such fees within 30 days from the effective date of -termination of this Agreement. - -Termination of this Agreement shall not affect any rights of Customers to -continue use of Applications and Devices (and therein incorporated -Redistributables). - -12.5. Extension of Rights under Special Circumstances - -In the event of The Qt Company choosing not to renew the Development License(s) -or QA Tools Licenses, as set forth in Section 3.1 and 3.5 respectively, and -where such decision of non-renewal is not due to any ongoing breach or alleged -breach (as reasonably determined by The Qt Company) by Licensee of the terms of -this Agreement or any applicable license terms of Open Source Qt, then all -valid and affected Development Licenses and QA Tools licenses possessed by the -Licensee at such date shall be extended to be valid in perpetuity under the -terms of this Agreement and Licensee is entitled to purchase additional -licenses as set forth in Section 10.2. - -In the event The Qt Company is declared bankrupt under a final, non-cancellable -decision by relevant court of law, and this Agreement is not, at the date of -expiry of the Development License(s) or QA Tools Licenses, assigned to party, -who has assumed The Qt Company's position as a legitimate licensor of Licensed -Software under this Agreement, then all valid Development Licenses and QA Tools -Licenses possessed by the Licensee at such date of expiry, and which the -Licensee has not notified for expiry, shall be extended to be valid in -perpetuity under the terms of this Agreement. - -For clarity, in case of an extension under this Section 12.5, any such -extension shall not apply to The Qt Company's Support obligations, but Support -shall be provided only up until the end of the respective fixed Development -License Term regardless of the extension of relevant Development License or QA -Tools License, unless otherwise agreed between the Parties. - -13. GOVERNING LAW AND LEGAL VENUE - -In the event this Agreement is in the name of The Qt Company Inc., a Delaware -Corporation, then: - (i) this Agreement shall be construed and interpreted in accordance with - the laws of the State of California, USA, excluding its choice of law - provisions; - (ii) the United Nations Convention on Contracts for the International Sale - of Goods will not apply to this Agreement; and - (iii) any dispute, claim or controversy arising out of or relating to this - Agreement or the breach, termination, enforcement, interpretation or - validity thereof, including the determination of the scope or - applicability of this Agreement to arbitrate, shall be determined by - arbitration in San Francisco, USA, before one arbitrator. The - arbitration shall be administered by JAMS pursuant to JAMS' Streamlined - Arbitration Rules and Procedures. Judgment on the Award may be entered - in any court having jurisdiction. This Section shall not preclude - parties from seeking provisional remedies in aid of arbitration from a - court of appropriate jurisdiction. - -In the event this Agreement is in the name of The Qt Company Ltd., a Finnish -Company, then: - (i) this Agreement shall be construed and interpreted in accordance with - the laws of Finland, excluding its choice of law provisions; - (ii) the United Nations Convention on Contracts for the International Sale - of Goods will not apply to this Agreement; and - (iii) any disputes, controversy or claim arising out of or relating to this - Agreement, or the breach, termination or validity thereof shall be - finally settled by arbitration in accordance with the Arbitration Rules - of International Chamber of Commerce. The arbitration tribunal shall - consist of one (1), or if either Party so requires, of three (3), - arbitrators. The award shall be final and binding and enforceable in - any court of competent jurisdiction. The arbitration shall be held in - Helsinki, Finland and the process shall be conducted in the English - language. This Section shall not preclude parties from seeking - provisional remedies in aid of arbitration from a court of appropriate - jurisdiction. - -14. GENERAL PROVISIONS - -14.1. No Assignment - -Except in the case of a merger or sale of substantially all of its corporate -assets, Licensee shall not be entitled to assign or transfer all or any of its -rights, benefits and obligations under this Agreement without the prior written -consent of The Qt Company, which shall not be unreasonably withheld or delayed. -The Qt Company shall be entitled to freely assign or transfer any of its -rights, benefits or obligations under this Agreement. - -14.2. No Third-Party Representations - -Licensee shall make no representations or warranties concerning the Licensed -Software on behalf of The Qt Company. Any representation or warranty Licensee -makes or purports to make on The Qt Company's behalf shall be void as to -The Qt Company. - -14.3. Surviving Sections - -Any terms and conditions that by their nature or otherwise reasonably should -survive termination of this Agreement shall so be deemed to survive. Such -sections include especially the following: 1, 2, 6, 7, 9, 11, 12.4, 13 and 14. - -14.4. Entire Agreement - -This Agreement, the Appendices hereto, the License Certificate and any -applicable quote and Purchase Order accepted by The Qt Company constitute the -complete agreement between the Parties and supersedes all prior or -contemporaneous discussions, representations, and proposals, written or oral, -with respect to the subject matters discussed herein. - -In the event of any conflict or inconsistency between this Agreement and any -Purchase Order, the terms of this Agreement will prevail over the terms of the -Purchase Order with respect to such conflict or inconsistency. - -Parties specifically acknowledge and agree that this Agreement prevails over -any click-to-accept or similar agreements the Designated Users may need to -accept online upon download of the Licensed Software, as may be required by -The Qt Company's applicable processes relating to Licensed Software. - -14.5. Modifications - -No modification of this Agreement shall be effective unless contained in a -writing executed by an authorized representative of each Party. No term or -condition contained in Licensee's Purchase Order ("Deviating Terms") shall -apply unless The Qt Company has expressly agreed such Deviating Terms in -writing. Unless and to the extent expressly agreed by The Qt Company, any such -Deviating Terms shall be deemed void and with no legal effect. For clarity, -delivery of the Licensed Software following the receipt of the Purchase Order -including Deviating Terms shall not constitute acceptance of such Deviating -Terms. - -14.6. Force Majeure - -Except for the payment obligations hereunder, neither Party shall be liable to -the other for any delay or non-performance of its obligations hereunder in the -event and to the extent that such delay or non-performance is due to an event -of act of God, terrorist attack or other similar unforeseeable catastrophic -event that prevents either Party for fulfilling its obligations under this -Agreement and which such Party cannot avoid or circumvent ("Force Majeure -Event"). If the Force Majeure Event results in a delay or non-performance of a -Party for a period of three (3) months or longer, then either Party shall have -the right to terminate this Agreement with immediate effect without any -liability (except for the obligations of payment arising prior to the event of -Force Majeure) towards the other Party. - -14.7. Notices - -Any notice given by one Party to the other shall be deemed properly given and -deemed received if specifically acknowledged by the receiving Party in writing -or when successfully delivered to the recipient by hand, fax, or special -courier during normal business hours on a business day to the addresses -specified for each Party on the signature page. Each communication and document -made or delivered by one Party to the other Party pursuant to this Agreement -shall be in the English language. - -14.8. Export Control - -Licensee acknowledges that the Redistributables, as incorporated in -Applications or Devices, may be subject to export control restrictions under -the applicable laws of respective countries. Licensee shall fully comply with -all applicable export license restrictions and requirements as well as with all -laws and regulations relating to the Redistributables and exercise of licenses -hereunder and shall procure all necessary governmental authorizations, -including without limitation, all necessary licenses, approvals, permissions or -consents, where necessary for the re-exportation of the Redistributables, -Applications and/or Devices. - -14.9. No Implied License - -There are no implied licenses or other implied rights granted under this -Agreement, and all rights, save for those expressly granted hereunder, shall -remain with The Qt Company and its licensors. In addition, no licenses or -immunities are granted to the combination of the Licensed Software with any -other software or hardware not delivered by The Qt Company under this -Agreement. - -14.10. Attorney Fees - -The prevailing Party in any action to enforce this Agreement shall be entitled -to recover its attorney's fees and costs in connection with such action, as to -be ordered by the relevant dispute resolution body. - -14.11. Privacy - -Licensee acknowledges and agrees that for the purpose of this Agreement, -The Qt Company may collect, use, transfer and disclose personal data pertaining -to Designated Users as well as any other employees and directors of the -Licensee and its Contractors relevant for carrying out the intent of this -Agreement. Such personal data will be primarily collected from the relevant -individuals but may be collected also from Licensee (e.g. in the course of -Licensee's reporting obligations). The Parties acknowledge that as -The Qt Company determines the purpose and means for such collection and -processing of the applicable personal data, The Qt Company shall be regarded as -the Data Controller under the applicable Data Protection Legislation. -The Qt Company shall process any such personal data in accordance with its -privacy and security policies and practices, which will comply with all -applicable requirements of the Data Protection Legislation. - -14.12. Severability - -If any provision of this Agreement shall be adjudged by any court of competent -jurisdiction to be unenforceable or invalid, that provision shall be limited or -eliminated to the minimum extent necessary so that this Agreement shall -otherwise remain in full force and effect and enforceable. - -14.13. Marketing Rights - -Parties have agreed upon Marketing Rights pursuant to Appendix 7, if any. - - - - -APPENDICES -The Agreement includes following Appendices 1-10, as applicable. -- Appendix 1: Licensed Software details -- Appendix 2: Pricing -- Appendix 3: Add-on Software details (optional) -- Appendix 4: Small business and startup Licenses (optional) -- Appendix 5: Non-commercial and educational Licenses (optional) -- Appendix 6: License Reporting (optional) -- Appendix 7: Marketing Rights (optional) -- Appendix 8: Intentionally left blank (optional) -- Appendix 9: Support Terms -- Appendix 10: Conversion from legacy Licenses to Subscription (optional) -- Appendix 11: TERMS OF USE - QT INSIGHT TRACKER LIBRARY - - -APPENDIX 1: LICENSED SOFTWARE - -The modules and/or tools that are included in the latest publicly available -version of the respective product at the effective date of this Agreement- Qt -for Application Development Professional (ADP), Qt for Application Development -Enterprise (ADE), Qt for Device Creation Professional (DCP), Qt for Device -Creation Enterprise (DCE), - are marked with "X" in the below table. The -modules and tools are specific to each product version respectively and may -vary from version to version. Modules and tools included in the latest publicly -available version of the respective product at any given time are listed in -Appendix 1 of the latest version of this Agreement available at -www.qt.io/terms-conditions/. If a new version of Licensed Software does not -include a module or tool present in an older version which Licensee is entitled -to use under a valid license from The Qt Company, then Licensee will continue -to have such right during the Term of this Agreement. In the event a new -version of the Licensed Software adds modules or tools to any previous -version(s), Licensee's rights will extend to cover also such additional modules -and tools. - -Parts of the product that are permitted for distribution in object-code form -only ("Redistributables") are marked with "R" in the below table. - -+----------------------------------------------------------+ -| Modules / Tools | ADP | ADE | DCP | DCE | -+----------------------------------------------------------+ -| Active Qt | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt 3D | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt 5 Core Compatibility APIs | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Android Extras | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Bluetooth | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Canvas 3D | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Charts | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Concurrent | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Core | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Data Visualization | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt D-Bus | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt for Python | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt for WebAssembly | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Gamepad | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Graphical Effects | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt GUI | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Help | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Image Formats | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Location | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Lottie Animation | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Mac Extras | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Multimedia | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Multimedia Widgets | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Network | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Network Authorization | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt NFC | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt OpenGL | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt PDF | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Platform Headers | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Positioning | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Print Support | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Purchasing | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt QML | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick 3D | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick Controls 1 | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick Controls | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick Dialogs | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick Extras | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick Layouts | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick Test | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick Timeline | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick WebGL | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick Widgets | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Remote Objects | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Script | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Script Tools | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt SCXML | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Sensors | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Serial Bus | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Serial Port | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Shader Tools | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Speech | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt State Machine | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt SQL | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt SVG | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Test | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt UI Tools | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Virtual Keyboard | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Wayland Compositor | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt WebChannel | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt WebEngine | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt WebSockets | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt WebView | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Widgets | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Windows Extras | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt X11 Extras | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt XML | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt XML Patterns | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Designer (Qt Widget Designer) | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Linguist | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt Assistant | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| lupdate | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| lrelease | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| lconvert | X,R | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt MQTT | | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt KNX | | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt OPC UA | | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Qt CoAP | | X,R | X,R | X,R | -+----------------------------------------------------------+ -| Boot 2 Qt stacks | | | X,R | X,R | -+----------------------------------------------------------+ -| Qt OTA | | | X,R | X,R | -+----------------------------------------------------------+ -| Device Utilities | | | X,R | X,R | -+----------------------------------------------------------+ -| Qt Debugging Bridge (QDB) Daemon | | | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick Ultralite Controls | | | X,R | X,R | -+----------------------------------------------------------+ -| Qt Quick Ultralite | | | X,R | X,R | -+----------------------------------------------------------+ -| Qt Safe Renderer (QSR) | | | | X,R | -+----------------------------------------------------------+ -| Qt Application Manager | | | | X,R | -+----------------------------------------------------------+ -| Qt Interface Framework | | | | X,R | -+----------------------------------------------------------+ -| Neptune Reference UI | | | | X,R | -+----------------------------------------------------------+ -| Qt for Android Automotive (QAA) | | | | X,R | -+----------------------------------------------------------+ -| Qt Creator | X | X | X | X | -+----------------------------------------------------------+ -| Qt Design Studio Professional | X | X | X | X | -+----------------------------------------------------------+ -| androiddeployqt | X | X | X | X | -+----------------------------------------------------------+ -| androidtestrunner | X | X | X | X | -+----------------------------------------------------------+ -| canbusutil | X | X | X | X | -+----------------------------------------------------------+ -| dumpcpp | X | X | X | X | -+----------------------------------------------------------+ -| dumpdoc | X | X | X | X | -+----------------------------------------------------------+ -| fixqt4headers.pl | X | X | X | X | -+----------------------------------------------------------+ -| idc | X | X | X | X | -+----------------------------------------------------------+ -| moc | X | X | X | X | -+----------------------------------------------------------+ -| pixeltool | X | X | X | X | -+----------------------------------------------------------+ -| qdbus | X | X | X | X | -+----------------------------------------------------------+ -| qdbuscpp2xml | X | X | X | X | -+----------------------------------------------------------+ -| qdbusviwer | X | X | X | X | -+----------------------------------------------------------+ -| qdbusxml2cpp | X | X | X | X | -+----------------------------------------------------------+ -| qdistancefieldgenerator | X | X | X | X | -+----------------------------------------------------------+ -| qdoc | X | X | X | X | -+----------------------------------------------------------+ -| qhelpgenerator | X | X | X | X | -+----------------------------------------------------------+ -| qlalr | X | X | X | X | -+----------------------------------------------------------+ -| qmake | X | X | X | X | -+----------------------------------------------------------+ -| qml | X | X | X | X | -+----------------------------------------------------------+ -| qmlcachegen | X | X | X | X | -+----------------------------------------------------------+ -| qmldom | X | X | X | X | -+----------------------------------------------------------+ -| qmleasing | X | X | X | X | -+----------------------------------------------------------+ -| qmlformat | X | X | X | X | -+----------------------------------------------------------+ -| qmllint | X | X | X | X | -+----------------------------------------------------------+ -| qmlpreview | X | X | X | X | -+----------------------------------------------------------+ -| qmlprofiler | X | X | X | X | -+----------------------------------------------------------+ -| qmlscene | X | X | X | X | -+----------------------------------------------------------+ -| qmltestrunner | X | X | X | X | -+----------------------------------------------------------+ -| qmltime | X | X | X | X | -+----------------------------------------------------------+ -| qmlviewer | X | X | X | X | -+----------------------------------------------------------+ -| qtdiag | X | X | X | X | -+----------------------------------------------------------+ -| qtpaths | X | X | X | X | -+----------------------------------------------------------+ -| qtplugininfo | X | X | X | X | -+----------------------------------------------------------+ -| qvkgen | X | X | X | X | -+----------------------------------------------------------+ -| rcc | X | X | X | X | -+----------------------------------------------------------+ -| tracegen | X | X | X | X | -+----------------------------------------------------------+ -| uic | X | X | X | X | -+----------------------------------------------------------+ -| windeployqt | X | X | X | X | -+----------------------------------------------------------+ -| Target toolchains | | | X | X | -+----------------------------------------------------------+ -| Qt Debugging Bridge Host Tools | | | X | X | -+----------------------------------------------------------+ -| qtconfig-gui | | | X | X | -+----------------------------------------------------------+ -| Qt Emulator | | | X | X | -+----------------------------------------------------------+ -| Qt Creator VxWorks plugin | | | X | X | -+----------------------------------------------------------+ -| Qt Creator plugin for Qt | | | | X | -| Application Manager | | | | | -+----------------------------------------------------------+ -| qmlinterfacegenerator | | | | X | -+----------------------------------------------------------+ -| qmltocpp | | | | X | -+----------------------------------------------------------+ -| qulfontcompiler | | | | X | -+----------------------------------------------------------+ -| Qt Deployment Server | | | | X | -+----------------------------------------------------------+ - - -Rights for Application and Device use cases - -Following table summarizes the rights afforded by different products of the -Licensed Software to create and distribute Applications and Devices as defined -in this Agreement (X marks for rights): - -+---------------------------------------------------------------+ -| | Applications | Devices | -+---------------------------------------------------------------+ -| ADP | X | | -+---------------------------------------------------------------+ -| ADE | X | | -+---------------------------------------------------------------+ -| DCP | X | X | -+---------------------------------------------------------------+ -| DCE | X | X | -+---------------------------------------------------------------+ - -Licensed Software: Designer tools and modules - -The modules and/or tools that are included in the respective product - Qt for -Design Studio Professional (DSP), Qt for Design Studio Enterprise (DSE) - are -marked with "X" in the below table. - -Designer tools provides no Redistributables. - -+---------------------------------------------+ -| | DSP | DSE | -+---------------------------------------------+ -| Qt Design Studio | X | X | -+---------------------------------------------+ -| Qt Design Bridges | | X | -+---------------------------------------------+ -| QML Live on host | X | X | -+---------------------------------------------+ -| QML Live on target | | X | -+---------------------------------------------+ -| Variant Management | | X | -+---------------------------------------------+ -| Shader creation tools | | X | -+---------------------------------------------+ -| Profiling tools | | X | -+---------------------------------------------+ -| Simulink support | | X | -+---------------------------------------------+ - - -Both DSP and DSE can be used to create an user interface for use cases covered -by ADP, ADE, DCP and DCE. - -Licensed Software: QA Tools - -The modules and/or tools that are included in the respective QA Tools product -- Squish (both Tester and execution Licenses), Coco or Test Center - are marked -with "X" in the below table. Optional features that will need additional -licenses are marked with "O". QA Tools include no Redistributables. - -+---------------------------------------------------------------------+ -| | Squish | Coco | Test Center | -+---------------------------------------------------------------------+ -| Squish IDE | X | | | -+---------------------------------------------------------------------+ -| QA Tool-specific command line tools | X | X | X | -+---------------------------------------------------------------------+ -| Coverage Browser | | X | | -+---------------------------------------------------------------------+ -| HTML interface | | | X | -+---------------------------------------------------------------------+ -| Qt Support Module | X | | | -+---------------------------------------------------------------------+ -| Java support module | X | | | -+---------------------------------------------------------------------+ -| Windows support module | X | | | -+---------------------------------------------------------------------+ -| iOS support module | X | | | -+---------------------------------------------------------------------+ -| Android support module | X | | | -+---------------------------------------------------------------------+ -| Web support module | X | | | -+---------------------------------------------------------------------+ -| macOS support module | X | | | -+---------------------------------------------------------------------+ -| VNC support module | X | | | -+---------------------------------------------------------------------+ -| MCU support module | X | | | -+---------------------------------------------------------------------+ -| C and C++ language module | | X | | -+---------------------------------------------------------------------+ -| C# language module | | X | | -+---------------------------------------------------------------------+ -| QML language module | | X | | -+---------------------------------------------------------------------+ -| Tester Cross-Compilation Add-On | O | O | | -+---------------------------------------------------------------------+ - -License capabilities for Squish - -License capabilities that are included in the Squish Tester and Execution -Licenses are marked with "X" in the below table. - -+-----------------------------------------------------------------------------+ -| | Squish Tester License | Squish Execution License | -+-----------------------------------------------------------------------------+ -| Ability to create, edit, | X | | -| and debug test cas | | | -+-----------------------------------------------------------------------------+ -| Ability to execute test | X | X | -| cases | | | -+-----------------------------------------------------------------------------+ - -Install and use capabilities for QA Tools - -Install and use capabilities that are included in the respective QA Tools -products are defined in the below table. - -+-----------------------------------------------------------------------------+ -| | Squish | Squish | Coco | Test | -| | Tester | Execution | License | Center | -| | License | License | | License | -+-----------------------------------------------------------------------------+ -| Number of installation | Unlimited | Unlimited | Unlimited | One(1) | -| instances per license | | | | | -+-----------------------------------------------------------------------------+ -| Number of concurrent | Limited by| Limited by | Limited by | Limited by | -| users | number of | number of | number of | number of | -| | Squish | Squish | Coco | Test Center | -| | Tester | Execution | Tester | Licenses | -| | Licenses | Licenses | Licenses | | -+-----------------------------------------------------------------------------+ - - -APPENDIX 2: PRICING - -Separate template - -APPENDIX 3: ADD-ON PRODUCTS TO LICENSED SOFTWARE - -Intentionally left blank. - -APPENDIX 4: SMALL BUSINESS AND STARTUP - -The provisions of this Appendix 4 are applicable for companies with an annual -revenue, including funding, equivalent to maximum of 250,000 USD (in applicable -currency) during the latest full calendar year, as evidenced by duly audited -records of the Licensee and approved by The Qt Company ("Start-up Company"). - -Start-up Companies are qualified for a discounted License Fee for maximum of -four (4) Development Licenses ("Start-up Development License") unless otherwise -agreed between the parties. - -Start-up Development License entitles the respective Designated User for -Support only for Install Support as defined in Appendix 9, Support Terms. - -Upon expiry of the respective Development License Term, the Start-up -Development Licenses shall be automatically extended, pursuant to Section 3.1 -of the Agreement, for a Renewal Term either as new Start-up Development -Licenses (if the Licensee still qualifies as a Start-up Company), or as normal -then standard list price Development Licenses (if the Licensee no longer -qualifies as a Start-up Company). - -APPENDIX 5: NON-COMMERCIAL AND EDUCATIONAL USE - -The provisions of this Appendix 5 are applicable for non-commercial use of the -Licensed Software by the Licensee. - -For the purpose of this Appendix 5, the following additional definitions -(replacing the relevant definition of the Agreement, where applicable) shall be -applicable: - -"Demo Units" shall mean (i) hardware development platform, which incorporates -the Licensed Software along with Licensee's software and/or hardware, and (ii) -prototype versions of Applications or Devices. - -"Designated User(s)" shall mean the employees and students of the Licensee. - -"Licensee Products" shall mean Applications and/or Devices. - -"Permitted Purpose" shall mean (i) Licensee's internal evaluation and testing -of Licensed Software, (ii) building Demo Units as well as (iii) educational -use. - -"Agreement Term" shall mean a period of twelve (12) months or any such other -period as may be agreed between the Parties. - -For the purpose of this Appendix 5, the following changes shall be agreed with -respect to relevant Sections of the Agreement: - I. Recital (A) shall be replaced in its entirety to read as follows: - "(A) Licensee wishes to use the Licensed Software for the Permitted - Purpose." - II. Section 3.1 shall be replaced in its entirety to read as follows: - "The Qt Company grants to Licensee a personal, non-exclusive, - non-transferable, revocable, royalty-free license, valid for the - Agreement Term, to use, modify and copy the Licensed Software solely - for the Permitted Purpose. Licensee may install copies of the Licensed - Software on five (5) computers per Designated User, provided that only - the Designated Users who have a valid Development License may use the - Licensed Software. Licensee may demonstrate the Demo Units, provided - that such demonstrations must be conducted by Licensee, and the Demo - Units must remain in Licensee's possession and under Licensee's control - at all times. - For clarity, this Agreement does not (i) entitle Licensee to use - Licensed Software to create Applications or Devices (other than - prototypes thereof) or (ii) carry any distribution rights to Licensee, - but such rights are subject to and conditional upon conclusion of a - separate license agreement with The Qt Company." - III. Sections 3.2, 3.3, 3.5, 3.6, 8 and 10 shall be deleted. - IV. Section 3.4 shall be replaced in its entirety to read as follows: - "Licensee shall not: - - remove or alter any copyright, trademark or other proprietary rights - notice contained in any portion of the Licensed Software; - - transfer, publish, sublicense, disclose, display or otherwise make - the Licensed Software available to any third party (except that - Licensee may demonstrate the Demo Units pursuant to Section 3.1); - - in any way combine, incorporate or integrate Licensed Software with, - or use Licensed Software for creation of, any software created with - or incorporating Open Source Qt; Licensee shall cause all Designated - Users who make use of the licenses granted under this Agreement, to - be contractually bound to comply with the relevant terms of this - Agreement and not to use the Licensed Software beyond the terms - hereof. Licensee shall be responsible for any and all actions and - omissions of its Designated Users relating to the Licensed Software - and use thereof. Any use of Licensed Software beyond the provisions - of this Agreement is strictly prohibited and requires an additional - license from The Qt Company." - V. Section 12 shall be replaced in its entirety to read as follows: - "This Agreement shall enter into force upon due acceptance by both - Parties and remain in force for the Agreement Term, unless and until - terminated pursuant to the terms of Section 12. - Upon termination of the Agreement, Licensee shall cease using the - Licensed Software. All other copies of Licensed Software in the - possession or control of Licensee must be erased or destroyed. An - officer of Licensee must, upon request, promptly deliver to The Qt - Company a written confirmation that this has occurred." - -Except for the modifications specified above, this Appendix carries no change -to the terms of the Agreement which shall remain in full force. - -APPENDIX 6: LICENSE REPORTING - -Separate template - -APPENDIX 7: MARKETING RIGHTS - -This Appendix 7 has the purpose to grant visibility through The Qt Company -marketing channels of the usage of Qt and related product and service in -Licensee product. Following related marketing right are agreed between the Qt -Company and the Licensee. - -1. LICENSEE NAME AND LICENSEE LOGO - -The Qt Company has the right to use Licensee name and Licensee logo in public -channel, in respect of the value proposition that the Qt company provided to -the Licensee. - -2. MARKETING CONTENT COOPERATION - -2.1. LICENSEE CASES - -The Licensee is open to collaborate on content creation for marketing and -communication purpose. The Licensee will nominate one responsible that will be -in charge to support The Qt company with this content creation, according to -content format paragraph, answering technical questions or sharing professional -picture or video of required content. The Qt Company will have the right to -advertise this in Content Format and Channel as mentioned in paragraph 3 and 4. - -2.2. FINAL PRODUCT REFERRAL - -Licensee agree that The Qt Company could connect their software product and -services with the Licensee device or application, that the Licensee has created -using The Qt Company technology and competence. Licensee will provide high -quality picture, and video of the created final product where the Qt technology -is running into. The Qt Company will have the right to advertise this in -Content Format and Channel as mentioned in paragraph 3 and 4. - -3. CONTENT FORMAT - -- Video -- Written Licensee case -- Press release -- Social media posts -- Emails -- Event booth Graphics -- Printed material - -4. CHANNELS - -- Social media -- The Qt Company resource center and website -- Email to the Qt company contact database -- Events -- Online webinars -- Public speech -- Public presentations - -APPENDIX 8: INTENTIONALLY LEFT BLANK - -APPENDIX 9: SUPPORT TERMS -Version 2023-04 - -These Qt support terms and conditions (“Support Terms”) set forth the legal -framework, where under The Qt Company (“The Qt Company”) provides support -services (as herein defined) to the Licensee. - -1 DEFINITIONS - -“Application Code” shall mean a computer software program written strictly -using the Qt programming language, by or for the Licensee, with a user -interface, enabling the Licensee or their users to accomplish a specific task -and display any results of the task on the display monitor or screen. - -“Customer Portal” shall mean The Qt Company’s web-based service and support -user interface located at https://account.qt.io/ or at another location -designated by The Qt Company. Customer Portal is used by a Designated User with -Qt Account, and it provides downloads, license management, license certificate -and other services for Designated Users. - -“Dedicated Contact” shall mean the employee of The Qt Company who will be the -first point of contact for all Designated Users’ requests for Support. - -“Errors” shall mean an error, flaw, mistake, failure, or fault in Licensed -Software that prevents it from behaving as described in the relevant -documentation or as agreed between the Parties. Designated User can follow the -state and progress of Errors in Customer Portal. - -“Extended Support” shall mean a continuation to the normal Support period, -which allows Designated Users to receive selected Support (Standard Support or -Premium Support) for a version of Licensed Software that is no longer generally -supported by The Qt Company. - -”Install Support” shall mean Support that is limited to installation-related -Error(s) on Development Platforms specified as supported host platforms for -each Qt release under doc.qt.io. Install Support covers also operational use of -the QA Tools, but not operational use of Qt Software. - -“Maintenance Release” shall mean a release or version of Licensed Software -containing bug fixes, error corrections and other changes targeted to -maintaining and improving product stability and quality. Maintenance Releases -are generally depicted as a change to the third digit of Licensed Software -version number. - -“Platforms” shall mean both Development Platforms and Deployment Platforms. -Supported host and target Platforms may vary from for each Qt release as -defined under doc.qt.io. - -“Premium Support” shall mean an upgraded level of Support that The Qt Company -provides pursuant to these Support Terms to Licensee if Licensee has purchased -Premium Support instead of Standard Support. Premium Support also covers what -is included in Standard Support. Premium Support shall always be purchased for -all Designated User(s) in the respective development team of the Licensee. - -“Qt Account” shall mean the Qt Account for a Designated User used for using Qt -services and Customer Portal. A Qt Account is mapped to the Licensee company -with the corporate email domain or domains. - -”Qualification Kit” shall mean a set of documents and validation test cases -used for product certification needs as defined in section 2.6. - -“Response Time” shall mean the period of time from when Licensee notifies The -Qt Company about an Error or requests Support until The Qt Company provides -Licensee with a response that addresses (but not necessarily resolves) the -reported Error or provides the requested Support. - -“Standard Support” shall mean standard level of Support that The Qt Company -provides pursuant to these Support Terms to Licensee. Standard Support also -covers what is included in Install Support. - -“Security Issue” shall mean an Error that may cause a vulnerability in a system -or application that uses the Licensed Software. - -“Support” shall mean developer assistance that is provided by The Qt Company to -assist eligible Designated Users in Licensed Software installation, usage and -functionality problem resolution for Error(s) and Error workarounds pursuant to -the terms of these Support Terms. Support for different products is available -as specified in the below table (‘X’ marking the Support that is included in -the license price, optional Add-on Support services are marked as ‘O’): - -+-----------------------------------------------------------------------------+ -| | Install| Standard| Premium| Extended| Qualification| -| | Support| Support | Support| Support | Kit | -+-----------------------------------------------------------------------------+ -| DSP | X | X | O | O | | -+-----------------------------------------------------------------------------+ -| DSE | X | X | O | O | | -+-----------------------------------------------------------------------------+ -| ADP | X | | | | | -+-----------------------------------------------------------------------------+ -| ADE | X | X | O | O | | -+-----------------------------------------------------------------------------+ -| DCP | X | X | O | O | | -+-----------------------------------------------------------------------------+ -| DCE | X | X | O | O | | -+-----------------------------------------------------------------------------+ -| Squish | X | X | O | | O | -+-----------------------------------------------------------------------------+ -| Coco | X | X | O | | O | -+-----------------------------------------------------------------------------+ -| Test Center | X | X | O | | O | -+-----------------------------------------------------------------------------+ -| Axivion Suite | X | X | | | | -+-----------------------------------------------------------------------------+ -| Architecture Analysis | X | X | | | | -+-----------------------------------------------------------------------------+ -| Static Code Analysis | X | X | | | | -+-----------------------------------------------------------------------------+ -| Static Coverage | X | X | | | | -| Analysis Professional | | | | | | -+-----------------------------------------------------------------------------+ -| Qt Insight | | X | | | | -+-----------------------------------------------------------------------------+ - -“Support Validity Term” shall mean the Development License Term or any other -fixed time period agreed between the Parties during which time the Licensee is -eligible to receive Support from The Qt Company. - -2 SUPPORT SERVICES - -2.1 Support Services Provided by The Qt Company - -Subject to these Support Terms and during the Support Validity Term, The Qt -Company will via its Customer Portal, provide Designated User(s) with Support -for the Licensed Software which Licensee has licensed under the Agreement. The -Qt Company will make commercially reasonable efforts to solve any Errors -reported by Designated User(s). Resolution of an Error may be provided through -Designated User(s) themselves downloading of a later released version of the -applicable Licensed Software product(s) or providing the Designated User with a -workaround addressing such Error or providing the Designated User with an -updated tool configuration. - -2.2 Licensee's Obligations - -To report an Error, the Designated User shall register the Error on the -Customer Portal. If the Designated User considers the reported Error to be a -Security Issue, the Error shall be marked as a Security Issue. - -The Designated User must provide adequate information and documentation to The -Qt Company to enable it to recreate the Error or problem for which the -Designated User has sought assistance. To ensure efficient handling of Errors, -the Designated User must provide the following information, where relevant: -- A clear, detailed description of the problem, question or suggestion; -- Identification of which Licensed Software product and version is affected; -- Identification of the operating environment (e.g. operating system, hardware - Platform, build tools, tool configuration, etc.) on which the problem exists; -- Marking the issue as a Security Issue, when reporting a Security Issue; -- On Standard Support: A complete and compilable test case of not more than 500 - lines of code that demonstrates the problem; -- On Premium Support: A complete and compilable test case that demonstrates the - problem or access to Application Code source codes. - -Additional relevant content, such as screenshots, etc. -Additional content should be included as attachments. The preferred image -formats are JPEG and PNG. Compressed content should be included in zip or -tar.gz archives. Executable content and documents in platform specific formats -such as Microsoft Office' are not accepted. - -In order for The Qt Company to provide prompt handling of Errors, the -Designated User shall promptly respond to any requests from The Qt Company for -additional information. - -2.3 Support Limitations - -General limitations: - -Each version or release of the Licensed Software will be Supported under -Standard Support or Premium Support only for limited time period as set forth -in doc.qt.io or in documentation provided with the respective Licensed Software -product. If nothing is documented, a release of Licensed Software is supported -for one (1) year from the release date of the version x.y.0 and Long Term -Support (LTS) Releases are supported for a period of three (3) years from the -release date of the LTS version x.y.0. - -The Qt Company shall only provide Support for Designated User(s) through -Customer Portal.Support is made available for the entire development teams -only: It is not allowed to purchase Support only for some members of the -development team, and all Designated Users of the respective development team -must be eligible for the same level of Support. - -Support is not provided for snapshots, preview releases, beta releases or -release candidates. - -The Qt Company shall have no obligation to provide Support for 3rd party -components, hardware or operating system specific problems or problems arising -from improper use, accident, neglect, or modification of Qt. - -Limitations with Install Support: - -Support limited to (i) Error(s) regarding installation and setting up of the Qt -development environment on host Platforms, or (ii) Errors impacting operational -use of the QA Tools. - -Limitations with Standard Support: - -The Qt Company shall not provide Support for third-party software or problems -caused by third-party software even if such third-party software is distributed -together with Licensed Software product(s). - -The Qt Company shall only provide Support for Error(s) that are reported on and -can be reproduced on Platforms that are officially supported for the release of -the Licensed Software. - -Limitations with Premium support: - -The Qt Company shall not provide Support for third-party software or problems -caused by third-party software. However, if such third-party software is -distributed together with Licensed Software, The Qt Company will make -commercially reasonable efforts to solve such problems. - -The Qt Company shall only provide Support for Error(s) that can be reproduced -on Platforms that are officially supported for the release of the Licensed -Software. If the Error is on a Platform that is not supported, The Qt Company -will make commercially reasonable efforts to provide a solution on closest -corresponding supported Platform. - -Premium Support is optional and purchased for an agreed bucket of hours -(“Bucket”). Hours can be used by any Designated User in the respective -development team. To encourage continuous usage of the Support, ten percent -(10%) of the purchased Bucket shall automatically expire (regardless of whether -such support hours are actually used or not by the Licensee) each month after -three (3) months from the purchase of the Premium Support. - -2.4 Handling of Security Issues - -The reported Errors marked as Security Issues will be assessed by experts to -determine the severity of the issue and to verify if it indeed is a valid -Security Issue. The Designated User who reported the issue may be contacted for -more details. If the reported issue is not deemed to be a Security Issue, it -will be treated as a normal Error and handled accordingly. - -A verified Security Issue will be fixed as soon as possible. Qt Company will -notify all Licensees via appropriate channels about the Security Errors and -availability of patches for Licensed Software. Typically, a fix for the -Security Issue is included in the next Maintenance Release of Licensed -Software. - -If the Security Issue is reported in a third-party library used in Licensed -Software, The Qt Company will notify the relevant third party of such Security -Issue detected in their library. When the Security Issue is fixed in the -third-party library, the new version of the third-party library will be in the -next feasible Maintenance Release of the Licensed Software. If a fixed version -of the third-party library is not available, The Qt Company may instead decide -to include documentation regarding the issue, or a patch for this third-party -library. - -All known Security Issues in Licensed Software will be mentioned as part of the -change notes released with each version of Licensed Software. - -2.5 Extended Support - -Extended Support extends the Support Validity Term for a release of Licensed -Software that is no longer generally supported. - -Extended Support includes and is by default provided with Standard Support -rules and limitations, unless Extended Support is purchased together with -Premium Support in which case Premium Support rules and limitations will apply. - -Extended Support is optional and purchased with annual fee and separately per -each Licensee product. Extended Support will need definition of (i) Licensee -product, (ii) used Platform(s) and (iii) Licensed Software version(s). For -avoidance of doubt, Extended Support requires that the Designated User has a -valid license for the respective Licensed Software. - -2.6 Qualification Kit - -The Qt Company shall provide a set of documents and validation tests that -enable the Licensee to qualify QA testing tool (subject to a separate fee) or -Qt Safe Renderer for the purpose of safety certification of Licensee end-to-end -solution. Exact complied safety standards may vary between products, used -features, use case, and industry. - -3 RESPONSE TIME - -In performing Support, The Qt Company shall commit to following, non-binding, -Response Times: - -Standard Support: Errors and Support requests will have a Response Time not to -exceed two (2) business days. - -Premium Support: Errors and Support requests will have a Response Time not to -exceed one (1) business day. - -Security Issues: Errors that are Security Issues will have a Response Time not -to exceed one (1) business day. - -For complex issues, The Qt Company may provide an initial response to the -Designated User and then follow up, without undue delay, with additional -communication before an Error is properly addressed or Support provided. - -4 ADDITIONAL SERVICES IN PREMIUM SUPPORT - -The Designated User(s) will be assigned a Dedicated Contact to handle requests -for Support. Dedicated Contact is subject to change in cases such as sick -leave, vacation and other similar reasons. - -The Designated User(s) can on request ask The Qt Company to access their -computer remotely in order to resolve problems directly. - -The Designated User(s) can request a session via Instant Messaging or phone -call in the support request to The Qt Company. - -Premium Support can assist Licensee in implementing new features, bug fixes -and accessing patches in Licensed Software or Application Code. - -All Support requests will be handled with high priority. - -5 MAINTENANCE RELEASES, UPDATES AND UPGRADES - -Under the Support the Licensee is eligible for Maintenance Releases and Updates -that The Qt Company generally makes available to customers who has purchased -Support. Unless otherwise decided by The Company at its free and absolute -discretion, Upgrades will not be provided under the Support. - -The primary focus of Maintenance Releases is product quality. Therefore, each -Maintenance Release typically includes the following types of changes to the -previous version of Licensed Software: -- Bug fixes caused by changes to previously working code; -- Fixes related to build issues on supported Platforms; -- Error corrections specific to a single Platform that are not present on other - Platforms; -- Corrections to Security Issues; -- Critical Error corrections such as crashes, data corruption, loss of data, - race conditions; and -- Updates to documentation and license information when deemed necessary by - The Qt Company. - -The primary focus of Updates is introducing new features to Licensed Software -and covering new platforms. Therefore, each Updates typically includes the -following types of changes to the previous version of Licensed Software: -- New platform support; -- New toolchain support; -- New features and Qt modules; - -6 WARRANTY DISCLAIMER - -The Qt Company makes no warranties that the Support provided will be successful -in resolving any difficulties or problems or in diagnosing faults reported by -Licensee. Support is provided to Licensee on an "as is" basis. To the maximum -extent permitted by applicable law, The Qt Company disclaims all warranties and -conditions, either express or implied, including, but not limited to, implied -warranties of merchantability and fitness for a particular purpose for the -Support provided by The Qt Company to Licensee. - -APPENDIX 10: CONVERSION TO SUBSCRIPTION - -Subject to the terms of this Appendix Licensee's current development licenses -("Current Licenses") for commercial version of Qt Software and the license -agreements governing such Current Licenses ("Existing Agreements") are being -replaced by this Agreement and subscription based Development Licenses -governed hereunder, as further specified below. - -+---------------------------------------------------------------------------+ -| Existing Agreement(s) | and | -| signing parties, version | | -| thereof | | -+---------------------------------------------------------------------------+ - -Parties hereby agree on conversion of Current Licenses listed in attached -Exhibit A to the subscription licenses listed in attached Exhibit B for use -through License Term. As of the date hereof, - -i. Licensee's Current Licenses as listed in Exhibit A shall terminate and be -replaced with the Subscription licenses listed in Exhibit B and; -ii. Existing Agreements are terminated. - -Prices for the conversion of Current Licenses are defined in Appendix 2 -Pricing or Quote. - -Notwithstanding anything in this Appendix to the contrary, and in addition to -any payments due pursuant to this Appendix, Licensee remains fully obligated to -fulfill any and all outstanding payment obligations to The Qt Company under any -applicable Existing Agreements. For the avoidance of doubt, if any payments -remain outstanding on the Current Licenses under the applicable terms Licensee -will continue to make such payments in accordance with the applicable order -documentation, notwithstanding the fact that the Current Licenses are being -converted to Development Licenses pursuant to this Appendix. - -APPENDIX 11: TERMS OF USE - QT INSIGHT TRACKER LIBRARY -Version 1.0 - -Qt Insight Tracker Library ("Tracker Library") is a software module used to -collect end user data from Customer's Application and Devices relating to The -Qt Company's Qt Insight online service the Customer is ordering from The Qt -Company under a separate service agreement ("Service Agreement"). - -Unless otherwise set forth herein, definitions written in capital letters used -herein shall have the meaning set forth in the Service Agreement. - -Subject to these terms The Qt Company grants to Customer a worldwide, -non-exclusive, non-transferable, royalty-free, revocable (for cause) right and -license, valid for the term of the Service Agreement, to - (i) use, copy and modify Tracker Library for the purpose of including it - into the Devices and Applications and solely for the purpose of being - used only in conjunction with Insight Cloud or Insight Private Cloud, - and - (ii) distribute, by itself or through its Contractors, Tracker Library as - installed, incorporated, or integrated into Applications and/or - Devices. - -Use of Tracker Library in a way or for the purpose other than the above is -strictly prohibited. Tracker Library is licensed to the Customer in all -respects "as is". - -TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE QT COMPANY ON BEHALF OF -ITSELF AND ITS LICENSORS, SUPPLIERS AND AFFILIATES, DISCLAIMS ALL OTHER -WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND -NON-INFRINGEMENT WITH REGARD TO THE TRACKER LIBRARY. THE QT COMPANY DOES NOT -WARRANT THAT THE TRACKER LIBRARY WILL SATISFY CUSTOMER'S REQUIREMENTS OR THAT -IT WILL OPERATE WITHOUT DEFECT OR ERROR OR THAT THE OPERATION THEREOF WILL BE -UNINTERRUPTED. -IN NO EVENT SHALL THE QT COMPANY BE LIABLE TO THE CUSTOMER FOR ANY LOSS OF -PROFIT, LOSS OF DATA, LOSS OF BUSINESS OR GOODWILL OR ANY OTHER INDIRECT, -SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE COST, DAMAGES OR EXPENSE OF ANY -KIND, HOWSOEVER ARISING UNDER OR IN CONNECTION WITH THE USE OF THE TRACKER -LIBRARY. - -THE TOTAL MAXIMUM LIABILITY OF THE QT COMPANY UNDER THESE TERMS SHALL IN NO -EVENT EXCEED 10,000 EUROS. +Qt Frame Agreement +Version 2024-02 + +1. PARTIES OF THIS AGREEMENT +1.1. This Qt Frame Agreement—comprised of these general terms together with the appendices attached hereto, (hereinafter “Agreement”) is made by and between: The Qt Company, as defined below (hereinafter ”The Qt Company”) AND Customer name (hereinafter “Customer"):___________________ Business Id (e.g. VAT or EIN number):___________________ +1.2. The parties above are hereinafter individually referred to as a "Party" and collectively as the "Parties". + +2. STRUCTURE AND OBJECT OF THE AGREEMENT +2.1. The Parties have entered into this Agreement to agree on the terms and conditions applicable to The Qt Company's delivery of products and services ("Services") to Customer. +2.2. This Agreement is comprised of the following components: +(i) This Agreement, which contains the general terms applicable to all Services, +(ii) Appendices for each of the Services, containing terms applicable to that individual set of Services ("Service Terms"), +(iii) a Qt Appendix for Pricing, if applicable, which contains pricing for specific Services, and +(iv) other topic-specific appendices, such as Support or Marketing Rights. +2.3. Any and all Services purchased shall be specified in, and agreed upon between, the Parties under a separate purchase order, statement of work, quote, or similar document ("Purchase Document"). Each Purchase Document concluded under this Agreement shall include a reference to this Agreement and be governed by this Agreement. + +3. DEFINITIONS +3.1. "Affiliate" of a Party shall mean an entity (i) which is directly or indirectly controlling such Party; (ii) which is under the same direct or indirect ownership or control as such Party; or (iii) which is directly or indirectly owned or controlled by such Party. For these purposes, an entity shall be treated as being controlled by another if that other entity has fifty percent (50 %) or more of the votes in such entity, is able to direct its affairs and/or to control the composition of its board of directors or equivalent body. +3.2. "Contractor" shall mean third-party consultants, distributors and contractors performing services to Customer under an applicable contractual arrangement. +3.3. "Customer" shall mean the individual or legal entity specified in Section 1 above, that is a Party to this Agreement. +3.4. "Force Majeure Event" shall have the meaning set forth in Section 11.7. +3.5. "Licensed Software" shall mean The Qt Company's commercial software product which is licensed for use by Customer under this Agreement and corresponding Service Terms. Licensed Software shall include, if and to the extent applicable and specified in the applicable relevant Service Terms, corresponding online or electronic documentation, associated media and printed materials, including the source code, and example programs. The Qt Company may in the course of its development activities, at its free and absolute discretion and without any obligation to send or publish any notifications to Customer or in general, make changes, additions or deletions in the components and functionalities of the Licensed Software, provided that no such changes, additions or deletions will affect the already released version of the Licensed Software, but only upcoming version(s). Licensed Software is commercial computer software, developed at private expense and offered to the public under standard commercial terms. +3.6. "Professional Services" shall mean The Qt Company's professional-, consulting-, training- and/or project services delivered to Customer under this Agreement and specified in a Purchase Document. +3.7. "Support" shall mean maintenance and support services provided by The Qt Company to assist Customer in using the Licensed Software, as further specified in the Appendix for Support Terms. +3.8. "The Qt Company" shall mean: +(i) in the event Customer is an entity residing in the United States or a legal entity incorporated in or having its headquarters in the United States, The Qt Company Inc., a Delaware corporation with its office at 3031 Tisch Way, 110 Plaza West, San Jose, CA 95128, USA.; or +(ii) in the event Customer is an entity residing outside of the United States or a legal entity incorporated or having its registered office outside of the United States, The Qt Company Oy., a Finnish company with its registered office at Miestentie 7, 02150 Espoo, Finland. + +4. PRICES AND PAYMENT +4.1. The Qt Company agrees to make Services available to Customer subject to the prices set forth in the Appendix for Pricing. In the event that the Appendix for Pricing does not include a price for certain Services, the applicable price shall be the price agreed by the Parties in the respective Purchase Document. +4.2. All prices are exclusive of value added tax or other taxes, levels, or duties. Value added tax as well as other possible public charges imposed by authorities shall be added to the prices. +4.3. All fees under this Agreement are non-cancellable and non-refundable. +4.4. All fees under this Agreement shall be paid by Customer no later than thirty (30) days from the date of the applicable invoice from The Qt Company. +4.5. Unless otherwise agreed or provided in the respective Service Terms or Purchase Document, The Qt Company will invoice fees for: +4.5.1. Licensed Software and Support in advance upon conclusion of the Purchase Document, and +4.5.2. Professional Services monthly in arrears after the Service has been performed. +4.6. A late payment charge of the lower of: (a) one percent (1%) per month; or (b) the highest interest rate stipulated by applicable law, shall be charged on any unpaid balances that remain past due and which have not been disputed by Customer in good faith within thirty (30) days of receipt of invoice from The Qt Company. +4.7. The Qt Company may either (i) invoice Customer based on existing agreement, (ii) request Customer to place a purchase order corresponding to a quote by The Qt Company, or (iii) use Customer's stored Credit Card information to automatically charge the Customer for the relevant Renewal Term. +4.8. Unless and to the extent otherwise agreed in the Appendix for Pricing or in the Purchase Document, The Qt Company shall be entitled to adjust the prices set forth in the Appendix for Pricing by notifying Customer of the change in writing at least sixty (60) days before the effective date of the change. The change shall not affect the current pricing term of Services agreed upon before the effective date of the change. + +5. CONFIDENTIALITY +5.1. The Parties shall keep confidential, and shall not use or disclose to any unauthorized third parties, the existence and content of this Agreement as well as any Confidential Information received from the other Party or otherwise learned in connection with the Agreement or the performance of the Services, without the prior written consent of the other Party. Confidential Information shall mean information that is designated as confidential or that would be reasonably understood to be confidential given the circumstances of disclosure and the nature of the information. The Parties shall not use Confidential Information received from the other Party for any other purposes than the performance of the Agreement or the fulfilment of their rights and obligations hereunder. +5.2. Each Party shall limit access the other Party's Confidential Information only to those of its employees, subcontractors, Contractors, Affiliates or financial or legal advisors who necessarily need access to the Confidential Information for the proper performance of the Party's rights and obligations under the Agreement. Each Party shall ensure that the persons receiving Confidential Information of the other Party are bound by confidentiality obligations not less restrictive than those stipulated herein. +5.3. Each Party shall protect the confidentiality of the other Party's Confidential Information with at least the same degree of security as it exercises to its own confidential information, but no less than a standard of reasonable care. +5.4. The confidentiality obligation stipulated herein shall not be applied to material and information which: +(iii) has become generally available or otherwise public prior to its submission by the other Party; +(iv) becomes generally available or otherwise public due to a reason other than the negligence or omission of the recipient or its personnel or other actions in violation of this Agreement or applicable legislation; +(v) the Party has lawfully received from a third party without any obligation of confidentiality; +(vi) was lawfully in the possession of the receiving Party prior to receipt of the same from the other Party without any obligation of confidentiality related thereto; +(vii) a Party has developed independently without using material or information received from the other Party; or +(viii) a Party must disclose pursuant to law, decree or other order issued by competent regulatory or governmental body or other public authority or a judicial order, in which case the Party shall, to the extent permitted by applicable law, inform the other Party in writing of the disclosure of information prior to such disclosure. +5.5. Each Party shall, upon request of the other Party at any time, including upon termination, cancellation or expiry of the Agreement, promptly destroy or deliver to the other Party any and all the documents, files, copies and material containing Confidential Information of the other Party. Notwithstanding the foregoing, a Party may retain one copy of the Confidential Information in a secure location, if and solely to the extent required to comply with applicable laws or regulations. Any Confidential Information stored in electronic back-up form shall be rendered inaccessible and destroyed in accordance with standard back-up procedures. + +6. INTELLECTUAL PROPERTY RIGHTS +6.1. Unless and to the extent expressly provided in the respective Service Terms, this Agreement carries no assignment or license to the intellectual property rights of either Party and all such rights are and shall remain the exclusive property of the Party to whom such rights are vested under applicable law at the signing of this Agreement or thereafter. +6.2. Where The Qt Company's delivery includes any materials owned by a third party, such third party materials shall be governed in all respects by the applicable license terms of such third-party right holders. The Qt Company shall duly inform the Customer whenever such third party materials are included in the Services and of applicable license terms to be followed by the Customer in using such third party materials. + +7. FEES AND ORDERING +7.1. Services Fees. Services Fees are described in the Purchase Document. +7.2. Ordering Services. +(i) Customer may purchase Services pursuant to agreed pricing terms or, if no specific pricing terms have been agreed upon, at The Qt Company's standard pricing terms applicable at the time of purchase. +(ii) Unless expressly otherwise agreed, any price or other term quoted to Customer shall only be valid for the thirty (30) days from the date such price has been quoted. + +8. LIMITED WARRANTY AND WARRANTY DISCLAIMER +8.1. The Qt Company hereby represents and warrants that: (i) it has the power and authority to grant the rights and licenses granted to Customer under this Agreement; (ii) the Licensed Software will operate materially in accordance with its specifications (as set forth in the applicable product documentation or, where relevant, program description); (iii) Professional Services and Support will be performed in a professional, workmanlike manner pursuant to the Agreement; and (iv) during the ten years prior to the effective date of this Agreement, there have not been any claims alleging that the Licensed Software has infringed any intellectual property rights of a third party and, to the knowledge of The Qt Company as of the effective date of this Agreement, no such infringement exists. These warranties do not apply to issues arising from, or relating to, any third-party materials or Customer's use of the Licensed Software in violation of applicable law or the terms of this Agreement. +8.2. Except to the extent set forth above, the Services are delivered to Customer "as is" and to the maximum extent permitted by applicable law, exclusive of other warranties, whether express, implied, or otherwise. Customer's sole and exclusive remedy and The Qt Company's entire liability for deficiencies or errors in the Services shall be limited, at The Qt Company's option, to correction of the error, replacement of the Services, re-performance of the Service or return of the applicable fees paid for the defective Service for the time period during which Customer was not able to utilize the Service as agreed. + +9. LIMITATION OF LIABILITY +9.1. EXCEPT FOR (I) CASES OF GROSS NEGLIGENCE OR INTENTIONAL MISCONDUCT, (II) A BREACH OR VIOLATION OF THE OTHER PARTY'S INTELLECTUAL PROPERTY RIGHTS, OR (III) WHERE REQUIRED BY APPLICABLE LAW, IN NO EVENT SHALL EITHER PARTY BE LIABLE TO THE OTHER PARTY FOR ANY LOST PROFITS, LOSS OF DATA, LOSS OF BUSINESS OR GOODWILL OR ANY OTHER INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE COST, DAMAGES OR EXPENSE OF ANY KIND, HOWSOEVER ARISING UNDER OR IN CONNECTION WITH THIS AGREEMENT. +9.2. EXCEPT FOR (I) CASES OF GROSS NEGLIGENCE OR INTENTIONAL MISCONDUCT, (II) A BREACH OR VIOLATION OF THE OTHER PARTY'S INTELLECTUAL PROPERTY RIGHTS, AND TO THE EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL EITHER PARTY'S TOTAL AGGREGATE LIABILITY UNDER THIS AGREEMENT EXCEED THE AGGREGATE FEES PAID OR PAYABLE TO THE QT COMPANY BY CUSTOMER FOR THE RESPECTIVE LICENSED SOFTWARE OR SERVICE GIVING RISE TO THE LIABILITY. THE FOREGOING LIMITATION WILL NOT APPLY TO CUSTOMER'S OBLIGATION TO PAY THE APPLICABLE FEES CORRESPONDING TO ITS ACTUAL USE OF LICENSED SOFTWARE OR SERVICES. + +10. TERM AND TERMINATION +10.1. This Agreement shall enter into force upon signing by both Parties and is effective as of the last date of signature. +10.2. This Agreement shall remain in force until further notice and may be terminated without cause by either Party by no less than three (3) months' prior written notice to the other Party. +10.3. Termination of a particular Purchase Document and the Services governed thereunder shall be stipulated under the applicable Service Terms. +10.4. Either Party may terminate this Agreement with immediate effect, if the other Party: +(i) commits a material breach of the terms of this Agreement (including applicable Service Terms) and has not remedied such breach within a reasonable period of time (which shall be no less than thirty (30) days) of the non-breaching Party's written notice specifying the breach, or +(ii) becomes bankrupt, insolvent or goes into liquidation or debt restructuring. +10.5. Termination of this Agreement shall, as such, have no effect on the validity of any Services ordered and agreed prior to the effective date of such termination, and such Services shall continue to remain in force pursuant to applicable Service Terms (including the terms of this Agreement) for the remainder of the duration of the applicable Service validity term. + +11. GOVERNING LAW AND DISPUTE RESOLUTION +11.1. The United Nations Convention on Contracts for the International Sale of Goods will not apply to this Agreement. +11.2. Where this Agreement is concluded with The Qt Company, Inc., a Delaware corporation, the Parties agree that this Section 10.2 will apply. This Agreement will be governed by, and construed in accordance with the laws of the State of California and any controlling United States federal law. Any dispute, controversy or claim arising out of or relating to this contract, including the formation, interpretation, breach or termination thereof, and whether the claims asserted are arbitrable, will be referred to and finally determined by arbitration in accordance with the JAMS International Arbitration Rules. The tribunal will consist of one arbitrator. The place of arbitration will be San Francisco, California, USA. The language to be used in the arbitral proceedings will be English. Judgment upon the award rendered by the arbitrator(s) may be entered in any court having jurisdiction thereof. This Section 10.2 shall not preclude parties from seeking provisional remedies in aid of arbitration from a court of appropriate jurisdiction. Notwithstanding the foregoing, any action by The Qt Company solely to collect license or other fees hereunder may be brought in any court of competent jurisdiction. +11.3. Where this Agreement is concluded with The Qt Company, Oy., a Finnish company, the parties agree that this Section 10.3 will apply. This Agreement shall be construed and interpreted in accordance with the laws of Finland, excluding its choice of law provisions. All disputes arising out of or in connection with this Agreement shall be finally settled in accordance with the laws of Finland, excluding its choice of law provisions. All disputes arising out of or in connection with this Agreement shall be finally settled under the Rules of Arbitration of the International Chamber of Commerce by one or more arbitrators appointed in accordance with the said Rules. The place of arbitration will be Helsinki, Finland. The language to be used in arbitral proceedings will be English. This Section 10.3 shall not preclude parties from seeking provisional remedies in aid of arbitration from a court of appropriate jurisdiction. + +12. MISCELLANOUS +12.1. No Assignment. Customer shall not be entitled to assign or transfer all or any of its rights, benefits and obligations under this Agreement except in case of sale of relevant business or assets or otherwise with prior written consent of The Qt Company, which shall not be unreasonably withheld or delayed. The Qt Company shall be entitled to freely assign or transfer any of its rights, benefits or obligations under this Agreement. +12.2. Surviving Sections. Any terms and conditions that by their nature or otherwise reasonably should survive termination of this Agreement shall so be deemed to survive. +12.3. Entire Agreement. This Agreement, its Appendices and any applicable Purchase Documents constitute the complete agreement between the Parties and supersedes all prior or contemporaneous discussions, representations, contracts (including prior License Agreements and similar prior agreements), and proposals, written or oral, with respect to the subject matters discussed herein. +12.4. Subcontractors. The Qt Company may utilize subcontractors in the performance of Services under this Agreement, provided that The Qt Company remains responsible for the performance of the Services and compliance with this Agreement, as well as ensuring that subcontractors are required to abide by relevant restrictions (e.g., confidentiality) set forth in this Agreement. +12.5. Modifications. No modification of this Agreement shall be effective unless contained in a writing executed by an authorized representative of each Party. No standard terms and conditions or provisions of any Customer purchase order or other ordering form that Customer may use in connection with the acquisition of Services will modify or affect this Agreement, the parties agree that any such terms and conditions are void with no legal effect. +12.6. Affiliate Orders. Customer Affiliates may purchase Services via this Agreement as follows: +(i) any purchases by Customer Affiliates from The Qt Company or its Affiliates will create a contractual relationship directly between the relevant The Qt Company entity and the respective ordering Customer Affiliate; +(ii) the entry into a Purchase Document between The Qt Company and Customer Affiliate creates an agreement between The Qt Company and Customer Affiliate and incorporates all terms and conditions of this Agreement as the governing agreement between The Qt Company and Customer Affiliate ("Accession Agreement"): and +(iii) Customer Affiliate will be deemed "Customer" under the terms of this Agreement and all rights and obligations under such Accession Agreement are vested and borne solely by the ordering Customer Affiliate and the relevant The Qt Company entity as contracting parties under such Accession Agreement. +12.7. Force Majeure. Neither Party shall be liable to the other for any delay or non-performance of its obligations hereunder in the event and to the extent that such delay or non-performance is due to an event of act of God, terrorist attack or other similar unforeseeable catastrophic event that prevents either Party for fulfilling its obligations under this Agreement and which such Party cannot avoid or circumvent ("Force Majeure Event"). If the Force Majeure Event results in a delay or non-performance of a Party for a period of three (3) months or longer, then either Party shall have the right to terminate the relevant Purchase Document and Services thereunder with immediate effect without any liability (except for the obligations of payment arising prior to the Force Majeure Event) towards the other Party. +12.8. Notices. Any notice given by one Party to the other shall be deemed properly given and deemed received if specifically acknowledged by the receiving Party in writing or when successfully delivered to the recipient by hand, fax, or special courier during normal business hours on a business day to the addresses specified for each Party in this Agreement. Each communication and document made or delivered by one Party to the other Party pursuant to this Agreement shall be in the English language. +12.9. Attorney Fees. The prevailing Party in any action to enforce this Agreement shall be entitled to recover its attorney's fees and costs in connection with such action. +12.10. Privacy and Security. The Parties commit to and comply with their respective applicable obligations under the privacy and security terms set forth in the Privacy and Security Appendix and relevant Appendices attached hereto. +12.11. Feedback. Customer agrees that, from time to time, The Qt Company, may request feedback from Customer regarding the Services ("Feedback"). Customer may choose to provide Feedback and agrees that The Qt Company may freely use, copy, disclose, and exploit any Feedback. No Feedback will be considered Customer Confidential Information unless explicitly agreed otherwise between the Parties. +12.12. Export Control. Customer acknowledges that the Services, or portions thereof, may be subject to export control restrictions under the applicable laws of respective countries. Customer shall fully comply with all applicable export license restrictions and requirements, economic sanctions restrictions, as well as with all laws and regulations relating thereto, and shall procure all necessary governmental authorizations, including without limitation, all necessary licenses, approvals, permissions, or consents, where necessary (e.g., for re-exportation of the Redistributables, Applications and/or Devices, each as defined in the relevant Service Terms). +12.13. Severability. If any provision of this Agreement shall be adjudged by any court of competent jurisdiction to be unenforceable or invalid, that provision shall be limited or eliminated to the minimum extent necessary so that this Agreement shall otherwise remain in full force and effect and enforceable. + +13. APPENDICES +13.1. The following appendices form an integral part of this Agreement. In case of a discrepancy between this Agreement and any of its Appendices, this Agreement shall prevail. In case of discrepancies between the Purchase Document(s) and this Agreement or applicable Service Terms, the terms of this Agreement or the applicable Service Terms shall prevail, except in cases where an express deliberate deviation from the terms of this Agreement or applicable Service Terms has been concluded pursuant to Section 2.3 hereof, in which case the Purchase Document shall prevail. +1. Appendix for Qt Development Framework +2. Appendix for Support Terms https://www.qt.io/terms-conditions/support-terms +3. Appendix for Privacy and Security Terms https://www.qt.io/terms-conditions/privacy-and-security + +Appendix for Qt Development Framework +Version 2024-02 + +1. This Appendix for Qt Development Framework is an integral part of the Agreement and specifies the legal terms for the licensing of Licensed Software (as defined below) between The Qt Company and the Customer. Entry into this Appendix governs the use of and supersedes any prior contracts between the Parties (including prior License Agreements and similar prior agreements), with respect to the Licensed Software under this Appendix. + +2. DEFINITIONS +2.1. Capitalized words used in this Appendix shall have the meanings described in the Agreement or as defined below. +2.2. "Add-on Products" shall mean The Qt Company's specific add-on software products which are not licensed as part of The Qt Company's standard Services offerings, but shall be included into the scope of Licensed Software only if so specifically agreed between the Parties. +2.3. "Application" means software products created using the Licensed Software, which include the Redistributables, or part thereof. +2.4. "End Customer" shall mean Customer's customer(s) to whom Customer, directly or indirectly, distributes copies of the Redistributables as integrated or incorporated into Applications or Devices. +2.5. "Data Protection Legislation" shall mean the General Data Protection Regulation (EU 2016/679) (GDPR) and any national implementing laws, regulations and secondary legislation, as may be amended or updated from time to time, as well as any other data protection laws or regulations applicable in the relevant territory. +2.6. "Deployment Platforms" shall mean target operating systems and/or hardware specified in the License Certificate, on which the Redistributables can be distributed pursuant to the terms and conditions of this Appendix. +2.7. "Designated User(s)" shall mean the employee(s) of Customer or Customer's Affiliates acting within the scope of their employment or Customer's Contractors acting within the scope of their services on behalf of Customer. +2.8. "Development License" shall mean the license needed by the Customer for each Designated User to use Licensed Software under the license grant described in Section 5 of this Appendix. Development Licenses are available per respective Licensed Software products; each product having its designated scope and purpose of use. +2.9. "Development Platforms" shall mean the host operating system(s) specified in the License Certificate, on which Licensed Software can be used under the Development License. +2.10. "Devices" shall mean +(i) hardware devices or products that +a. are manufactured and/or distributed by the Customer, its Affiliates, Contractors or End Customer, and +b. incorporate, integrate or link to Applications such that substantial functionality of such unit, when used by an End User, is provided by Application(s) or otherwise depends on the Licensed Software; or +(ii) Applications designed for the hardware devices specified in item (i). +Devices covered by this Appendix shall be specified in the Pricing Appendix or Purchase Document. +2.11. "Distribution License(s)" shall mean a royalty-bearing license required for any kind of sale, trade, exchange, loan, lease, rental or other distribution by or on behalf of Customer to a third party of Redistributables in connection with Devices pursuant to license grant described in Section 5.3 of this Appendix. Distribution Licenses are sold separately for each type of Device respectively and cannot be used for any other type of Devices. +2.12. "Distribution License Packs" shall mean set of prepaid Distribution Licenses for distribution of Redistributables, as defined in The Qt Company's standard price list, quote, Pricing Appendix or in the Purchase Document, as applicable. +2.13. "Evaluation License Term" shall mean a time period specified in the License Certificate for the Customer to use the relevant Licensed Software for evaluation purposes according to Section 5.6 of this Appendix. +2.14. "Intellectual Property Rights" shall mean patents (including utility models), design patents, and designs (whether or not capable of registration), chip topography rights and other like protection, copyrights, trademarks, service marks, trade names, logos or other words or symbols and any other form of statutory protection of any kind and applications for any of the foregoing as well as any trade secrets. +2.15. "License Certificate" shall mean a certificate generated by The Qt Company for each Designated User respectively upon their download of the Licensed Software, which will be available under the respective Designated User's Qt Account at account.qt.io. License Certificates will specify relevant information pertaining to the Licensed Software purchased by Customer and the license to the Licensed Software. +2.16. "License Fee" shall mean the fee charged to Customer for rights granted under this Appendix. +2.17. "Licensed Software" shall mean the specified product(s) of Qt Software which Customer has purchased and which is provided to Customer under the terms of this Appendix (including its Exhibits). Licensed Software shall include corresponding online or electronic documentation, associated media and printed materials, including source code (where applicable), example programs and the documentation. Licensed Software does not include Third Party Software (as defined in Section 6) or Qt Community Edition. The Qt Company may, in the course of its development activities, at its free and absolute discretion and without any obligation to send or publish any notifications to Customer or in general, make changes, additions or deletions in the components and functionalities of the Licensed Software, provided that no such changes, additions or deletions will affect the already released version of the Licensed Software, but only upcoming version(s). +2.18. "License Term" shall mean the agreed validity period of the Development License during which the relevant Licensed Software product can be used pursuant to this Appendix. The agreed License Term, as ordered and paid for by Customer, shall be memorialized in the applicable License Certificate. +2.19. "Customer's Records" shall mean books and records that contain information bearing on Customer's compliance with the Agreement, Customer's use of Qt Community Edition and/or the payments due to The Qt Company under the Agreement, including, but not limited to user information, assembly logs, sales records and distribution records. +2.20. "Modified Software" shall have the meaning as set forth below in Section 4. +2.21. "Qt Software" shall mean the development and design software of The Qt Company, which The Qt Company makes available under commercial and/or open source licenses as either the "Licensed Software" or the "Qt Community Edition". +2.22. "Permitted Software" shall mean third party products that are generally available to the public, which may include parts of Qt Community Edition or be developed using Qt Community Edition. +2.23. "Pre-Release Code" shall have the meaning as set forth in Section 7. +2.24. "Prohibited Combination" shall mean any effort to use, combine, incorporate, link or integrate Licensed Software with any software created with or incorporating Qt Community Edition, or use Licensed Software for creation of any such software. +2.25. "Qt Community Edition" shall mean the open source version of Qt Software available under the terms of the GNU Lesser General Public License, version 2.1 or later ("LGPL") or the GNU General Public License, version 2.0 or later ("GPL"). For clarity, Qt Community Edition shall not be provided, governed or used under this Appendix. +2.26. "Redistributables" shall mean the portions of Licensed Software as set forth in Exhibit 1 hereto that may be distributed pursuant to this Appendix in object code form only, including any relevant documentation. Where relevant, any reference to Licensed Software in this Appendix includes and refers to Redistributables. +2.27. "Renewal Term" shall mean an extension of the previous License Term as agreed between the Parties. +2.28. "Submitted Modified Software" shall have the meaning as set forth in Section 4.2 of this Appendix. +2.29. "Third-Party Software" shall have the meaning set forth in Section 6 of this Appendix. +2.30. "Updates" shall mean a release or version of the Licensed Software containing bug fixes, error corrections and other changes that are generally made available to users of the Licensed Software that have contracted for Support. Updates are generally depicted as a change to the digits following the decimal in the Licensed Software version number. The Qt Company shall make Updates available to Customer under the Support. Updates shall be considered as part of the Licensed Software hereunder. +2.31. "Upgrades" shall mean a release or version of the Licensed Software containing enhancements and new features and are generally depicted as a change to the first digit of the Licensed Software version number. In the event that Upgrades are provided to Customer under this Appendix, they shall be considered as part of the Licensed Software hereunder. + +3. OWNERSHIP +3.1. Ownership of The Qt Company +3.1.1. The Licensed Software is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties. The Licensed Software is licensed, not sold. +3.1.2. All of The Qt Company's Intellectual Property Rights are and shall remain the exclusive property of The Qt Company or its respective licensors . No rights to The Qt Company's Intellectual Property Rights are assigned or granted to Customer under this Appendix, except when and to the extent expressly specified herein. +3.2. Ownership of Customer +3.2.1. All of Customer's Intellectual Property Rights are and shall remain the exclusive property of Customer or its licensors respectively. +3.2.2. Except to the extent set forth in this Appendix, all Intellectual Property Rights to the Modified Software, Applications and Devices (except to Redistributables included therein) shall remain with Customer. + +4. MODIFIED SOFTWARE +4.1. Customer may create bug-fixes, error corrections, patches or modifications to the Licensed Software ("Modified Software"). To the extent that Customer's Modified Software breaks source or binary compatibility or other functionality with the Licensed Software, Customer acknowledges that The Qt Company's ability to provide Support may be prevented or limited and Customer's ability to make use of Updates may be restricted. +4.2. Customer may, at its sole and absolute discretion, choose to submit Modified Software to The Qt Company ("Submitted Modified Software") in connection with Customer's Support request, service request or otherwise. In the event Customer does so, then, Customer hereby grants The Qt Company a sublicensable, assignable, irrevocable, perpetual, worldwide, non-exclusive, royalty-free and fully paid-up license, under all of Customer's Intellectual Property Rights, to reproduce, adapt, translate, modify, and prepare derivative works of, publicly display, publicly perform, sublicense, make available and distribute such Submitted Modified Software as The Qt Company sees fit at its free and absolute discretion. + +5. LICENSES GRANTED +5.1. Development with Licensed Software +5.1.1. Subject to the terms of the Agreement, The Qt Company grants to Customer a worldwide, non-exclusive, non-transferable license, valid for each License Term, to use, modify and copy the Licensed Software by Designated Users on the Development Platforms for the sole purposes of designing, developing, demonstrating and testing Application(s) and/or Devices, and to provide support and other services related to such Applications and Devices to End Customers. Each Application and/or Device can only include, incorporate or integrate contributions by such Designated Users who are duly licensed for the applicable Development Platform(s) and Deployment Platform(s) (i.e have a valid license for the appropriate Licensed Software product and only use one type of Qt Development License per Customer Application and/or Device(s)). +5.1.2. Customer may install copies of the Licensed Software on five (5) computers per Designated User, provided that only Designated Users who have a valid Development License may use the Licensed Software. +5.1.3. Customer may designate another Designated User to replace a then-current Designated User by notifying The Qt Company in writing, where such replacement is due to termination of employment, long-term absence or other permanent reason affecting Designated User's need for Licensed Software. +5.1.4. Upon expiry of the initially agreed License Term, the respective License Term shall be automatically extended by one or more Renewal Term(s), unless and until either Party notifies the other Party in writing, that it does not wish to continue the License Term, such notification to be provided to the other Party no less than thirty (30) days before expiry of the respective License Term. The Qt Company shall, in good time before the due date for the above notification, remind the Customer on the coming Renewal Term. Unless otherwise agreed between the Parties, Renewal Term shall be equal to the length of the previous License Term, but no longer than thirty-six (36) months. +5.1.5. Any such Renewal Term shall be subject to License Fees agreed between the Parties or, if no advance agreement exists, subject to The Qt Company's standard list pricing applicable at the commencement date of any such Renewal Term. +5.2. Distribution of Applications +5.2.1. Subject to the terms of the Agreement, The Qt Company grants to Customer a worldwide, non-exclusive, non-transferable, perpetual, royalty-free and revocable (only for Customer’s material breach of agreement) right and license to: +(i) distribute, by itself or through its Contractors, Redistributables as installed, incorporated or integrated into Applications for execution on the Deployment Platforms; and +(ii) grant perpetual and irrevocable sublicenses to Redistributables, as distributed hereunder, for End Customers solely to the extent necessary in order for the End Customers to use the Applications for their respective intended purposes. +5.2.2. Right to distribute the Redistributables as part of an Application as provided herein is not royalty-bearing but is conditional upon the Application having been created, updated and maintained under a valid and duly paid Development License. +5.3. Distribution of Devices +5.3.1. Subject to the terms of the Agreement, The Qt Company grants to Customer a worldwide, non-exclusive, non-transferable, perpetual, revocable (only for Customer’s material breach of agreement), royalty-bearing right and license to: +(i) distribute, by itself or through one or more tiers of Contractors, Redistributables as installed, incorporated or integrated, or intended to be installed, incorporated or integrated into Devices for execution on the Deployment Platforms; and +(ii) grant perpetual and irrevocable sublicenses to Redistributables, as distributed hereunder, for End Customers solely to the extent necessary in order for the End Customers to use the Devices for their respective intended purposes. +5.3.2. Right to distribute the Devices as provided herein is conditional upon (i) the Devices having been created, updated and maintained under a valid and duly paid Development License, and (ii) Customer having acquired corresponding Distribution Licenses at the time of distribution of any Devices to End Customers. +5.4. Further Requirements +5.4.1. The licenses granted in this Section 5 by The Qt Company to Customer are conditional and subject to Customer's compliance with the following terms: +(i) Customer acknowledges that The Qt Company has separate products for the purpose of Applications and Devices respectively, where development and distribution of Devices is only allowed using the correct designated product. Customer shall ensure and bear the burden of proof that Customer is using a correct product entitling Customer to development and distribution of Devices; +(ii) Customer shall not remove or alter any copyright, trademark or other proprietary rights notice(s) contained in any portion of the Licensed Software; +(iii) Applications must add primary and substantial functionality to Licensed Software so as not to compete with the Licensed Software; +(iv) Applications may not pass on functionality which in any way makes it possible for others to create software with Licensed Software; provided however that Customer may use Licensed Software’s scripting and QML ("Qt Quick") functionality solely in order to enable scripting, themes and styles that augment the functionality and appearance of the Application(s) without adding primary and substantial functionality to the Application(s); +(v) Customer shall not use Licensed Software in any manner or for any purpose that infringes, misappropriates or otherwise violates any Intellectual Property Right or right of any third party, or that violates any applicable law; +(vi) Customer shall not use The Qt Company's or any of its suppliers' names, logos, or trademarks to market Applications, except that Customer may use “Built with Qt” logo to indicate that an Application or Device was developed using Licensed Software; +(vii) Customer shall not distribute, sublicense or disclose source code of Licensed Software to any third party (provided however that Customer may appoint employee(s) of Contractors and Affiliates as Designated Users to use Licensed Software pursuant to this Appendix). +(viii) Customer shall not grant the End Customers a right to: (a) make copies of the Redistributables except when and to the extent required to use the Applications and/or Devices for their intended purpose; (b) modify the Redistributables or create derivative works thereof; (c) decompile, disassemble or otherwise reverse engineer Redistributables; or (d) redistribute any copy or portion of the Redistributables to any third party, except as part of the onward sale of the Application or Device on which the Redistributables are installed; +(ix) Customer shall not, and shall cause that its Affiliates or Contractors shall not, use Licensed Software in any Prohibited Combination, unless Customer has received specific advance written permission from The Qt Company to do so. Absent such written permission, any and all distribution by Customer during the term of the Agreement of a hardware device or product: a) which incorporates or integrates any part of Licensed Software or Qt Community Edition; or b) where substantial functionality is provided by software built with Licensed Software or Qt Community Edition or otherwise depends on Licensed Software or Qt Community Edition, shall be considered to be Device distribution under this Appendix and shall be dependent on Customer’s compliance thereof (including but not limited to the obligation to pay applicable License Fees for such distribution). Notwithstanding the foregoing, Customer is entitled to use and combine Licensed Software with Permitted Software; +(x) Customer shall cause all of its Affiliates, Contractors and End Customer entitled to make use of the licenses granted under this Appendix, to be contractually bound to comply with the relevant terms hereof and not to use the Licensed Software beyond the terms hereof nor for any purposes other than operating within the scope of their services for Customer. Customer shall be responsible for any and all actions and omissions of its Affiliates, Contractors, and End Customers relating to the Licensed Software and use thereof (including but not limited to payment of all applicable License Fees); +(xi) Except when and to the extent explicitly provided in this Section 5, Customer shall not transfer, publish, disclose, display or otherwise make available the Licensed Software; and +(xii) Customer shall not attempt or enlist a third party to conduct or attempt to conduct any of the above. +5.4.2. The above terms shall not be applicable if and solely to the extent they conflict with any mandatory provisions of applicable laws. +5.4.3. Any use of Licensed Software beyond the provisions of this Appendix is strictly prohibited and requires, at a minimum an additional license from The Qt Company (e.g. certain additional rights granted under software development kit “SDK” agreement with regard to limitations of Section 5.4.1 iv, vii or viii). +5.5. Evaluation License +5.5.1. Subject to the terms of this Appendix, The Qt Company grants to Customer a worldwide, non-exclusive, non-transferable license, valid for the Evaluation License Term to use the relevant Licensed Software product solely for Customer’s internal use to evaluate and determine whether the Licensed Software meets Customer's business requirements, specifically excluding any commercial use of the Licensed Software or any derived work thereof. +5.5.2. Upon the expiry of the Evaluation License Term, Customer must either discontinue use of the relevant Licensed Software or acquire a commercial Development License specified herein. + +6. THIRD-PARTY SOFTWARE. The Licensed Software may provide links or access to third party libraries or code (collectively "Third-Party Software") to implement various functions. Third-Party Software does not, however, comprise part of the Licensed Software, but is provided to Customer complimentary and use thereof is discretionary for Customer. Third-Party Software will be listed in the ".../src/3rdparty" source tree delivered with the Licensed Software or documented in the Licensed Software, as such may be amended from time to time. Customer acknowledges that use or distribution of Third-Party Software is in all respects subject to applicable license terms of applicable third-party right holders. + +7. PRE-RELEASE CODE +7.1. The Licensed Software may contain pre-release code and functionality, or sample code marked or otherwise stated with appropriate designation such as "Technology Preview", "Alpha", "Beta", "Experimental", "Sample", "Example" etc. ("Pre-Release Code"). +7.2. Such Pre-Release Code may be provided complimentary for Customer, in order to provide experimental support or information for new platforms or preliminary versions of one or more new functionalities, or for other similar reasons. Pre-Release Code may not be at the level of performance and compatibility of a final, generally available, product offering. Pre-Release Code may not operate correctly, may contain errors and may be substantially modified by The Qt Company prior to a commercial product release, if any. The Qt Company is under no obligation to make Pre-Release Code commercially available, or provide any Support or Updates relating thereto. To the maximum extent permitted by law, the Qt Company assumes no liability whatsoever regarding any Pre-Release Code and any use thereof is exclusively at Customer's own risk and expense. +7.3. Unless Licensed Software specifies different license terms for the respective Pre-Release Code, Customer is entitled to use such pre-release code pursuant to Section 5 of this Appendix, just like other Licensed Software. + +8. SUPPORT. Support is provided according to agreed support level and subject to applicable requirements and restrictions, as specified in the Appendix for Support Terms. + +9. FEES AND ORDERING: DISTRIBUTION LICENSES +9.1. Distribution License Packs +9.1.1. Unless otherwise agreed in writing, Distribution Licenses shall be purchased by way of Distribution License Packs. +9.1.2. Upon due payment of the ordered Distribution License Pack(s), Customer will have an account of Distribution Licenses available for distributing the Redistributables in accordance with this Agreement. +9.2. Each time Customer distributes a copy of Redistributables, one Distribution License is used and Customer's account of available Distribution Licenses is decreased accordingly. +9.3. Customer may distribute copies of the Redistributables so long as Customer has Distribution Licenses remaining on its account. + +10. RECORD-KEEPING AND REPORTING OBLIGATIONS; AUDIT RIGHTS +10.1. Customer's Record-keeping +10.1.1. Customer shall at all times during the term of the Agreement or validity of any of the licenses hereunder, whichever is later, and for a period of two (2) years thereafter, maintain Customer's Records in an accurate and up-to-date form. Customer's Records shall be adequate to reasonably enable The Qt Company to determine Customer's compliance with the provisions of the Agreement. The records shall conform to general good accounting practices. +10.1.2. Customer shall, within thirty (30) days from receiving The Qt Company's request to that effect, deliver to The Qt Company a report based on Customer's Records, such report to contain information, in sufficient detail, on: (i) number and identity of users working with Licensed Software or Qt Community Edition, (ii) copies of Redistributables distributed by Customer during the most recent calendar quarter and/or any other term specified by The Qt Company, and (iii) any other information pertaining to Customer's compliance with the terms of the Agreement (e.g. information on products and/or projects relating to use of Distribution Licenses), as The Qt Company may reasonably require from time to time. +10.2. The Qt Company's Audit Rights +10.2.1. The Qt Company or an independent auditor acting on behalf of The Qt Company may, upon at least thirty (30) days' prior written notice and at The Qt Company expense, audit Customer with respect to Customer's use of the Licensed Software, but not more frequently than once during each six (6) month period. Such audit may be conducted by mail, electronic means or through an in-person visit to Customer's place of business. Any possible in-person audit shall be conducted during regular business hours at Customer's facilities, shall not unreasonably interfere with Customer's business activities and shall be limited in scope to verify Customer's compliance with the terms of the Agreement. The Qt Company or its independent auditor shall be entitled to inspect Customer's Records and conduct necessary interviews of Customer's relevant employees and Contractors. All Customer's Records and use thereof shall be subject to the obligation of confidentiality under the Agreement. +10.2.2. If an audit reveals that Customer is using the Licensed Software beyond scope of the licenses Customer has paid for, Customer shall pay to The Qt Company any amounts owed for such unauthorized use within thirty (30) days from receipt of the corresponding invoice from The Qt Company. +10.2.3. In addition, in the event the audit reveals a material violation of the terms of the Agreement (without limitation, either (i) underpayment of more than 10% of License Fees or 10,000 euros (whichever is more) or (ii) distribution of products, which include or result from Prohibited Combination, shall be deemed a material violation for purposes of this section), then Customer shall pay The Qt Company's reasonable cost of conducting such audit. + +11. TERMINATION +11.1. Termination of Licenses +11.1.1. The Qt Company may terminate Customer's rights to any and all Licensed Software (including access to Support), if Customer: +(i) commits a material breach of the Agreement (including this Appendix) and has not remedied the breach within a reasonable period of time (which shall be no less than 30 days) of The Qt Company's written notice specifying the breach, or +(ii) becomes bankrupt, insolvent or goes into liquidation or debt restructuring. +11.2. Suspension of rights: Instead of termination, The Qt Company reserves the right to suspend or withhold grants of any and all rights to the Licensed Software (including Support), should Customer fail to make payment in timely fashion or otherwise violate or is reasonably suspected of violating its obligations under the Agreement and/or this Appendix, and where such violation or breach is not cured within ten (10) business days following The Qt Company's written notice thereof. +11.3. Parties Rights and Duties upon Termination +11.3.1. Upon expiry or termination of the Development Licenses, Customer shall cease and shall cause all Designated Users (including those of its Affiliates' and Contractors') to cease using the relevant Licensed Software. +11.3.2. Upon such expiry or termination of Development Licenses, Customer shall destroy or return to The Qt Company all copies of the respective Licensed Software and all related materials and will certify the same by Customer's duly authorized officer to The Qt Company upon its request, provided however that Customer may retain and utilize such copies of the Licensed Software to the extent required to provide Customer's continued support to End Customers, for archiving purposes or as is required under applicable law. +11.3.3. Distribution Licenses are perpetual and, therefore, Customer's distribution rights hereunder shall only terminate upon The Qt Company's termination of Distribution Licenses due to Customer's material breach as set forth in Section 11.1.1(i) of this Appendix. In case of such termination by The Qt Company due to Customer's material breach, Customer must cease any distribution of Applications and Devices at the effective date of termination. +11.3.4. Expiry or termination of any of Customer's licenses hereunder for any reason whatsoever shall not: +(i) relieve Customer of its obligation to pay any License Fees accrued or payable to The Qt Company prior to the effective date of termination, and Customer pay to The Qt Company all such fees within 30 days from the effective date of termination of the licenses; +(ii) relieve Customer of its obligation to ensure that Applications and Devices (including those already distributed) remain in compliance with the terms of the Agreement; nor +(iii) affect any rights of End Customer to continue use of Applications and Devices (and therein incorporated Redistributables). +11.4. Extension of Rights under Special Circumstances. In the event that, during the applicable License Term, The Qt Company is declared bankrupt under a final, non-cancellable decision by relevant court of law, and the Agreement is not, at the date of expiry of the Development License(s), assigned to a party who has assumed The Qt Company's position as a legitimate licensor of Licensed Software under the Agreement, then all valid Development Licenses possessed by Customer at such date of expiry, and which Customer has not notified for expiry, shall be extended to be valid in perpetuity under the terms of the Agreement. Any such extension shall not apply to The Qt Company's Support obligations. + +EXHIBIT 1, Licensed Software +At the time of conclusion of this Appendix, the latest available version of Licensed Software includes the software libraries and tools set forth in Exhibit 1 (as provided below), depending on which product(s) Customer has purchased under the relevant Purchase Document. +The modules and tools are specific to each product version respectively and may vary from version to version. Modules and tools included in the latest publicly available version of the respective product at any given time are listed in Exhibit 1 of https://www.qt.io/terms-conditions/qt-dev-framework/exhibit-1. If a new version of Licensed Software does not include a module or tool present in an older version which Customer is entitled to use under a valid license from The Qt Company, then Customer will continue to have such right during the validity of Customer's license to relevant Licensed Software. In the event a new version of the Licensed Software adds modules or tools to any previous version(s), Customer's rights will extend to cover also such additional modules and tools. + +EXHIBIT 2 - Small Business Terms +1. This Exhibit applies to entities that qualify as a Qualified Small Business (defined below) and provides additional terms and conditions applicable to small business pricing and licensing. In the event that Customer is a Qualified Small Business and there is any conflict between the terms of this Exhibit and any other terms of the Agreement, the terms in this Exhibit shall take precedence. + +2. APPLICABILITY FOR SMALL BUSINESS LICENSES. Any small business discounts applied require that Customer (including any Customer Affiliates or group entities) has an annual revenue (including annual capital funding) below 1 Million EUR, or the equivalent thereof, as approved by The Qt Company (each, a "Qualified Small Business"). The annual revenue, including funding, must be evidenced upon request by business records and approved by The Qt Company in its reasonable discretion. + +3. SUPPORT. Support is limited to: (i) Install Support; and (ii) for any other Standard Support issue, five (5) support tickets annually. + +4. LIMITATION ON NUMBER OF SMALL BUSINESS DEVELOPER LICENSES. Qualified Small Business discounts and purchasing structure may be applied to a maximum of three discounted developer licenses (either ADE or DCP) per Qualified Small Business. Any additional licenses purchased will be at The Qt Company list price in effect at the time. + +5. LIMITATION FOR NUMBER OF INSTALLATIONS. Customer may install copies of the Licensed Software on two (2) computers per Designated User, provided that only the Designated Users who have a valid Development License may use the Licensed Software. + +6. CONDITIONAL WAIVER OF DISTRIBUTION LICENSES. For Qualified Small Businesses, the Agreement requirements to purchase Distribution Licenses for Devices shall apply only when Customer ceases to be a Qualified Small Business (e.g., when annual revenue threshholds are bypassed). + +7. ADDITIONAL TERMS FOR RENEWALS. The initial subscription purchase term for Qualified Small Business Licenses is twelve (12) months. Upon expiration of the initial twelve (12) month term and unless terminated in accordance with the Agreement, the Licenses will automatically renew for additional twelve (12) month terms with applicable Qualified Small Business discounts. If Customer ceases to be a Qualified Small Business, renewal pricing shall be at The Qt Company list price in effect at the time of renewal, or as agreed in writing between the parties. + +8. ADDITIONAL AUDIT RIGHTS. In addition to the audit rights set forth in the Agreement, The Qt Company reserves the right to audit Customer financial records in order to determine whether Customer is a Qualified Small Business. diff --git a/.cmake.conf b/.cmake.conf index 26d1873fe..a25c30e8f 100644 --- a/.cmake.conf +++ b/.cmake.conf @@ -1,4 +1,4 @@ -set(QT_REPO_MODULE_VERSION "6.6.1") +set(QT_REPO_MODULE_VERSION "6.6.2") set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1") set(QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_LEAN_HEADERS=1") diff --git a/.tag b/.tag index 0651059ea..9239f8267 100644 --- a/.tag +++ b/.tag @@ -1 +1 @@ -a4d7c879a21db0bd1aff6e9a6970600bb2ea6c60 +1d65066ac1a3a4a6d2ba6af36f4aa60c059a11bf diff --git a/debian/changelog b/debian/changelog index 5efd5d0c9..9ad77951e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,35 +1,38 @@ -qt6-declarative (6.6.1+dfsg-1deepin4) unstable; urgency=medium +qt6-declarative (6.6.2+dfsg-2) experimental; urgency=medium - * Import patch from upstream: - - TextField-Only-enable-paste-action-if-clipboard-has-text.patch - https://codereview.qt-project.org/c/qt/qtdeclarative/+/535176 - - -- Tianyu Chen Fri, 01 Mar 2024 10:16:35 +0800 + [ Patrick Franz ] + * Re-introduce package libqt6qmlworkerscript6. -qt6-declarative (6.6.1+dfsg-1deepin3) unstable; urgency=medium + -- Patrick Franz Tue, 12 Mar 2024 19:15:55 +0100 - * Import patch from upstream: - - Fix-corrupt-rendering-when-toggling-rendernode-based-items.patch - https://codereview.qt-project.org/c/qt/qtdeclarative/+/521190 +qt6-declarative (6.6.2+dfsg-1) experimental; urgency=medium - -- Tianyu Chen Wed, 17 Jan 2024 10:44:07 +0800 + [ Patrick Franz ] + * New upstream release (6.6.2). + * Bump Qt B-Ds to 6.6.2. + * Build-depend on pkgconf instead of pkg-config as the latter has been + superseded by the former. + * Update ABI to 6.6.2. -qt6-declarative (6.6.1+dfsg-1deepin2) unstable; urgency=medium + -- Patrick Franz Thu, 15 Feb 2024 20:55:06 +0100 - * Import three patches: - - Add-the-reset-function-for-properties-of-QQuickPalet.patch. - - Rename-accent-color-in-QPalette.patch - - Palette-Remove-redundant-code.patch - https://codereview.qt-project.org/c/qt/qtdeclarative/+/414503 +qt6-declarative (6.6.1+dfsg-3) experimental; urgency=medium + [ Lisandro Damián Nicanor Pérez Meyer ] + * qt6-declarative-dev: add versioned depends on packages produced by this + source. This avoids mixed installed versions as reported by Stuart + Prescott on IRC. - -- Tianyu Chen Wed, 10 Jan 2024 14:30:45 +0800 + -- Patrick Franz Sun, 14 Jan 2024 18:00:35 +0100 -qt6-declarative (6.6.1+dfsg-1deepin1) unstable; urgency=medium +qt6-declarative (6.6.1+dfsg-2) experimental; urgency=medium - * Drop patch introduced by git-rebase. + [ Patrick Franz ] + * Re-introduce package libqt6quickshapes6. + * Update symbols from buildlogs. + * Fix typos in documentation. - -- Tianyu Chen Wed, 27 Dec 2023 10:25:26 +0800 + -- Patrick Franz Tue, 09 Jan 2024 00:01:55 +0100 qt6-declarative (6.6.1+dfsg-1) experimental; urgency=medium diff --git a/debian/control b/debian/control index fc0d6facd..b0a8e041d 100644 --- a/debian/control +++ b/debian/control @@ -11,14 +11,14 @@ Build-Depends: cmake (>= 3.24~), libssl-dev, libvulkan-dev [linux-any], ninja-build, - pkg-config, + pkgconf, pkg-kde-tools, - qt6-base-dev (>= 6.6.1+dfsg~), - qt6-base-private-dev (>= 6.6.1+dfsg~), + qt6-base-dev (>= 6.6.2+dfsg~), + qt6-base-private-dev (>= 6.6.2+dfsg~), qt6-declarative-dev:native , - qt6-languageserver-private-dev (>= 6.6.1~), - qt6-shadertools-dev (>= 6.6.1~), - qt6-svg-dev (>= 6.6.1~), + qt6-languageserver-private-dev (>= 6.6.2~), + qt6-shadertools-dev (>= 6.6.2~), + qt6-svg-dev (>= 6.6.2~), Build-Depends-Indep: qt6-base-dev (>= 6.6~) , qt6-documentation-tools (>= 6.6~) , Standards-Version: 4.6.2 @@ -31,7 +31,7 @@ Package: libqt6qml6 Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends}, -Provides: qt6-declarative-private-abi (= 6.6.1), +Provides: qt6-declarative-private-abi (= 6.6.2), Depends: ${misc:Depends}, ${shlibs:Depends}, Recommends: libgl1, libglx-mesa0, Suggests: qt6-qmltooling-plugins, @@ -65,6 +65,16 @@ Description: Qt 6 QML Models library . This package contains the Qt QML Models support library. +Package: libqt6qmlworkerscript6 +Architecture: any +Multi-Arch: same +Depends: ${misc:Depends}, ${shlibs:Depends}, +Description: Qt 6 QML WorkerScript library + Qt is a cross-platform C++ application framework. Qt's primary feature + is its rich set of widgets that provide standard GUI functionality. + . + This package contains the Qt QML WorkerScript support library. + Package: libqt6quick6 Architecture: any Multi-Arch: same @@ -90,6 +100,17 @@ Description: Qt 6 Quick Controls 2 library . This package contains the Qt Quick Controls 2 support library. +Package: libqt6quickshapes6 +Architecture: any +Multi-Arch: same +Pre-Depends: ${misc:Pre-Depends}, +Depends: ${misc:Depends}, ${shlibs:Depends}, +Description: Qt 6 Quick Shapes library + Qt is a cross-platform C++ application framework. Qt's primary feature + is its rich set of widgets that provide standard GUI functionality. + . + This package contains the Qt Quick Shapes support library. + Package: libqt6quicktemplates2-6 Architecture: any Multi-Arch: same @@ -298,8 +319,6 @@ Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends}, Depends: ${misc:Depends}, ${shlibs:Depends}, -Breaks: libqt6qmlworkerscript6 -Replaces: libqt6qmlworkerscript6 Description: Qt 6 QtQml Workerscript QML module Qt is a cross-platform C++ application framework. Qt's primary feature is its rich set of widgets that provide standard GUI functionality. @@ -425,8 +444,6 @@ Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends}, Depends: ${misc:Depends}, ${shlibs:Depends}, -Breaks: libqt6quickshapes6 -Replaces: libqt6quickshapes6 Description: Qt 6 Quick Shapes QML module Qt is a cross-platform C++ application framework. Qt's primary feature is its rich set of widgets that provide standard GUI functionality. @@ -486,15 +503,17 @@ Multi-Arch: same Depends: libqt6qml6 (= ${binary:Version}), libqt6qmlcompiler6 (= ${binary:Version}), libqt6qmlmodels6 (= ${binary:Version}), + libqt6qmlworkerscript6 (= ${binary:Version}), libqt6quick6 (= ${binary:Version}), libqt6quickcontrols2-6 (= ${binary:Version}), + libqt6quickshapes6 (= ${binary:Version}), libqt6quicktemplates2-6 (= ${binary:Version}), libqt6quicktest6 (= ${binary:Version}), libqt6quickwidgets6 (= ${binary:Version}), qt6-base-dev, - qt6-declarative-dev-tools, - qt6-qmllint-plugins, - qt6-qmltooling-plugins, + qt6-declarative-dev-tools (= ${binary:Version}), + qt6-qmllint-plugins (= ${binary:Version}), + qt6-qmltooling-plugins (= ${binary:Version}), ${misc:Depends}, Description: Qt 6 declarative development files Qt is a cross-platform C++ application framework. Qt's primary feature diff --git a/debian/libqt6qml6.symbols b/debian/libqt6qml6.symbols index 8b0fba7a6..af123d834 100644 --- a/debian/libqt6qml6.symbols +++ b/debian/libqt6qml6.symbols @@ -1,6 +1,6 @@ # SymbolsHelper-Confirmed: 6.6.1 amd64 libQt6Qml.so.6 libqt6qml6 #MINVER# -| libqt6qml6 #MINVER#, qt6-declarative-private-abi (= 6.6.1) +| libqt6qml6 #MINVER#, qt6-declarative-private-abi (= 6.6.2) * Build-Depends-Packages: qt6-declarative-dev, qt6-declarative-private-dev Qt_6@Qt_6 6.6.0 (symver)Qt_6_PRIVATE_API 0 diff --git a/debian/libqt6qmlcompiler6.symbols b/debian/libqt6qmlcompiler6.symbols index 8959d3155..cab608989 100644 --- a/debian/libqt6qmlcompiler6.symbols +++ b/debian/libqt6qmlcompiler6.symbols @@ -1,6 +1,6 @@ # SymbolsHelper-Confirmed: 6.6.0 amd64 armel armhf hppa i386 powerpc riscv64 libQt6QmlCompiler.so.6 libqt6qmlcompiler6 #MINVER# -| libqt6qmlcompiler6 #MINVER#, qt6-declarative-private-abi (= 6.6.1) +| libqt6qmlcompiler6 #MINVER#, qt6-declarative-private-abi (= 6.6.2) * Build-Depends-Packages: qt6-declarative-dev, qt6-declarative-private-dev Qt_6@Qt_6 6.6.0 (symver)Qt_6_PRIVATE_API 0 diff --git a/debian/libqt6qmlmodels6.symbols b/debian/libqt6qmlmodels6.symbols index 2d9216ba0..57ce4a42a 100644 --- a/debian/libqt6qmlmodels6.symbols +++ b/debian/libqt6qmlmodels6.symbols @@ -1,6 +1,6 @@ # SymbolsHelper-Confirmed: 6.6.0 amd64 libQt6QmlModels.so.6 libqt6qmlmodels6 #MINVER# -| libqt6qmlmodels6 #MINVER#, qt6-declarative-private-abi (= 6.6.1) +| libqt6qmlmodels6 #MINVER#, qt6-declarative-private-abi (= 6.6.2) * Build-Depends-Packages: qt6-declarative-dev, qt6-declarative-private-dev Qt_6@Qt_6 6.6.0 (symver)Qt_6_PRIVATE_API 0 diff --git a/debian/libqt6qmlworkerscript6.install b/debian/libqt6qmlworkerscript6.install new file mode 100644 index 000000000..a2294a32e --- /dev/null +++ b/debian/libqt6qmlworkerscript6.install @@ -0,0 +1 @@ +usr/lib/${DEB_HOST_MULTIARCH}/libQt6QmlWorkerScript.so.* diff --git a/debian/libqt6qmlworkerscript6.lintian-overrides b/debian/libqt6qmlworkerscript6.lintian-overrides new file mode 100644 index 000000000..b8838310f --- /dev/null +++ b/debian/libqt6qmlworkerscript6.lintian-overrides @@ -0,0 +1,3 @@ +# This dependency has been added to track external packages building against +# our private headers. It is ok if internal packages depend on the ABI one. +libqt6qmlworkerscript6: symbols-declares-dependency-on-other-package qt6-declarative-private-abi * diff --git a/debian/libqt6qmlworkerscript6.symbols b/debian/libqt6qmlworkerscript6.symbols new file mode 100644 index 000000000..f02cc5a77 --- /dev/null +++ b/debian/libqt6qmlworkerscript6.symbols @@ -0,0 +1,9 @@ +# SymbolsHelper-Confirmed: 6.6.2 amd64 +libQt6QmlWorkerScript.so.6 libqt6qmlworkerscript6 #MINVER# +| libqt6qmlworkerscript6 #MINVER#, qt6-declarative-private-abi (= 6.6.2) +* Build-Depends-Packages: qt6-declarative-dev, qt6-declarative-private-dev + Qt_6@Qt_6 6.6.2 + (symver)Qt_6_PRIVATE_API 0 + _Z37qml_register_types_QtQml_WorkerScriptv@Qt_6 6.6.2 + _ZTIN3QV415ExecutionEngine9DeletableE@Qt_6 6.6.2 + _ZTSN3QV415ExecutionEngine9DeletableE@Qt_6 6.6.2 diff --git a/debian/libqt6quick6.symbols b/debian/libqt6quick6.symbols index 9c15ab9cf..55704a3f9 100644 --- a/debian/libqt6quick6.symbols +++ b/debian/libqt6quick6.symbols @@ -1,6 +1,6 @@ -# SymbolsHelper-Confirmed: 6.6.0 amd64 arm64 armel armhf hppa i386 loong64 powerpc ppc64 ppc64el riscv64 s390x +# SymbolsHelper-Confirmed: 6.6.1 mips64el libQt6Quick.so.6 libqt6quick6 #MINVER# -| libqt6quick6 #MINVER#, qt6-declarative-private-abi (= 6.6.1) +| libqt6quick6 #MINVER#, qt6-declarative-private-abi (= 6.6.2) * Build-Depends-Packages: qt6-declarative-dev, qt6-declarative-private-dev Qt_6@Qt_6 6.6.0 (symver)Qt_6_PRIVATE_API 0 @@ -398,8 +398,7 @@ libQt6Quick.so.6 libqt6quick6 #MINVER# _ZN16QNativeInterface16QSGOpenGLTextureD0Ev@Qt_6 6.6.0 _ZN16QNativeInterface16QSGOpenGLTextureD1Ev@Qt_6 6.6.0 _ZN16QNativeInterface16QSGOpenGLTextureD2Ev@Qt_6 6.6.0 - (arch=amd64 arm64 loong64 ppc64 ppc64el riscv64 s390x)_ZN16QNativeInterface16QSGVulkanTexture10fromNativeEP9VkImage_T13VkImageLayoutP12QQuickWindowRK5QSize6QFlagsINS4_19CreateTextureOptionEE@Qt_6 6.6.0 - (arch=!amd64 !arm64 !loong64 !ppc64 !ppc64el !riscv64 !s390x)_ZN16QNativeInterface16QSGVulkanTexture10fromNativeEy13VkImageLayoutP12QQuickWindowRK5QSize6QFlagsINS2_19CreateTextureOptionEE@Qt_6 6.6.0 + (arch=amd64 arm64 loong64 mips64el ppc64 ppc64el riscv64 s390x)_ZN16QNativeInterface16QSGVulkanTexture10fromNativeEP9VkImage_T13VkImageLayoutP12QQuickWindowRK5QSize6QFlagsINS4_19CreateTextureOptionEE@Qt_6 6.6.1 _ZN16QNativeInterface16QSGVulkanTextureD0Ev@Qt_6 6.6.0 _ZN16QNativeInterface16QSGVulkanTextureD1Ev@Qt_6 6.6.0 _ZN16QNativeInterface16QSGVulkanTextureD2Ev@Qt_6 6.6.0 @@ -525,10 +524,8 @@ libQt6Quick.so.6 libqt6quick6 #MINVER# _ZN17QSGSimpleRectNodeC2ERK6QRectFRK6QColor@Qt_6 6.6.0 _ZN17QSGSimpleRectNodeC2Ev@Qt_6 6.6.0 _ZN18QQuickRenderTarget15fromPaintDeviceEP12QPaintDevice@Qt_6 6.6.0 - (arch=amd64 arm64 loong64 ppc64 ppc64el riscv64 s390x)_ZN18QQuickRenderTarget15fromVulkanImageEP9VkImage_T13VkImageLayout8VkFormatRK5QSizei@Qt_6 6.6.0 - (arch=amd64 arm64 loong64 ppc64 ppc64el riscv64 s390x)_ZN18QQuickRenderTarget15fromVulkanImageEP9VkImage_T13VkImageLayoutRK5QSizei@Qt_6 6.6.0 - (arch=!amd64 !arm64 !loong64 !ppc64 !ppc64el !riscv64 !s390x)_ZN18QQuickRenderTarget15fromVulkanImageEy13VkImageLayout8VkFormatRK5QSizei@Qt_6 6.6.0 - (arch=!amd64 !arm64 !loong64 !ppc64 !ppc64el !riscv64 !s390x)_ZN18QQuickRenderTarget15fromVulkanImageEy13VkImageLayoutRK5QSizei@Qt_6 6.6.0 + (arch=amd64 arm64 loong64 mips64el ppc64 ppc64el riscv64 s390x)_ZN18QQuickRenderTarget15fromVulkanImageEP9VkImage_T13VkImageLayout8VkFormatRK5QSizei@Qt_6 6.6.1 + (arch=amd64 arm64 loong64 mips64el ppc64 ppc64el riscv64 s390x)_ZN18QQuickRenderTarget15fromVulkanImageEP9VkImage_T13VkImageLayoutRK5QSizei@Qt_6 6.6.1 _ZN18QQuickRenderTarget17fromOpenGLTextureEjRK5QSizei@Qt_6 6.6.0 _ZN18QQuickRenderTarget17fromOpenGLTextureEjjRK5QSizei@Qt_6 6.6.0 _ZN18QQuickRenderTarget19fromRhiRenderTargetEP16QRhiRenderTarget@Qt_6 6.6.0 diff --git a/debian/libqt6quickcontrols2-6.symbols b/debian/libqt6quickcontrols2-6.symbols index 66f696e8d..baf7806f8 100644 --- a/debian/libqt6quickcontrols2-6.symbols +++ b/debian/libqt6quickcontrols2-6.symbols @@ -1,6 +1,6 @@ # SymbolsHelper-Confirmed: 6.6.0 amd64 libQt6QuickControls2.so.6 libqt6quickcontrols2-6 #MINVER# -| libqt6quickcontrols2-6 #MINVER#, qt6-declarative-private-abi (= 6.6.1) +| libqt6quickcontrols2-6 #MINVER#, qt6-declarative-private-abi (= 6.6.2) * Build-Depends-Packages: qt6-declarative-dev, qt6-declarative-private-dev Qt_6@Qt_6 6.6.0 (symver)Qt_6_PRIVATE_API 0 diff --git a/debian/libqt6quickshapes6.install b/debian/libqt6quickshapes6.install new file mode 100644 index 000000000..93e5076a6 --- /dev/null +++ b/debian/libqt6quickshapes6.install @@ -0,0 +1 @@ +usr/lib/${DEB_HOST_MULTIARCH}/libQt6QuickShapes.so.* diff --git a/debian/libqt6quickshapes6.lintian-overrides b/debian/libqt6quickshapes6.lintian-overrides new file mode 100644 index 000000000..542fa7e7e --- /dev/null +++ b/debian/libqt6quickshapes6.lintian-overrides @@ -0,0 +1,3 @@ +# This dependency has been added to track external packages building against +# our private headers. It is ok if internal packages depend on the ABI one. +libqt6quickshapes6: symbols-declares-dependency-on-other-package qt6-declarative-private-abi * diff --git a/debian/libqt6quickshapes6.symbols b/debian/libqt6quickshapes6.symbols new file mode 100644 index 000000000..d75bd60ca --- /dev/null +++ b/debian/libqt6quickshapes6.symbols @@ -0,0 +1,19 @@ +# SymbolsHelper-Confirmed: 6.6.0 amd64 +libQt6QuickShapes.so.6 libqt6quickshapes6 #MINVER# +| libqt6quickshapes6 #MINVER#, qt6-declarative-private-abi (= 6.6.2) +* Build-Depends-Packages: qt6-declarative-dev, qt6-declarative-private-dev + Qt_6@Qt_6 6.6.0 + (symver)Qt_6_PRIVATE_API 0 + _Z29QQuickShapes_initializeModulev@Qt_6 6.6.0 + _Z33qml_register_types_QtQuick_Shapesv@Qt_6 6.6.0 + _ZGVZN9QMetaType21registerConverterImplI5QListIdE9QIterableI13QMetaSequenceEEEbSt8functionIFbPKvPvEES_S_E10unregister@Qt_6 6.6.0 + _ZGVZN9QMetaType23registerMutableViewImplI5QListIdE9QIterableI13QMetaSequenceEEEbSt8functionIFbPvS7_EES_S_E10unregister@Qt_6 6.6.0 + _ZN13QMetaSequence12MetaSequenceI5QListIdEE5valueE@Qt_6 6.6.0 + _ZTI17QQuickPathPrivate@Qt_6 6.6.0 + _ZTIZN9QMetaType17registerConverterI5QListIdE9QIterableI13QMetaSequenceEN9QtPrivate33QSequentialIterableConvertFunctorIS2_EEEEbT1_EUlPKvPvE_@Qt_6 6.6.0 + _ZTIZN9QMetaType19registerMutableViewI5QListIdE9QIterableI13QMetaSequenceEN9QtPrivate37QSequentialIterableMutableViewFunctorIS2_EEEEbT1_EUlPvSA_E_@Qt_6 6.6.0 + _ZTS17QQuickPathPrivate@Qt_6 6.6.0 + _ZTSZN9QMetaType17registerConverterI5QListIdE9QIterableI13QMetaSequenceEN9QtPrivate33QSequentialIterableConvertFunctorIS2_EEEEbT1_EUlPKvPvE_@Qt_6 6.6.0 + _ZTSZN9QMetaType19registerMutableViewI5QListIdE9QIterableI13QMetaSequenceEN9QtPrivate37QSequentialIterableMutableViewFunctorIS2_EEEEbT1_EUlPvSA_E_@Qt_6 6.6.0 + (optional=templinst)_ZZN9QMetaType21registerConverterImplI5QListIdE9QIterableI13QMetaSequenceEEEbSt8functionIFbPKvPvEES_S_E10unregister@Qt_6 6.6.0 + (optional=templinst)_ZZN9QMetaType23registerMutableViewImplI5QListIdE9QIterableI13QMetaSequenceEEEbSt8functionIFbPvS7_EES_S_E10unregister@Qt_6 6.6.0 diff --git a/debian/libqt6quicktemplates2-6.symbols b/debian/libqt6quicktemplates2-6.symbols index c8ea61c83..8fab2d132 100644 --- a/debian/libqt6quicktemplates2-6.symbols +++ b/debian/libqt6quicktemplates2-6.symbols @@ -1,6 +1,6 @@ # SymbolsHelper-Confirmed: 6.6.0 amd64 libQt6QuickTemplates2.so.6 libqt6quicktemplates2-6 #MINVER# -| libqt6quicktemplates2-6 #MINVER#, qt6-declarative-private-abi (= 6.6.1) +| libqt6quicktemplates2-6 #MINVER#, qt6-declarative-private-abi (= 6.6.2) * Build-Depends-Packages: qt6-declarative-dev, qt6-declarative-private-dev Qt_6@Qt_6 6.6.0 (symver)Qt_6_PRIVATE_API 0 diff --git a/debian/libqt6quicktest6.symbols b/debian/libqt6quicktest6.symbols index 9ce44ee7d..fd9dd094c 100644 --- a/debian/libqt6quicktest6.symbols +++ b/debian/libqt6quicktest6.symbols @@ -1,6 +1,6 @@ # SymbolsHelper-Confirmed: 6.6.0 amd64 libQt6QuickTest.so.6 libqt6quicktest6 #MINVER# -| libqt6quicktest6 #MINVER#, qt6-declarative-private-abi (= 6.6.1) +| libqt6quicktest6 #MINVER#, qt6-declarative-private-abi (= 6.6.2) * Build-Depends-Packages: qt6-declarative-dev, qt6-declarative-private-dev Qt_6@Qt_6 6.6.0 (symver)Qt_6_PRIVATE_API 0 diff --git a/debian/libqt6quickwidgets6.symbols b/debian/libqt6quickwidgets6.symbols index 0e2e9b7a1..15bf70d23 100644 --- a/debian/libqt6quickwidgets6.symbols +++ b/debian/libqt6quickwidgets6.symbols @@ -1,6 +1,6 @@ # SymbolsHelper-Confirmed: 6.6.0 amd64 libQt6QuickWidgets.so.6 libqt6quickwidgets6 #MINVER# -| libqt6quickwidgets6 #MINVER#, qt6-declarative-private-abi (= 6.6.1) +| libqt6quickwidgets6 #MINVER#, qt6-declarative-private-abi (= 6.6.2) * Build-Depends-Packages: qt6-declarative-dev, qt6-declarative-private-dev Qt_6@Qt_6 6.6.0 (symver)Qt_6_PRIVATE_API 0 diff --git a/debian/patches/deepin-0001-Add-the-reset-function-for-properties-of-QQuickPalet.patch b/debian/patches/deepin-0001-Add-the-reset-function-for-properties-of-QQuickPalet.patch deleted file mode 100644 index 1a312ca41..000000000 --- a/debian/patches/deepin-0001-Add-the-reset-function-for-properties-of-QQuickPalet.patch +++ /dev/null @@ -1,351 +0,0 @@ -From 4e7a83156d47683f777e92d2790cb617f0bb09d5 Mon Sep 17 00:00:00 2001 -From: JiDe Zhang -Date: Sun, 5 Jun 2022 13:53:14 +0800 -Subject: [PATCH] Add the reset function for properties of QQuickPalette - -Allow reset the group colors of QQuickPalette, and ensure ResolveMask -value of QPalette is right. - -Pick-to: 6.5 6.6 -Fixes: QTBUG-104008 -Change-Id: I57d71f6be73286b78bf0c31927993e39f9fab8d3 -Reviewed-by: Axel Spoerl ---- - src/quick/items/qquickpalette.cpp | 18 +++++ - src/quick/items/qquickpalette_p.h | 11 ++-- - src/quick/items/qquickpalettecolorprovider.cpp | 76 +++++++++++++++++++++- - src/quick/items/qquickpalettecolorprovider_p.h | 1 + - .../quickcontrols/palette/data/reset-color.qml | 52 +++++++++++++++ - tests/auto/quickcontrols/palette/tst_palette.cpp | 71 ++++++++++++++++++++ - 6 files changed, 222 insertions(+), 7 deletions(-) - create mode 100644 tests/auto/quickcontrols/palette/data/reset-color.qml - -diff --git a/src/quick/items/qquickpalette.cpp b/src/quick/items/qquickpalette.cpp -index 824a0bf0961..79b22bd8a07 100644 ---- a/src/quick/items/qquickpalette.cpp -+++ b/src/quick/items/qquickpalette.cpp -@@ -153,6 +153,24 @@ QQuickColorGroup *QQuickPalette::disabled() const - return colorGroup(QPalette::Disabled); - } - -+void QQuickPalette::resetActive() -+{ -+ if (colorProvider().resetColor(QPalette::Active)) -+ Q_EMIT changed(); -+} -+ -+void QQuickPalette::resetInactive() -+{ -+ if (colorProvider().resetColor(QPalette::Inactive)) -+ Q_EMIT changed(); -+} -+ -+void QQuickPalette::resetDisabled() -+{ -+ if (colorProvider().resetColor(QPalette::Disabled)) -+ Q_EMIT changed(); -+} -+ - /*! - \internal - -diff --git a/src/quick/items/qquickpalette_p.h b/src/quick/items/qquickpalette_p.h -index 6586d17a27f..641646c403e 100644 ---- a/src/quick/items/qquickpalette_p.h -+++ b/src/quick/items/qquickpalette_p.h -@@ -26,10 +26,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPalette : public QQuickColorGroup - { - Q_OBJECT - -- Q_PROPERTY(QQuickColorGroup *active READ active WRITE setActive NOTIFY activeChanged FINAL) -- Q_PROPERTY(QQuickColorGroup *inactive READ inactive WRITE setInactive NOTIFY inactiveChanged FINAL) -- Q_PROPERTY(QQuickColorGroup *disabled READ disabled WRITE setDisabled NOTIFY disabledChanged FINAL) -- -+ Q_PROPERTY(QQuickColorGroup *active READ active WRITE setActive RESET resetActive NOTIFY activeChanged FINAL) -+ Q_PROPERTY(QQuickColorGroup *inactive READ inactive WRITE setInactive RESET resetInactive NOTIFY inactiveChanged FINAL) -+ Q_PROPERTY(QQuickColorGroup *disabled READ disabled WRITE setDisabled RESET resetDisabled NOTIFY disabledChanged FINAL) - QML_NAMED_ELEMENT(Palette) - QML_ADDED_IN_VERSION(6, 0) - -@@ -43,6 +42,9 @@ public: - QQuickColorGroup *active() const; - QQuickColorGroup *inactive() const; - QQuickColorGroup *disabled() const; -+ void resetActive(); -+ void resetInactive(); -+ void resetDisabled(); - - QPalette::ColorGroup currentColorGroup() const override; - void setCurrentGroup(QPalette::ColorGroup currentGroup); -@@ -71,6 +73,7 @@ private: - void setColorGroup(QPalette::ColorGroup groupTag, - const QQuickColorGroup::GroupPtr &group, - void (QQuickPalette::*notifier)()); -+ - QQuickColorGroup::GroupPtr colorGroup(QPalette::ColorGroup groupTag) const; - QQuickColorGroup::GroupPtr findColorGroup(QPalette::ColorGroup groupTag) const; - -diff --git a/src/quick/items/qquickpalettecolorprovider.cpp b/src/quick/items/qquickpalettecolorprovider.cpp -index 2d36ff01c54..b92a31c930b 100644 ---- a/src/quick/items/qquickpalettecolorprovider.cpp -+++ b/src/quick/items/qquickpalettecolorprovider.cpp -@@ -16,6 +16,31 @@ static QPalette::ColorGroup adjustCg(QPalette::ColorGroup group) - return group == QPalette::All ? QPalette::Active : group; - } - -+// Begin copy from qpalette.cpp -+static constexpr QPalette::ResolveMask colorRoleOffset(QPalette::ColorGroup colorGroup) -+{ -+ Q_ASSERT(colorGroup < QPalette::NColorGroups); -+ // Exclude NoRole; that bit is used for AccentColor -+ return (qToUnderlying(QPalette::NColorRoles) - 1) * qToUnderlying(colorGroup); -+} -+ -+// TODO: Share the function by private interface in qtbase -+static constexpr QPalette::ResolveMask bitPosition(QPalette::ColorGroup colorGroup, -+ QPalette::ColorRole colorRole) -+{ -+ // Map AccentColor into NoRole for resolving purposes -+ if (colorRole == QPalette::AccentColor) -+ colorRole = QPalette::NoRole; -+ -+ return colorRole + colorRoleOffset(colorGroup); -+} -+ -+static_assert(bitPosition(QPalette::ColorGroup(QPalette::NColorGroups - 1), -+ QPalette::ColorRole(QPalette::NColorRoles - 1)) -+ < sizeof(QPalette::ResolveMask) * CHAR_BIT, -+ "The resolve mask type is not wide enough to fit the entire bit mask."); -+// End copy from qpalette.cpp -+ - class DefaultPalettesProvider : public QQuickAbstractPaletteProvider - { - public: -@@ -44,10 +69,55 @@ bool QQuickPaletteColorProvider::setColor(QPalette::ColorGroup g, QPalette::Colo - - bool QQuickPaletteColorProvider::resetColor(QPalette::ColorGroup group, QPalette::ColorRole role) - { -- const auto &defaultPalette = paletteProvider()->defaultPalette() ; -- const auto &defaultColor = defaultPalette.color(adjustCg(group), role); -+ if (!m_requestedPalette.isAllocated()) -+ return false; -+ -+ QPalette::ResolveMask unsetResolveMask = 0; -+ -+ if (group == QPalette::Current) -+ group = m_requestedPalette->currentColorGroup(); -+ -+ if (group == QPalette::All) { -+ for (int g = QPalette::Active; g < QPalette::NColorGroups; ++g) -+ unsetResolveMask |= (QPalette::ResolveMask(1) << bitPosition(QPalette::ColorGroup(g), role)); -+ } else { -+ unsetResolveMask = (QPalette::ResolveMask(1) << bitPosition(group, role)); -+ } -+ -+ m_requestedPalette->setResolveMask(m_requestedPalette->resolveMask() & ~unsetResolveMask); -+ -+ return updateInheritedPalette(); -+} -+ -+bool QQuickPaletteColorProvider::resetColor(QPalette::ColorGroup group) -+{ -+ if (!m_requestedPalette.isAllocated()) -+ return false; -+ -+ QPalette::ResolveMask unsetResolveMask = 0; - -- return setColor(group, role, defaultColor); -+ auto getResolveMask = [] (QPalette::ColorGroup group) { -+ QPalette::ResolveMask mask = 0; -+ for (int roleIndex = QPalette::WindowText; roleIndex < QPalette::NColorRoles; ++roleIndex) { -+ const auto cr = QPalette::ColorRole(roleIndex); -+ mask |= (QPalette::ResolveMask(1) << bitPosition(group, cr)); -+ } -+ return mask; -+ }; -+ -+ if (group == QPalette::Current) -+ group = m_requestedPalette->currentColorGroup(); -+ -+ if (group == QPalette::All) { -+ for (int g = QPalette::Active; g < QPalette::NColorGroups; ++g) -+ unsetResolveMask |= getResolveMask(QPalette::ColorGroup(g)); -+ } else { -+ unsetResolveMask = getResolveMask(group); -+ } -+ -+ m_requestedPalette->setResolveMask(m_requestedPalette->resolveMask() & ~unsetResolveMask); -+ -+ return updateInheritedPalette(); - } - - bool QQuickPaletteColorProvider::fromQPalette(QPalette p) -diff --git a/src/quick/items/qquickpalettecolorprovider_p.h b/src/quick/items/qquickpalettecolorprovider_p.h -index ff715219dc2..d5c8fc744fb 100644 ---- a/src/quick/items/qquickpalettecolorprovider_p.h -+++ b/src/quick/items/qquickpalettecolorprovider_p.h -@@ -34,6 +34,7 @@ public: - const QColor &color(QPalette::ColorGroup group, QPalette::ColorRole role) const; - bool setColor(QPalette::ColorGroup group, QPalette::ColorRole role, QColor color); - bool resetColor(QPalette::ColorGroup group, QPalette::ColorRole role); -+ bool resetColor(QPalette::ColorGroup group); - - bool fromQPalette(QPalette p); - QPalette palette() const; -diff --git a/tests/auto/quickcontrols/palette/data/reset-color.qml b/tests/auto/quickcontrols/palette/data/reset-color.qml -new file mode 100644 -index 00000000000..d09faed39f8 ---- /dev/null -+++ b/tests/auto/quickcontrols/palette/data/reset-color.qml -@@ -0,0 +1,52 @@ -+// Copyright (C) 2022 zccrs , JiDe Zhang . -+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -+ -+import QtQuick -+import QtQuick.Controls -+ -+ApplicationWindow { -+ id: window -+ property alias control: control -+ property alias item1Palette: item1.palette -+ property alias item2Palette: item2.palette -+ -+ palette { -+ disabled { -+ windowText: "blue" -+ } -+ } -+ -+ Item { -+ id: item1 -+ -+ palette.disabled { -+ text: "yellow" -+ } -+ -+ Item { -+ id: item2 -+ -+ palette.disabled { -+ window: "yellow" -+ } -+ } -+ } -+ -+ Control { -+ id: control -+ objectName: "Control" -+ -+ palette { -+ window: "red" -+ disabled: item2.palette.disabled -+ } -+ } -+ -+ function resetColor() { -+ control.palette.window = undefined -+ } -+ -+ function resetGroup() { -+ control.palette.disabled = undefined -+ } -+} -diff --git a/tests/auto/quickcontrols/palette/tst_palette.cpp b/tests/auto/quickcontrols/palette/tst_palette.cpp -index e3a53f0c21e..27b65618096 100644 ---- a/tests/auto/quickcontrols/palette/tst_palette.cpp -+++ b/tests/auto/quickcontrols/palette/tst_palette.cpp -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - - using namespace QQuickControlsTestUtils; - -@@ -52,6 +53,8 @@ private slots: - void updateBindings(); - - void resolve(); -+ -+ void resetColor(); - }; - - tst_palette::tst_palette() -@@ -427,6 +430,74 @@ void tst_palette::resolve() - control->property("palette").value()->windowText()); - } - -+void tst_palette::resetColor() -+{ -+ QQmlEngine engine; -+ QQmlComponent component(&engine); -+ component.loadUrl(testFileUrl("reset-color.qml")); -+ -+ QScopedPointer window(qobject_cast(component.create())); -+ QVERIFY2(!window.isNull(), qPrintable(component.errorString())); -+ auto windowPalette = window->property("palette").value(); -+ QVERIFY(windowPalette); -+ -+ auto control = window->property("control").value(); -+ QVERIFY(control); -+ auto controlPalette = control->property("palette").value(); -+ QVERIFY(controlPalette); -+ auto item1Palette = window->property("item1Palette").value(); -+ QVERIFY(item1Palette); -+ auto item2Palette = window->property("item2Palette").value(); -+ QVERIFY(item2Palette); -+ -+ QCOMPARE(controlPalette->disabled()->window(), item2Palette->disabled()->window()); -+ QCOMPARE(controlPalette->disabled()->text(), item1Palette->disabled()->text()); -+ QCOMPARE(controlPalette->disabled()->windowText(), windowPalette->disabled()->windowText()); -+ -+ { -+ QSignalSpy spy(controlPalette, &QQuickPalette::changed); -+ item1Palette->disabled()->setText(Qt::red); -+ QVERIFY(spy.count() == 1 || spy.wait()); -+ QCOMPARE(controlPalette->disabled()->text(), QColor(Qt::red)); -+ } -+ -+ { -+ QSignalSpy spy(controlPalette, &QQuickPalette::changed); -+ item1Palette->disabled()->setWindowText(Qt::red); -+ QVERIFY(spy.count() == 1 || spy.wait()); -+ QCOMPARE(controlPalette->disabled()->windowText(), QColor(Qt::red)); -+ } -+ -+ { -+ QSignalSpy spy(controlPalette, &QQuickPalette::changed); -+ item2Palette->disabled()->setWindowText(Qt::blue); -+ QVERIFY(spy.count() == 1 || spy.wait()); -+ QCOMPARE(controlPalette->disabled()->windowText(), QColor(Qt::blue)); -+ } -+ -+ { -+ QSignalSpy spy(controlPalette, &QQuickPalette::changed); -+ QMetaObject::invokeMethod(window.get(), "resetColor", Qt::DirectConnection); -+ QCOMPARE(controlPalette->window(), windowPalette->window()); -+ windowPalette->setWindow(Qt::green); -+ QCOMPARE(controlPalette->window(), QColor(Qt::green)); -+ QVERIFY(spy.count() >= 2); -+ } -+ -+ { -+ QSignalSpy spy(controlPalette, &QQuickPalette::changed); -+ QMetaObject::invokeMethod(window.get(), "resetGroup", Qt::DirectConnection); -+ QCOMPARE(controlPalette->disabled()->windowText(), windowPalette->disabled()->windowText()); -+ windowPalette->disabled()->setWindow(Qt::blue); -+ QCOMPARE(controlPalette->disabled()->window(), QColor(Qt::blue)); -+ item2Palette->disabled()->setWindow(Qt::red); -+ QCOMPARE(controlPalette->disabled()->window(), QColor(Qt::blue)); -+ if (spy.count() == 0) -+ spy.wait(); -+ QCOMPARE(spy.count(), 2); -+ } -+} -+ - QTEST_MAIN(tst_palette) - - #include "tst_palette.moc" --- -2.16.3 - diff --git a/debian/patches/deepin-0002-Rename-accent-color-in-QPalette.patch b/debian/patches/deepin-0002-Rename-accent-color-in-QPalette.patch deleted file mode 100644 index 50620bf6f..000000000 --- a/debian/patches/deepin-0002-Rename-accent-color-in-QPalette.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 4ebb07698d2cd30c824232c1eeb88d91e2d1dac8 Mon Sep 17 00:00:00 2001 -From: Santhosh Kumar -Date: Wed, 16 Aug 2023 14:06:51 +0200 -Subject: [PATCH] Rename accent color in QPalette - -Follow up patch set for 334e1fe2c3da710c821f3c0c98ceb2b7a857838b. - -Synchronized accent color role name change in qtdeclarative. - -Fixes: QTBUG-116107 -Pick-to: 6.6 -Change-Id: Idd2a4bcf16f7df839d5a7c283dc7f152d4f5fe92 -Reviewed-by: Mitch Curtis ---- - src/quick/items/qquickpalettecolorprovider.cpp | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/quick/items/qquickpalettecolorprovider.cpp b/src/quick/items/qquickpalettecolorprovider.cpp -index b92a31c930b..1354a20749b 100644 ---- a/src/quick/items/qquickpalettecolorprovider.cpp -+++ b/src/quick/items/qquickpalettecolorprovider.cpp -@@ -20,7 +20,7 @@ static QPalette::ColorGroup adjustCg(QPalette::ColorGroup group) - static constexpr QPalette::ResolveMask colorRoleOffset(QPalette::ColorGroup colorGroup) - { - Q_ASSERT(colorGroup < QPalette::NColorGroups); -- // Exclude NoRole; that bit is used for AccentColor -+ // Exclude NoRole; that bit is used for Accent - return (qToUnderlying(QPalette::NColorRoles) - 1) * qToUnderlying(colorGroup); - } - -@@ -28,8 +28,8 @@ static constexpr QPalette::ResolveMask colorRoleOffset(QPalette::ColorGroup colo - static constexpr QPalette::ResolveMask bitPosition(QPalette::ColorGroup colorGroup, - QPalette::ColorRole colorRole) - { -- // Map AccentColor into NoRole for resolving purposes -- if (colorRole == QPalette::AccentColor) -+ // Map Accent into NoRole for resolving purposes -+ if (colorRole == QPalette::Accent) - colorRole = QPalette::NoRole; - - return colorRole + colorRoleOffset(colorGroup); diff --git a/debian/patches/deepin-0003-Palette-Remove-redundant-code.patch b/debian/patches/deepin-0003-Palette-Remove-redundant-code.patch deleted file mode 100644 index df10ee960..000000000 --- a/debian/patches/deepin-0003-Palette-Remove-redundant-code.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 874654f3537592feb048d821c4d14c90184dd700 Mon Sep 17 00:00:00 2001 -From: Oliver Eftevaag -Date: Tue, 10 Oct 2023 13:28:39 +0200 -Subject: [PATCH] Palette: Remove redundant code - -In 4e7a83156d47683f777e92d2790cb617f0bb09d5 we duplicated the -implementation for the bitPosition() function in qpalette.cpp. - -The intention was to expose the function in a private header, and -eventually replace the redundant functions in qpalettecolorprovider, -with the ones in QtGui. - -Now that qpalette_p.h exist, lets actually use it. - -Change-Id: Id7528b7f1c3f5481e0410688ef8e018afb951410 -Reviewed-by: Mitch Curtis ---- - .../items/qquickpalettecolorprovider.cpp | 32 +++---------------- - 1 file changed, 4 insertions(+), 28 deletions(-) - -diff --git a/src/quick/items/qquickpalettecolorprovider.cpp b/src/quick/items/qquickpalettecolorprovider.cpp -index 1354a20749b..af6f0ef7a5d 100644 ---- a/src/quick/items/qquickpalettecolorprovider.cpp -+++ b/src/quick/items/qquickpalettecolorprovider.cpp -@@ -3,6 +3,7 @@ - #include "qquickpalettecolorprovider_p.h" - - #include -+#include - - QT_BEGIN_NAMESPACE - -@@ -16,31 +17,6 @@ static QPalette::ColorGroup adjustCg(QPalette::ColorGroup group) - return group == QPalette::All ? QPalette::Active : group; - } - --// Begin copy from qpalette.cpp --static constexpr QPalette::ResolveMask colorRoleOffset(QPalette::ColorGroup colorGroup) --{ -- Q_ASSERT(colorGroup < QPalette::NColorGroups); -- // Exclude NoRole; that bit is used for Accent -- return (qToUnderlying(QPalette::NColorRoles) - 1) * qToUnderlying(colorGroup); --} -- --// TODO: Share the function by private interface in qtbase --static constexpr QPalette::ResolveMask bitPosition(QPalette::ColorGroup colorGroup, -- QPalette::ColorRole colorRole) --{ -- // Map Accent into NoRole for resolving purposes -- if (colorRole == QPalette::Accent) -- colorRole = QPalette::NoRole; -- -- return colorRole + colorRoleOffset(colorGroup); --} -- --static_assert(bitPosition(QPalette::ColorGroup(QPalette::NColorGroups - 1), -- QPalette::ColorRole(QPalette::NColorRoles - 1)) -- < sizeof(QPalette::ResolveMask) * CHAR_BIT, -- "The resolve mask type is not wide enough to fit the entire bit mask."); --// End copy from qpalette.cpp -- - class DefaultPalettesProvider : public QQuickAbstractPaletteProvider - { - public: -@@ -79,9 +55,9 @@ bool QQuickPaletteColorProvider::resetColor(QPalette::ColorGroup group, QPalette - - if (group == QPalette::All) { - for (int g = QPalette::Active; g < QPalette::NColorGroups; ++g) -- unsetResolveMask |= (QPalette::ResolveMask(1) << bitPosition(QPalette::ColorGroup(g), role)); -+ unsetResolveMask |= (QPalette::ResolveMask(1) << QPalettePrivate::bitPosition(QPalette::ColorGroup(g), role)); - } else { -- unsetResolveMask = (QPalette::ResolveMask(1) << bitPosition(group, role)); -+ unsetResolveMask = (QPalette::ResolveMask(1) << QPalettePrivate::bitPosition(group, role)); - } - - m_requestedPalette->setResolveMask(m_requestedPalette->resolveMask() & ~unsetResolveMask); -@@ -100,7 +76,7 @@ bool QQuickPaletteColorProvider::resetColor(QPalette::ColorGroup group) - QPalette::ResolveMask mask = 0; - for (int roleIndex = QPalette::WindowText; roleIndex < QPalette::NColorRoles; ++roleIndex) { - const auto cr = QPalette::ColorRole(roleIndex); -- mask |= (QPalette::ResolveMask(1) << bitPosition(group, cr)); -+ mask |= (QPalette::ResolveMask(1) << QPalettePrivate::bitPosition(group, cr)); - } - return mask; - }; diff --git a/debian/patches/deepin-0004-Fix-corrupt-rendering-when-toggling-rendernode-based-items.patch b/debian/patches/deepin-0004-Fix-corrupt-rendering-when-toggling-rendernode-based-items.patch deleted file mode 100644 index 095498604..000000000 --- a/debian/patches/deepin-0004-Fix-corrupt-rendering-when-toggling-rendernode-based-items.patch +++ /dev/null @@ -1,71 +0,0 @@ -From ae2df32f7921f33925602025173163f9903d2d55 Mon Sep 17 00:00:00 2001 -From: Laszlo Agocs -Date: Wed, 15 Nov 2023 14:31:22 +0100 -Subject: [PATCH] Fix corrupt rendering when toggling rendernode-based items - -Meaning the toggling of visibility. Having a QSGRenderNode come and -go in the scenegraph leads to visual problems, in case the adding -and removal of the node toggles the m_forceNoUseDepthBuffer flag, -which in turn makes useDepthBuffer() return a different value -than before (so disables and then enables doing the opaque -pass in the renderer). Changing this value needs a full rebuild -of the render lists. When adding a node, this is done (regardless -of toggling the flag). When removing, it was not done at all. -Now we do it when resetting the no-Z flag back to false. - -Add a button to the customrendernode example to toggle visibility -since this is useful for example's purposes anyways. However, this -on its own is not sufficient to reproduce the issue. For that, -the DepthAwareRendering flag needs to be removed from the -QSGRenderNode subclass. - -Pick-to: 6.5 -Fixes: QTBUG-119160 -Change-Id: I232354d88f5a4fe5f9f2d6102d0d5439d92782fb -Reviewed-by: Qt CI Bot -Reviewed-by: Andy Nichols -(cherry picked from commit d70b847f776f0d0382c3b2ee1c7549a8a1edc1c1) -Reviewed-by: Qt Cherry-pick Bot ---- - examples/quick/scenegraph/customrendernode/main.qml | 5 +++++ - src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 7 ++++++- - 2 files changed, 11 insertions(+), 1 deletion(-) - -diff --git a/examples/quick/scenegraph/customrendernode/main.qml b/examples/quick/scenegraph/customrendernode/main.qml -index a0b62c4bf81..6a098e47f7c 100644 ---- a/examples/quick/scenegraph/customrendernode/main.qml -+++ b/examples/quick/scenegraph/customrendernode/main.qml -@@ -102,6 +102,11 @@ Item { - } - - -+ Button { -+ text: qsTr("Toggle custom item visibility") -+ onClicked: custom.visible = !custom.visible -+ } -+ - CustomRender { - id: custom - width: Math.min(parent.width, parent.height) -diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp -index a034906c4c0..4baa1f0f608 100644 ---- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp -+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp -@@ -1222,8 +1222,13 @@ void Renderer::nodeWasRemoved(Node *node) - if (e) { - e->removed = true; - m_elementsToDelete.add(e); -- if (m_renderNodeElements.isEmpty()) -+ if (m_renderNodeElements.isEmpty()) { - m_forceNoDepthBuffer = false; -+ // Must have a full rebuild given useDepthBuffer() now returns -+ // a different value than before, meaning there can once again -+ // be an opaque pass. -+ m_rebuild |= FullRebuild; -+ } - - if (e->batch != nullptr) - e->batch->needsPurge = true; --- -2.16.3 - diff --git a/debian/patches/deepin-0005-TextField-Only-enable-paste-action-if-clipboard-has-text.patch b/debian/patches/deepin-0005-TextField-Only-enable-paste-action-if-clipboard-has-text.patch deleted file mode 100644 index 9c0c6c442..000000000 --- a/debian/patches/deepin-0005-TextField-Only-enable-paste-action-if-clipboard-has-text.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 580715fe586e49cf3fc85bb1c1d114d8e02ae625 Mon Sep 17 00:00:00 2001 -From: Wang Fei -Date: Mon, 29 Jan 2024 13:43:17 +0800 -Subject: [PATCH] TextField: Only enable paste action if clipboard has text -MIME-Version: 1.0 -Content-Type: text/plain; charset=utf8 -Content-Transfer-Encoding: 8bit - -Regardless of whether the content of the system clipboard is empty, -Paste Action was always enabled. Add a condition in canPaste that -the clipboard has text, similar to what we do in Qt Widgets. - -Fixes: QTBUG-121594 -Change-Id: I4b897c5ccea40229c4b8fc7d1d0da20540ed5ae1 -Reviewed-by: Tor Arne Vestbø ---- - src/quick/items/qquicktextinput.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp -index 746942591b9..0acb4b38dc0 100644 ---- a/src/quick/items/qquicktextinput.cpp -+++ b/src/quick/items/qquicktextinput.cpp -@@ -2587,7 +2587,7 @@ bool QQuickTextInput::canPaste() const - Q_D(const QQuickTextInput); - if (!d->canPasteValid) { - if (const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData()) -- const_cast(d)->canPaste = !d->m_readOnly && mimeData->hasText(); -+ const_cast(d)->canPaste = !d->m_readOnly && mimeData->hasText() && !mimeData->text().isEmpty(); - const_cast(d)->canPasteValid = true; - } - return d->canPaste; --- -2.16.3 - diff --git a/debian/patches/series b/debian/patches/series deleted file mode 100644 index a9c2a8420..000000000 --- a/debian/patches/series +++ /dev/null @@ -1,7 +0,0 @@ -deepin-0001-Add-the-reset-function-for-properties-of-QQuickPalet.patch -deepin-0002-Rename-accent-color-in-QPalette.patch -deepin-0003-Palette-Remove-redundant-code.patch -deepin-0004-Fix-corrupt-rendering-when-toggling-rendernode-based-items.patch - -# https://codereview.qt-project.org/c/qt/qtdeclarative/+/535176 -deepin-0005-TextField-Only-enable-paste-action-if-clipboard-has-text.patch diff --git a/debian/qml6-module-qtqml-workerscript.install b/debian/qml6-module-qtqml-workerscript.install index b6c4e3026..229d56e99 100644 --- a/debian/qml6-module-qtqml-workerscript.install +++ b/debian/qml6-module-qtqml-workerscript.install @@ -1,4 +1,3 @@ usr/lib/${DEB_HOST_MULTIARCH}/qt6/qml/QtQml/WorkerScript/libworkerscriptplugin.so usr/lib/${DEB_HOST_MULTIARCH}/qt6/qml/QtQml/WorkerScript/plugins.qmltypes usr/lib/${DEB_HOST_MULTIARCH}/qt6/qml/QtQml/WorkerScript/qmldir -usr/lib/${DEB_HOST_MULTIARCH}/libQt6QmlWorkerScript.so.* diff --git a/debian/qml6-module-qtqml-workerscript.lintian-overrides b/debian/qml6-module-qtqml-workerscript.lintian-overrides deleted file mode 100644 index 40b1a7b6f..000000000 --- a/debian/qml6-module-qtqml-workerscript.lintian-overrides +++ /dev/null @@ -1,3 +0,0 @@ -# libQt6QmlWorkerScript6 is a private library installed in a public path -qml6-module-qtqml-workerscript: package-name-doesnt-match-sonames libQt6QmlWorkerScript6 -qml6-module-qtqml-workerscript: no-symbols-control-file usr/lib/*/libQt6QmlWorkerScript.so.6.* diff --git a/debian/qml6-module-qtquick-shapes.install b/debian/qml6-module-qtquick-shapes.install index 5b97302f4..aab0b7d17 100644 --- a/debian/qml6-module-qtquick-shapes.install +++ b/debian/qml6-module-qtquick-shapes.install @@ -1,4 +1,3 @@ usr/lib/${DEB_HOST_MULTIARCH}/qt6/qml/QtQuick/Shapes/libqmlshapesplugin.so usr/lib/${DEB_HOST_MULTIARCH}/qt6/qml/QtQuick/Shapes/plugins.qmltypes usr/lib/${DEB_HOST_MULTIARCH}/qt6/qml/QtQuick/Shapes/qmldir -usr/lib/${DEB_HOST_MULTIARCH}/libQt6QuickShapes.so.* diff --git a/debian/qml6-module-qtquick-shapes.lintian-overrides b/debian/qml6-module-qtquick-shapes.lintian-overrides deleted file mode 100644 index 1b590cd5e..000000000 --- a/debian/qml6-module-qtquick-shapes.lintian-overrides +++ /dev/null @@ -1,3 +0,0 @@ -# libQt6QuickShapes6 is a private library installed in a public path -qml6-module-qtquick-shapes: package-name-doesnt-match-sonames libQt6QuickShapes6 -qml6-module-qtquick-shapes: no-symbols-control-file usr/lib/*/libQt6QuickShapes.so.6.* diff --git a/debian/qt6-declarative-doc-html.doc-base.qtlabsplatform b/debian/qt6-declarative-doc-html.doc-base.qtlabsplatform index ab3bd0d94..960f0b8f6 100644 --- a/debian/qt6-declarative-doc-html.doc-base.qtlabsplatform +++ b/debian/qt6-declarative-doc-html.doc-base.qtlabsplatform @@ -5,5 +5,5 @@ Abstract: This is the HTML documentation for Qt 6 Qt Labs Platform Section: Programming/C++ Format: HTML -Index: /usr/share/doc/qt6-declarative-doc-html/html/qtlabsplatform/qtqtlabsplatform.index +Index: /usr/share/doc/qt6-declarative-doc-html/html/qtlabsplatform/qtlabsplatform.index Files: /usr/share/doc/qt6-declarative-doc-html/html/qtlabsplatform/*.html diff --git a/debian/qt6-declarative-doc-html.doc-base.qtqml b/debian/qt6-declarative-doc-html.doc-base.qtqml index 0886cfc9f..d388297b9 100644 --- a/debian/qt6-declarative-doc-html.doc-base.qtqml +++ b/debian/qt6-declarative-doc-html.doc-base.qtqml @@ -5,5 +5,5 @@ Abstract: This is the HTML documentation for Qt 6 Qt QML Section: Programming/C++ Format: HTML -Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqml/qtqtqml.index +Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqml/qtqml.index Files: /usr/share/doc/qt6-declarative-doc-html/html/qtqml/*.html diff --git a/debian/qt6-declarative-doc-html.doc-base.qtqmlcompiler b/debian/qt6-declarative-doc-html.doc-base.qtqmlcompiler index 40a131c94..8cdfcdaaf 100644 --- a/debian/qt6-declarative-doc-html.doc-base.qtqmlcompiler +++ b/debian/qt6-declarative-doc-html.doc-base.qtqmlcompiler @@ -5,5 +5,5 @@ Abstract: This is the HTML documentation for Qt 6 Qt QML Compiler Section: Programming/C++ Format: HTML -Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlcompiler/qtqtqmlcompiler.index +Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlcompiler/qtqmlcompiler.index Files: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlcompiler/*.html diff --git a/debian/qt6-declarative-doc-html.doc-base.qtqmlcore b/debian/qt6-declarative-doc-html.doc-base.qtqmlcore index c7b3d24d2..524fbd7e4 100644 --- a/debian/qt6-declarative-doc-html.doc-base.qtqmlcore +++ b/debian/qt6-declarative-doc-html.doc-base.qtqmlcore @@ -5,5 +5,5 @@ Abstract: This is the HTML documentation for Qt 6 Qt QML Core Section: Programming/C++ Format: HTML -Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlcore/qtqtqmlcore.index +Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlcore/qtqmlcore.index Files: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlcore/*.html diff --git a/debian/qt6-declarative-doc-html.doc-base.qtqmlmodels b/debian/qt6-declarative-doc-html.doc-base.qtqmlmodels index 2e5194cb9..4256c94d4 100644 --- a/debian/qt6-declarative-doc-html.doc-base.qtqmlmodels +++ b/debian/qt6-declarative-doc-html.doc-base.qtqmlmodels @@ -5,5 +5,5 @@ Abstract: This is the HTML documentation for Qt 6 Qt QML models Section: Programming/C++ Format: HTML -Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlmodels/qtqtqmlmodels.index +Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlmodels/qtqmlmodels.index Files: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlmodels/*.html diff --git a/debian/qt6-declarative-doc-html.doc-base.qtqmltest b/debian/qt6-declarative-doc-html.doc-base.qtqmltest index b1b5cfee4..40922e7d5 100644 --- a/debian/qt6-declarative-doc-html.doc-base.qtqmltest +++ b/debian/qt6-declarative-doc-html.doc-base.qtqmltest @@ -5,5 +5,5 @@ Abstract: This is the HTML documentation for Qt 6 Qt QML Test Section: Programming/C++ Format: HTML -Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqmltest/qtqtqmltest.index +Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqmltest/qtqmltest.index Files: /usr/share/doc/qt6-declarative-doc-html/html/qtqmltest/*.html diff --git a/debian/qt6-declarative-doc-html.doc-base.qtqmlworkerscript b/debian/qt6-declarative-doc-html.doc-base.qtqmlworkerscript index 5d686aa9e..5390b91f4 100644 --- a/debian/qt6-declarative-doc-html.doc-base.qtqmlworkerscript +++ b/debian/qt6-declarative-doc-html.doc-base.qtqmlworkerscript @@ -5,5 +5,5 @@ Abstract: This is the HTML documentation for Qt 6 Qt QML worker script Section: Programming/C++ Format: HTML -Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlworkerscript/qtqtqmlworkerscript.index +Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlworkerscript/qtqmlworkerscript.index Files: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlworkerscript/*.html diff --git a/debian/qt6-declarative-doc-html.doc-base.qtqmlxmllistmodel b/debian/qt6-declarative-doc-html.doc-base.qtqmlxmllistmodel index 37210b38f..ece128419 100644 --- a/debian/qt6-declarative-doc-html.doc-base.qtqmlxmllistmodel +++ b/debian/qt6-declarative-doc-html.doc-base.qtqmlxmllistmodel @@ -5,5 +5,5 @@ Abstract: This is the HTML documentation for Qt 6 Qt QML XML list model Section: Programming/C++ Format: HTML -Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlxmllistmodel/qtqtqmlxmllistmodel.index +Index: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlxmllistmodel/qtqmlxmllistmodel.index Files: /usr/share/doc/qt6-declarative-doc-html/html/qtqmlxmllistmodel/*.html diff --git a/debian/qt6-declarative-doc-html.doc-base.qtquick b/debian/qt6-declarative-doc-html.doc-base.qtquick index 36097f678..e45bbea9f 100644 --- a/debian/qt6-declarative-doc-html.doc-base.qtquick +++ b/debian/qt6-declarative-doc-html.doc-base.qtquick @@ -5,5 +5,5 @@ Abstract: This is the HTML documentation for Qt 6 Qt Quick Section: Programming/C++ Format: HTML -Index: /usr/share/doc/qt6-declarative-doc-html/html/qtquick/qtqtquick.index +Index: /usr/share/doc/qt6-declarative-doc-html/html/qtquick/qtquick.index Files: /usr/share/doc/qt6-declarative-doc-html/html/qtquick/*.html diff --git a/debian/qt6-declarative-doc-html.doc-base.qtquickcontrols b/debian/qt6-declarative-doc-html.doc-base.qtquickcontrols index 14dfd755a..7feef2b2a 100644 --- a/debian/qt6-declarative-doc-html.doc-base.qtquickcontrols +++ b/debian/qt6-declarative-doc-html.doc-base.qtquickcontrols @@ -5,5 +5,5 @@ Abstract: This is the HTML documentation for Qt 6 Qt Quick Controls Section: Programming/C++ Format: HTML -Index: /usr/share/doc/qt6-declarative-doc-html/html/qtquickcontrols/qtqtquickcontrols.index +Index: /usr/share/doc/qt6-declarative-doc-html/html/qtquickcontrols/qtquickcontrols.index Files: /usr/share/doc/qt6-declarative-doc-html/html/qtquickcontrols/*.html diff --git a/debian/qt6-declarative-doc-html.doc-base.qtquickdialogs b/debian/qt6-declarative-doc-html.doc-base.qtquickdialogs index 4a601be40..2d4d01df0 100644 --- a/debian/qt6-declarative-doc-html.doc-base.qtquickdialogs +++ b/debian/qt6-declarative-doc-html.doc-base.qtquickdialogs @@ -5,5 +5,5 @@ Abstract: This is the HTML documentation for Qt 6 Qt Quick Dialogs Section: Programming/C++ Format: HTML -Index: /usr/share/doc/qt6-declarative-doc-html/html/qtquickdialogs/qtqtquickdialogs.index +Index: /usr/share/doc/qt6-declarative-doc-html/html/qtquickdialogs/qtquickdialogs.index Files: /usr/share/doc/qt6-declarative-doc-html/html/qtquickdialogs/*.html diff --git a/dependencies.yaml b/dependencies.yaml index a756c0858..9f2ff79e8 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,16 +1,16 @@ dependencies: ../qtbase: - ref: e2cbce919ccefcae2b18f90257d67bc6e24c3c94 + ref: dec1863c7dc63e5788b0c6c061d36e856a6ae2b2 required: true ../qtimageformats: - ref: 64278e72cd3f796f5883626b024c4561797445d7 + ref: 96cc838d4b7768b2a9ee3388114d4c498afd3ea2 required: false ../qtlanguageserver: - ref: f8c5ba5dd172cb3f537ae9a35bfcaa611aab2bf4 + ref: 7fef2d2c09f3c8c2380c9e759aad8b4c8b765ba2 required: false ../qtshadertools: - ref: aa5c5eeabd09e6af1aeeb11450fa54f2eeabd987 + ref: 890783bc860332041cd5526e51a5b28c2042f428 required: false ../qtsvg: - ref: 18801e1b024dad9401fc655549a6bb123439cfa3 + ref: c5aacf55ee78a4d229dfbb62cb3b142ffcb5eb83 required: false diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter1/CMakeLists.txt b/examples/qmlcompiler/tutorials/helloworld/chapter1/CMakeLists.txt new file mode 100644 index 000000000..b9466b61b --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter1/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.21) + +project(hello_world_plugin VERSION 1.0.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 REQUIRED COMPONENTS QmlCompiler) + +qt_standard_project_setup( + REQUIRES 6.6 +) + +qt_add_plugin(HelloWorldPlugin) + +target_sources(HelloWorldPlugin + PRIVATE + helloplugin.h + helloplugin.cpp +) + +target_link_libraries(HelloWorldPlugin PRIVATE Qt::QmlCompiler) diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.cpp b/examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.cpp new file mode 100644 index 000000000..ad36e64fa --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +#include "helloplugin.h" +#include + +using namespace Qt::StringLiterals; + +static constexpr QQmlSA::LoggerWarningId helloWorld { "Plugin.HelloWorld.hello-world" }; + +void HelloWorldPlugin::registerPasses(QQmlSA::PassManager *manager, const QQmlSA::Element &rootElement) +{ + const bool pluginIsEnabled = manager->isCategoryEnabled(helloWorld); + qDebug() << "Hello World plugin is" << (pluginIsEnabled ? "enabled" : "disabled"); + if (!pluginIsEnabled) + return; // skip registration if the plugin is disabled anyway + // here we will later register our passes +} + +#include "moc_helloplugin.cpp" diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.h b/examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.h new file mode 100644 index 000000000..6666c78be --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.h @@ -0,0 +1,21 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef HELLO_PLUGIN_H +#define HELLO_PLUGIN_H + +#include +#include + +class HelloWorldPlugin : public QObject, public QQmlSA::LintPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QmlLintPluginInterface_iid FILE "plugin.json") + Q_INTERFACES(QQmlSA::LintPlugin) + +public: + void registerPasses(QQmlSA::PassManager *manager, const QQmlSA::Element &rootElement) override; +}; + +#endif + diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter1/plugin.json b/examples/qmlcompiler/tutorials/helloworld/chapter1/plugin.json new file mode 100644 index 000000000..3d8c1ff20 --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter1/plugin.json @@ -0,0 +1,13 @@ +{ + "name": "HelloWorld", + "author": "Qt Example", + "description": "Demonstrates how to write a qmllint plugin", + "version": "1.0", + "loggingCategories": [ + { + "name": "hello-world", + "settingsName": "HelloWorld", + "description": "Used to create test messages" + } + ] +} diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter1/test.qml b/examples/qmlcompiler/tutorials/helloworld/chapter1/test.qml new file mode 100644 index 000000000..99af71ad7 --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter1/test.qml @@ -0,0 +1,24 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Item { + id: root + + property string greeting: "Hello" + + component MyText : Text {} + + component NotText : Item { + property string text + } + + Text { text: "Hello world!" } + Text { text: root.greeting } + Text { text: "Goodbye world!" } + NotText { + text: "Does not trigger" + MyText { text: "Goodbye world!" } + } +} diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter2/CMakeLists.txt b/examples/qmlcompiler/tutorials/helloworld/chapter2/CMakeLists.txt new file mode 100644 index 000000000..b9466b61b --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter2/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.21) + +project(hello_world_plugin VERSION 1.0.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 REQUIRED COMPONENTS QmlCompiler) + +qt_standard_project_setup( + REQUIRES 6.6 +) + +qt_add_plugin(HelloWorldPlugin) + +target_sources(HelloWorldPlugin + PRIVATE + helloplugin.h + helloplugin.cpp +) + +target_link_libraries(HelloWorldPlugin PRIVATE Qt::QmlCompiler) diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.cpp b/examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.cpp new file mode 100644 index 000000000..431ad97f1 --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "helloplugin.h" +#include + +using namespace Qt::StringLiterals; + +static constexpr QQmlSA::LoggerWarningId helloWorld { "Plugin.HelloWorld.hello-world" }; + +class HelloWorldElementPass : public QQmlSA::ElementPass +{ +public: + HelloWorldElementPass(QQmlSA::PassManager *manager); + bool shouldRun(const QQmlSA::Element &element) override; + void run(const QQmlSA::Element &element) override; +private: + QQmlSA::Element m_textType; +}; + +HelloWorldElementPass::HelloWorldElementPass(QQmlSA::PassManager *manager) + : QQmlSA::ElementPass(manager) +{ + m_textType = resolveType("QtQuick", "Text"); +} + +bool HelloWorldElementPass::shouldRun(const QQmlSA::Element &element) +{ + if (!element.inherits(m_textType)) + return false; + if (!element.hasOwnPropertyBindings(u"text"_s)) + return false; + return true; +} + +void HelloWorldElementPass::run(const QQmlSA::Element &element) +{ + auto textBindings = element.ownPropertyBindings(u"text"_s); + for (const auto &textBinding: textBindings) { + if (textBinding.bindingType() != QQmlSA::BindingType::StringLiteral) + continue; + if (textBinding.stringValue() != u"Hello world!"_s) + emitWarning("Incorrect greeting", helloWorld, textBinding.sourceLocation()); + } +} + +void HelloWorldPlugin::registerPasses(QQmlSA::PassManager *manager, const QQmlSA::Element &rootElement) +{ + const bool pluginIsEnabled = manager->isCategoryEnabled(helloWorld); + qDebug() << "Hello World plugin is" << (pluginIsEnabled ? "enabled" : "disabled"); + if (!pluginIsEnabled) + return; // skip registration if the plugin is disabled anyway + manager->registerElementPass(std::make_unique(manager)); +} + +#include "moc_helloplugin.cpp" diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.h b/examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.h new file mode 100644 index 000000000..6666c78be --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.h @@ -0,0 +1,21 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef HELLO_PLUGIN_H +#define HELLO_PLUGIN_H + +#include +#include + +class HelloWorldPlugin : public QObject, public QQmlSA::LintPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QmlLintPluginInterface_iid FILE "plugin.json") + Q_INTERFACES(QQmlSA::LintPlugin) + +public: + void registerPasses(QQmlSA::PassManager *manager, const QQmlSA::Element &rootElement) override; +}; + +#endif + diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter2/plugin.json b/examples/qmlcompiler/tutorials/helloworld/chapter2/plugin.json new file mode 100644 index 000000000..3d8c1ff20 --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter2/plugin.json @@ -0,0 +1,13 @@ +{ + "name": "HelloWorld", + "author": "Qt Example", + "description": "Demonstrates how to write a qmllint plugin", + "version": "1.0", + "loggingCategories": [ + { + "name": "hello-world", + "settingsName": "HelloWorld", + "description": "Used to create test messages" + } + ] +} diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter2/test.qml b/examples/qmlcompiler/tutorials/helloworld/chapter2/test.qml new file mode 100644 index 000000000..99af71ad7 --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter2/test.qml @@ -0,0 +1,24 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick + +Item { + id: root + + property string greeting: "Hello" + + component MyText : Text {} + + component NotText : Item { + property string text + } + + Text { text: "Hello world!" } + Text { text: root.greeting } + Text { text: "Goodbye world!" } + NotText { + text: "Does not trigger" + MyText { text: "Goodbye world!" } + } +} diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter3/CMakeLists.txt b/examples/qmlcompiler/tutorials/helloworld/chapter3/CMakeLists.txt new file mode 100644 index 000000000..b9466b61b --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter3/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.21) + +project(hello_world_plugin VERSION 1.0.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 REQUIRED COMPONENTS QmlCompiler) + +qt_standard_project_setup( + REQUIRES 6.6 +) + +qt_add_plugin(HelloWorldPlugin) + +target_sources(HelloWorldPlugin + PRIVATE + helloplugin.h + helloplugin.cpp +) + +target_link_libraries(HelloWorldPlugin PRIVATE Qt::QmlCompiler) diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.cpp b/examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.cpp new file mode 100644 index 000000000..93ee6d80c --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "helloplugin.h" +#include + +using namespace Qt::StringLiterals; + +static constexpr QQmlSA::LoggerWarningId helloWorld { "Plugin.HelloWorld.hello-world" }; + +class HelloWorldElementPass : public QQmlSA::ElementPass +{ +public: + HelloWorldElementPass(QQmlSA::PassManager *manager); + bool shouldRun(const QQmlSA::Element &element) override; + void run(const QQmlSA::Element &element) override; +private: + QQmlSA::Element m_textType; +}; + +HelloWorldElementPass::HelloWorldElementPass(QQmlSA::PassManager *manager) + : QQmlSA::ElementPass(manager) +{ + m_textType = resolveType("QtQuick", "Text"); +} + +bool HelloWorldElementPass::shouldRun(const QQmlSA::Element &element) +{ + if (!element.inherits(m_textType)) + return false; + if (!element.hasOwnPropertyBindings(u"text"_s)) + return false; + return true; +} + +void HelloWorldElementPass::run(const QQmlSA::Element &element) +{ + auto textBindings = element.ownPropertyBindings(u"text"_s); + for (const auto &textBinding: textBindings) { + if (textBinding.bindingType() != QQmlSA::BindingType::StringLiteral) + continue; + QString currentBinding = textBinding.stringValue(); + if (currentBinding == u"Hello world!"_s) + continue; + if (currentBinding == u"Goodbye world!"_s) { + QQmlSA::FixSuggestion suggestion(u"Replace 'Goodbye' with 'Hello'"_s, + textBinding.sourceLocation(), u"\"Hello world!\""_s); + suggestion.setAutoApplicable(true); + emitWarning("Incorrect greeting", helloWorld, textBinding.sourceLocation(), suggestion); + } + } +} + + +void HelloWorldPlugin::registerPasses(QQmlSA::PassManager *manager, const QQmlSA::Element &rootElement) +{ + const bool pluginIsEnabled = manager->isCategoryEnabled(helloWorld); + qDebug() << "Hello World plugin is" << (pluginIsEnabled ? "enabled" : "disabled"); + if (!pluginIsEnabled) + return; // skip registration if the plugin is disabled anyway + manager->registerElementPass(std::make_unique(manager)); +} + +#include "moc_helloplugin.cpp" diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.h b/examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.h new file mode 100644 index 000000000..6666c78be --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.h @@ -0,0 +1,21 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef HELLO_PLUGIN_H +#define HELLO_PLUGIN_H + +#include +#include + +class HelloWorldPlugin : public QObject, public QQmlSA::LintPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QmlLintPluginInterface_iid FILE "plugin.json") + Q_INTERFACES(QQmlSA::LintPlugin) + +public: + void registerPasses(QQmlSA::PassManager *manager, const QQmlSA::Element &rootElement) override; +}; + +#endif + diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter3/plugin.json b/examples/qmlcompiler/tutorials/helloworld/chapter3/plugin.json new file mode 100644 index 000000000..3d8c1ff20 --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter3/plugin.json @@ -0,0 +1,13 @@ +{ + "name": "HelloWorld", + "author": "Qt Example", + "description": "Demonstrates how to write a qmllint plugin", + "version": "1.0", + "loggingCategories": [ + { + "name": "hello-world", + "settingsName": "HelloWorld", + "description": "Used to create test messages" + } + ] +} diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter3/test.qml b/examples/qmlcompiler/tutorials/helloworld/chapter3/test.qml new file mode 100644 index 000000000..42fbaa108 --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter3/test.qml @@ -0,0 +1,26 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +// [0] +import QtQuick + +Item { + id: root + + property string greeting: "Hello" + + component MyText : Text {} + + component NotText : Item { + property string text + } + + Text { text: "Hello world!" } + Text { text: root.greeting } + Text { text: "Goodbye world!" } + NotText { + text: "Does not trigger" + MyText { text: "Goodbye world!" } + } +} +// [0] diff --git a/examples/quick/customitems/dialcontrol/doc/src/dialcontrol.qdoc b/examples/quick/customitems/dialcontrol/doc/src/dialcontrol.qdoc index a94d93788..7b56478c3 100644 --- a/examples/quick/customitems/dialcontrol/doc/src/dialcontrol.qdoc +++ b/examples/quick/customitems/dialcontrol/doc/src/dialcontrol.qdoc @@ -6,7 +6,7 @@ \title UI Components: Dial Control Example \example customitems/dialcontrol \brief The Dial Control Example shows how to create a speedometer-type dial. - \examplecategory {Graphics & Multimedia} + \examplecategory {User Interface Components} This example shows how to create a dial-type control. It combines \l Image elements with \l Rotation transforms and \l SpringAnimation behaviors diff --git a/examples/quick/customitems/flipable/doc/src/flipable.qdoc b/examples/quick/customitems/flipable/doc/src/flipable.qdoc index e9cd6b75f..8b2eea661 100644 --- a/examples/quick/customitems/flipable/doc/src/flipable.qdoc +++ b/examples/quick/customitems/flipable/doc/src/flipable.qdoc @@ -5,7 +5,7 @@ \title UI Components: Flipable Example \example customitems/flipable \brief The Flipable Example shows an item that flips whenever clicked, rotating around the y-axis. - \examplecategory {Graphics & Multimedia} + \examplecategory {User Interface Components} This example shows how to use the \l Flipable element. diff --git a/examples/quick/customitems/painteditem/CMakeLists.txt b/examples/quick/customitems/painteditem/CMakeLists.txt index b9f608da0..d97db9b03 100644 --- a/examples/quick/customitems/painteditem/CMakeLists.txt +++ b/examples/quick/customitems/painteditem/CMakeLists.txt @@ -45,7 +45,5 @@ install(TARGETS painteditemexample include(../../shared/QtBundleQmlModuleForMacOS.cmake) set(app_target "painteditemexample") -set(qml_plugin_target "qmltextballoon") -set(qml_module_uri "TextBalloon") -add_qml_module_to_macos_app_bundle( - "${app_target}" "${qml_plugin_target}" "${qml_module_uri}") +set(qml_module "qmltextballoon") +add_qml_module_to_macos_app_bundle("${app_target}" "${qml_module}") diff --git a/examples/quick/embeddedinwidgets/embeddedinwidgets.qrc b/examples/quick/embeddedinwidgets/embeddedinwidgets.qrc index 40a959932..9fc33601d 100644 --- a/examples/quick/embeddedinwidgets/embeddedinwidgets.qrc +++ b/examples/quick/embeddedinwidgets/embeddedinwidgets.qrc @@ -1,5 +1,5 @@ - + main.qml reflect.frag.qsb diff --git a/examples/quick/pointerhandlers/components/QuadPieMenu.qml b/examples/quick/pointerhandlers/components/QuadPieMenu.qml index 9c2364fea..2e2967790 100644 --- a/examples/quick/pointerhandlers/components/QuadPieMenu.qml +++ b/examples/quick/pointerhandlers/components/QuadPieMenu.qml @@ -9,6 +9,7 @@ TapHandler { signal triggered(string text) id: menuTap + acceptedButtons: Qt.RightButton gesturePolicy: TapHandler.DragWithinBounds onPressedChanged: if (pressed) { impl.x = point.position.x - impl.width / 2 @@ -22,7 +23,10 @@ TapHandler { parent: menuTap.parent width: 100 height: 100 - scale: Math.min(1, Math.max(0, menuTap.timeHeld * 4)) + // with touchscreen or stylus, long-press slowly expands the menu to size + // with mouse or touchpad right-click, it opens instantly + scale: menuTap.point.device.pointerType === PointerDevice.Generic ? + 1 : Math.min(1, Math.max(0, menuTap.timeHeld * 4)) opacity: scale * 2 visible: menuTap.pressed property Shape highlightedShape: null diff --git a/examples/quick/quickwidgets/quickwidget/main.cpp b/examples/quick/quickwidgets/quickwidget/main.cpp index ecac279a2..584cecfb0 100644 --- a/examples/quick/quickwidgets/quickwidget/main.cpp +++ b/examples/quick/quickwidgets/quickwidget/main.cpp @@ -63,14 +63,22 @@ MainWindow::MainWindow() setCentralWidget(centralWidget); QMenu *fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(tr("Grab framebuffer"), this, &MainWindow::grabFramebuffer); - fileMenu->addAction(tr("Render to pixmap"), this, &MainWindow::renderToPixmap); - fileMenu->addAction(tr("Grab via grabToImage"), this, &MainWindow::grabToImage); + auto grabAction = fileMenu->addAction(tr("Grab framebuffer"), this, &MainWindow::grabFramebuffer); + auto renderAction = fileMenu->addAction(tr("Render to pixmap"), this, &MainWindow::renderToPixmap); + auto grabToImageAction = fileMenu->addAction(tr("Grab via grabToImage"), this, &MainWindow::grabToImage); fileMenu->addAction(tr("Quit"), qApp, &QCoreApplication::quit); QMenu *windowMenu = menuBar()->addMenu(tr("&Window")); windowMenu->addAction(tr("Add tab widget"), this, [this, centralWidget] { createQuickWidgetsInTabs(centralWidget); }); + + connect(m_quickWidget, &QObject::destroyed, this, + [this, grabAction, renderAction, grabToImageAction] { + m_quickWidget = nullptr; + grabAction->setEnabled(false); + renderAction->setEnabled(false); + grabToImageAction->setEnabled(false); + }); } void MainWindow::createQuickWidgetsInTabs(QMdiArea *mdiArea) @@ -123,6 +131,7 @@ void MainWindow::quickWidgetStatusChanged(QQuickWidget::Status status) { if (status == QQuickWidget::Error) { QStringList errors; + Q_ASSERT(m_quickWidget); const auto widgetErrors = m_quickWidget->errors(); for (const QQmlError &error : widgetErrors) errors.append(error.toString()); @@ -147,12 +156,14 @@ template void saveToFile(QWidget *parent, T *saveable) void MainWindow::grabFramebuffer() { + Q_ASSERT(m_quickWidget); QImage image = m_quickWidget->grabFramebuffer(); saveToFile(this, &image); } void MainWindow::renderToPixmap() { + Q_ASSERT(m_quickWidget); QPixmap pixmap(m_quickWidget->size()); m_quickWidget->render(&pixmap); saveToFile(this, &pixmap); @@ -165,6 +176,7 @@ void MainWindow::grabToImage() fd.setDefaultSuffix("png"); fd.selectFile("test_grabToImage.png"); if (fd.exec() == QDialog::Accepted) { + Q_ASSERT(m_quickWidget); QMetaObject::invokeMethod(m_quickWidget->rootObject(), "performLayerBasedGrab", Q_ARG(QVariant, fd.selectedFiles().first())); } diff --git a/examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc b/examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc index 2d4ce46fe..09f3f3a9f 100644 --- a/examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc +++ b/examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc @@ -8,9 +8,9 @@ \ingroup qtquickexamples \brief Shows how to implement a custom geometry in the Qt Quick Scene Graph. - The custom geometry example shows how to create a QQuickItem which + The custom geometry example shows how to create a \l QQuickItem that uses the scene graph API to build a custom geometry for the scene - graph. It does this by creating a BezierCurve item which is made + graph. It does this by creating a \c BezierCurve item, which is made part of the CustomGeometry module and makes use of this in a QML file. @@ -115,7 +115,7 @@ \snippet scenegraph/customgeometry/beziercurve.cpp 6 The scene graph API provides a few commonly used material - implementations. In this example we use the QSGFlatColorMaterial + implementations. In this example we use the QSGFlatColorMaterial, which will fill the shape defined by the geometry with a solid color. Again we pass the ownership of the material to the node, so it can be cleaned up by the scene graph. @@ -130,7 +130,7 @@ \snippet scenegraph/customgeometry/beziercurve.cpp 8 - To fill the geometry, we first extract the vertex array from + To fill the geometry we first extract the vertex array from it. Since we are using one of the default attribute sets, we can use the convenience function QSGGeometry::vertexDataAsPoint2D(). Then we go through each segment and calculate its position and @@ -138,7 +138,7 @@ \snippet scenegraph/customgeometry/beziercurve.cpp 9 - In the end of the function, we return the node so the scene graph + At the end of the function we return the node so the scene graph can render it. \section1 Application Entry-Point @@ -153,9 +153,26 @@ To make use of the BezierCurve item, we need to register it in the QML engine, using the QML_ELEMENT macro. This gives it the name BezierCurve and makes it part of the \c {CustomGeometry 1.0} - module as defined in the customgeometry.pro file: - - \quotefile scenegraph/customgeometry/customgeometry.pro + module as defined in the project's build files: + + \if defined(onlinedocs) + \tab {build-qt-app}{tab-cmake}{CMake}{checked} + \tab {build-qt-app}{tab-qmake}{qmake}{} + \tabcontent {tab-cmake} + \else + \section1 Using CMake + \endif + \quotefile scenegraph/customgeometry/CMakeLists.txt + \if defined(onlinedocs) + \endtabcontent + \tabcontent {tab-qmake} + \else + \section1 Using qmake + \endif + \quotefile scenegraph/customgeometry/customgeometry.pro + \if defined(onlinedocs) + \endtabcontent + \endif As the bezier curve is drawn as line strips, we specify that the view should be multisampled to get antialiasing. This is not diff --git a/examples/quick/scenegraph/customrendernode/main.qml b/examples/quick/scenegraph/customrendernode/main.qml index a0b62c4bf..6a098e47f 100644 --- a/examples/quick/scenegraph/customrendernode/main.qml +++ b/examples/quick/scenegraph/customrendernode/main.qml @@ -102,6 +102,11 @@ Item { } + Button { + text: qsTr("Toggle custom item visibility") + onClicked: custom.visible = !custom.visible + } + CustomRender { id: custom width: Math.min(parent.width, parent.height) diff --git a/examples/quick/shared/CMakeLists.txt b/examples/quick/shared/CMakeLists.txt index 704d14802..629a35539 100644 --- a/examples/quick/shared/CMakeLists.txt +++ b/examples/quick/shared/CMakeLists.txt @@ -42,10 +42,8 @@ include(QtBundleQmlModuleForMacOS.cmake) # Puts the shared qml module plugin and qmldir into the macOS app bundle directory. # Only call this function if your main project has the MACOSX_BUNDLE option set. function(bundle_shared app_target) - set(qml_plugin_target "${PROJECT_NAME}_shared") - set(qml_module_uri "shared") - add_qml_module_to_macos_app_bundle( - "${app_target}" "${qml_plugin_target}" "${qml_module_uri}") + set(qml_module_target "${PROJECT_NAME}_shared") + add_qml_module_to_macos_app_bundle("${app_target}" "${qml_module_target}") endfunction() set(INSTALL_SHAREDDIR "${INSTALL_EXAMPLESDIR}/quick/${PROJECT_NAME}/shared") diff --git a/examples/quick/shared/LauncherList.qml b/examples/quick/shared/LauncherList.qml index ee8fc3984..f86ab8044 100644 --- a/examples/quick/shared/LauncherList.qml +++ b/examples/quick/shared/LauncherList.qml @@ -174,22 +174,26 @@ Rectangle { id: back source: "images/back.png" anchors.verticalCenter: parent.verticalCenter - anchors.verticalCenterOffset: 2 + anchors.verticalCenterOffset: 1 anchors.left: parent.left - anchors.leftMargin: 16 + anchors.leftMargin: 6 + width: 38 + height: 31 + fillMode: Image.Pad + horizontalAlignment: Image.AlignHCenter + verticalAlignment: Image.AlignVCenter TapHandler { id: tapHandler enabled: root.activePageCount > 0 + gesturePolicy: TapHandler.ReleaseWithinBounds + longPressThreshold: 0 onTapped: { pageContainer.children[pageContainer.children.length - 1].exit() } } Rectangle { - anchors.centerIn: back - width: 38 - height: 31 - anchors.verticalCenterOffset: -1 + anchors.fill: parent opacity: tapHandler.pressed ? 1 : 0 Behavior on opacity { NumberAnimation{ duration: 100 }} gradient: Gradient { diff --git a/examples/quick/shared/QtBundleQmlModuleForMacOS.cmake b/examples/quick/shared/QtBundleQmlModuleForMacOS.cmake index 06d148732..767b64bbf 100644 --- a/examples/quick/shared/QtBundleQmlModuleForMacOS.cmake +++ b/examples/quick/shared/QtBundleQmlModuleForMacOS.cmake @@ -1,12 +1,18 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -function(add_qml_module_to_macos_app_bundle app_target qml_plugin_target qml_module_uri) +function(add_qml_module_to_macos_app_bundle app_target qml_module) if(QT6_IS_SHARED_LIBS_BUILD AND APPLE) # The application's main.cpp adds an explicit QML import path to look for qml module plugins # under a PlugIns subdirectory of a macOS app bundle. # Copy the qmldir and shared library qml plugin. + qt6_query_qml_module(${qml_module} + QMLDIR qmldir_file + PLUGIN_TARGET qml_plugin_target + URI qml_module_uri + ) + # Ensure the executable depends on the plugin so the plugin is copied # only after it was built. add_dependencies(${app_target} ${qml_plugin_target}) @@ -17,9 +23,6 @@ function(add_qml_module_to_macos_app_bundle app_target qml_plugin_target qml_mod set(dest_module_dir_in_app_bundle "${app_dir}/../PlugIns/${escaped_uri}") - set(qml_plugin_dir "$") - set(qmldir_file "${qml_plugin_dir}/qmldir") - add_custom_command(TARGET ${app_target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${dest_module_dir_in_app_bundle} COMMAND ${CMAKE_COMMAND} -E copy_if_different diff --git a/examples/quick/shared/SimpleLauncherDelegate.qml b/examples/quick/shared/SimpleLauncherDelegate.qml index c6ca9802d..a6ac090b3 100644 --- a/examples/quick/shared/SimpleLauncherDelegate.qml +++ b/examples/quick/shared/SimpleLauncherDelegate.qml @@ -9,7 +9,7 @@ Rectangle { property Item exampleItem width: ListView.view.width - height: button.implicitHeight + 22 + height: col.implicitHeight + 22 signal clicked() @@ -22,10 +22,18 @@ Rectangle { GradientStop { position: 1 Behavior on color {ColorAnimation { duration: 100 }} - color: tapHandler.pressed ? "#e0e0e0" : button.containsMouse ? "#f5f5f5" : "#eee" + color: tapHandler.pressed ? "#e0e0e0" : hoverHandler.hovered ? "#f5f5f5" : "#eee" } } + TapHandler { + id: tapHandler + onTapped: container.clicked() + } + HoverHandler { + id: hoverHandler + } + Image { id: image opacity: 0.7 @@ -36,53 +44,28 @@ Rectangle { anchors.rightMargin: 16 } - Item { - id: button - anchors.top: parent.top + Column { + id: col + spacing: 2 anchors.left: parent.left - anchors.bottom: parent.bottom anchors.right:image.left - implicitHeight: col.height - height: implicitHeight - width: buttonLabel.width + 20 - property alias containsMouse: hoverHandler.hovered - - TapHandler { - id: tapHandler - onTapped: container.clicked() - } - HoverHandler { - id: hoverHandler + anchors.margins: 10 + anchors.verticalCenter: parent.verticalCenter + Text { + width: parent.width + text: container.name + color: "black" + font.pixelSize: 22 + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + styleColor: "white" + style: Text.Raised } - - Column { - spacing: 2 - id: col - anchors.verticalCenter: parent.verticalCenter + Text { width: parent.width - Text { - id: buttonLabel - anchors.left: parent.left - anchors.leftMargin: 10 - anchors.right: parent.right - anchors.rightMargin: 10 - text: container.name - color: "black" - font.pixelSize: 22 - wrapMode: Text.WrapAtWordBoundaryOrAnywhere - styleColor: "white" - style: Text.Raised - - } - Text { - id: buttonLabel2 - anchors.left: parent.left - anchors.leftMargin: 10 - text: container.description - wrapMode: Text.WrapAtWordBoundaryOrAnywhere - color: "#666" - font.pixelSize: 12 - } + text: container.description + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + color: "#666" + font.pixelSize: 12 } } diff --git a/examples/quickcontrols/CMakeLists.txt b/examples/quickcontrols/CMakeLists.txt index 63a443bd4..47f6281c7 100644 --- a/examples/quickcontrols/CMakeLists.txt +++ b/examples/quickcontrols/CMakeLists.txt @@ -13,7 +13,7 @@ qt_internal_add_example(texteditor) qt_internal_add_example(contactlist) qt_internal_add_example(wearable) qt_internal_add_example(imagine/automotive) -if (TARGET Qt6::Svg) +if (TARGET Qt6::Svg AND NOT ANDROID AND NOT IOS) qt_internal_add_example(filesystemexplorer) endif() if(TARGET Qt6::Widgets) diff --git a/examples/quickcontrols/attachedstyleproperties/CMakeLists.txt b/examples/quickcontrols/attachedstyleproperties/CMakeLists.txt index 5c5536aac..159395307 100644 --- a/examples/quickcontrols/attachedstyleproperties/CMakeLists.txt +++ b/examples/quickcontrols/attachedstyleproperties/CMakeLists.txt @@ -46,7 +46,5 @@ install(TARGETS attachedstylepropertiesexample include(../../quick/shared/QtBundleQmlModuleForMacOS.cmake) set(app_target "attachedstylepropertiesexample") -set(qml_plugin_target "MyStyleplugin") -set(qml_module_uri "MyStyle") -add_qml_module_to_macos_app_bundle( - "${app_target}" "${qml_plugin_target}" "${qml_module_uri}") +set(qml_module_target "MyStyle") +add_qml_module_to_macos_app_bundle("${app_target}" "${qml_module_target}") diff --git a/examples/quickcontrols/contactlist/CMakeLists.txt b/examples/quickcontrols/contactlist/CMakeLists.txt index 2024157a9..508bccaae 100644 --- a/examples/quickcontrols/contactlist/CMakeLists.txt +++ b/examples/quickcontrols/contactlist/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2022 The Qt Company Ltd. +# Copyright (C) 2023 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause cmake_minimum_required(VERSION 3.16) @@ -28,7 +28,7 @@ qt_add_qml_module(contactlistexample "ContactForm.ui.qml" "ContactView.ui.qml" "SectionDelegate.ui.qml" - "contactlist.qml" + "ContactList.qml" "designer/Backend/ContactModel.qml" ) diff --git a/examples/quickcontrols/contactlist/ContactDelegate.ui.qml b/examples/quickcontrols/contactlist/ContactDelegate.ui.qml index 3591b2f3f..e1e6127bb 100644 --- a/examples/quickcontrols/contactlist/ContactDelegate.ui.qml +++ b/examples/quickcontrols/contactlist/ContactDelegate.ui.qml @@ -1,4 +1,4 @@ -// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick @@ -7,14 +7,18 @@ import QtQuick.Controls ItemDelegate { id: delegate - checkable: true + required property string fullName + required property string address + required property string city + required property string number + contentItem: ColumnLayout { spacing: 10 Label { - text: fullName + text: delegate.fullName font.bold: true elide: Text.ElideRight Layout.fillWidth: true @@ -34,7 +38,7 @@ ItemDelegate { } Label { - text: address + text: delegate.address font.bold: true elide: Text.ElideRight Layout.fillWidth: true @@ -46,7 +50,7 @@ ItemDelegate { } Label { - text: city + text: delegate.city font.bold: true elide: Text.ElideRight Layout.fillWidth: true @@ -58,7 +62,7 @@ ItemDelegate { } Label { - text: number + text: delegate.number font.bold: true elide: Text.ElideRight Layout.fillWidth: true @@ -74,6 +78,7 @@ ItemDelegate { PropertyChanges { // TODO: When Qt Design Studio supports generalized grouped properties, change to: // grid.visible: true + // qmllint disable Quick.property-changes-parsed target: grid visible: true } diff --git a/examples/quickcontrols/contactlist/ContactDialog.qml b/examples/quickcontrols/contactlist/ContactDialog.qml index 9bb990f2a..3f287447e 100644 --- a/examples/quickcontrols/contactlist/ContactDialog.qml +++ b/examples/quickcontrols/contactlist/ContactDialog.qml @@ -1,4 +1,4 @@ -// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick @@ -41,5 +41,9 @@ Dialog { id: form } - onAccepted: finished(form.fullName.text, form.address.text, form.city.text, form.number.text) + onAccepted: { + if (form.fullName.text && form.address.text && form.city.text && form.number.text) { + finished(form.fullName.text, form.address.text, form.city.text, form.number.text); + } + } } diff --git a/examples/quickcontrols/contactlist/ContactForm.ui.qml b/examples/quickcontrols/contactlist/ContactForm.ui.qml index 918da57f3..56c918619 100644 --- a/examples/quickcontrols/contactlist/ContactForm.ui.qml +++ b/examples/quickcontrols/contactlist/ContactForm.ui.qml @@ -1,4 +1,4 @@ -// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick diff --git a/examples/quickcontrols/contactlist/contactlist.qml b/examples/quickcontrols/contactlist/ContactList.qml similarity index 72% rename from examples/quickcontrols/contactlist/contactlist.qml rename to examples/quickcontrols/contactlist/ContactList.qml index 28f887f2d..121b38f35 100644 --- a/examples/quickcontrols/contactlist/contactlist.qml +++ b/examples/quickcontrols/contactlist/ContactList.qml @@ -1,4 +1,4 @@ -// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick @@ -17,10 +17,10 @@ ApplicationWindow { ContactDialog { id: contactDialog onFinished: function(fullName, address, city, number) { - if (currentContact === -1) + if (window.currentContact === -1) contactView.model.append(fullName, address, city, number) else - contactView.model.set(currentContact, fullName, address, city, number) + contactView.model.set(window.currentContact, fullName, address, city, number) } } @@ -35,23 +35,23 @@ ApplicationWindow { font.bold: true width: parent.width horizontalAlignment: Qt.AlignHCenter - text: currentContact >= 0 ? contactView.model.get(currentContact).fullName : "" + text: window.currentContact >= 0 ? contactView.model.get(window.currentContact).fullName : "" } MenuItem { text: qsTr("Edit...") - onTriggered: contactDialog.editContact(contactView.model.get(currentContact)) + onTriggered: contactDialog.editContact(contactView.model.get(window.currentContact)) } MenuItem { text: qsTr("Remove") - onTriggered: contactView.model.remove(currentContact) + onTriggered: contactView.model.remove(window.currentContact) } } ContactView { id: contactView anchors.fill: parent - onPressAndHold: { - currentContact = index + onPressAndHold: function(index) { + window.currentContact = index contactMenu.open() } } @@ -63,7 +63,7 @@ ApplicationWindow { anchors.right: parent.right anchors.bottom: parent.bottom onClicked: { - currentContact = -1 + window.currentContact = -1 contactDialog.createContact() } } diff --git a/examples/quickcontrols/contactlist/ContactView.ui.qml b/examples/quickcontrols/contactlist/ContactView.ui.qml index 6e80d05ba..7d5b3cf6c 100644 --- a/examples/quickcontrols/contactlist/ContactView.ui.qml +++ b/examples/quickcontrols/contactlist/ContactView.ui.qml @@ -1,9 +1,11 @@ -// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +pragma ComponentBehavior: Bound + import QtQuick import QtQuick.Controls -import Backend +import contactlist ListView { id: listView @@ -25,6 +27,9 @@ ListView { delegate: ContactDelegate { id: delegate width: listView.width + + required property int index + onPressAndHold: listView.pressAndHold(index) } diff --git a/examples/quickcontrols/contactlist/SectionDelegate.ui.qml b/examples/quickcontrols/contactlist/SectionDelegate.ui.qml index 05b214728..1ed587abd 100644 --- a/examples/quickcontrols/contactlist/SectionDelegate.ui.qml +++ b/examples/quickcontrols/contactlist/SectionDelegate.ui.qml @@ -1,4 +1,4 @@ -// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick @@ -7,9 +7,11 @@ import QtQuick.Controls ToolBar { id: background + required property string section + Label { id: label - text: section + text: background.section anchors.fill: parent horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter diff --git a/examples/quickcontrols/contactlist/contactlist.pro b/examples/quickcontrols/contactlist/contactlist.pro index ceb99cbc4..2fead8318 100644 --- a/examples/quickcontrols/contactlist/contactlist.pro +++ b/examples/quickcontrols/contactlist/contactlist.pro @@ -2,6 +2,12 @@ TEMPLATE = app TARGET = contactlist QT += quick +CONFIG += qmltypes + +QML_IMPORT_PATH = $$pwd/. +QML_IMPORT_NAME = contactlist +QML_IMPORT_MAJOR_VERSION = 1 + HEADERS += \ contactmodel.h @@ -9,15 +15,20 @@ SOURCES += \ main.cpp \ contactmodel.cpp -RESOURCES += \ +qml_resources.files = \ + qmldir \ ContactDelegate.ui.qml \ ContactDialog.qml \ ContactForm.ui.qml \ - contactlist.qml \ + ContactList.qml \ ContactView.ui.qml \ designer/Backend/ContactModel.qml \ SectionDelegate.ui.qml +qml_resources.prefix = /qt/qml/contactlist + +RESOURCES += qml_resources + # Additional import path used to resolve QML modules just for Qt Quick Designer QML_DESIGNER_IMPORT_PATH = $$PWD/designer diff --git a/examples/quickcontrols/contactlist/contactmodel.cpp b/examples/quickcontrols/contactlist/contactmodel.cpp index 1add2e777..85ebad051 100644 --- a/examples/quickcontrols/contactlist/contactmodel.cpp +++ b/examples/quickcontrols/contactlist/contactmodel.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "contactmodel.h" diff --git a/examples/quickcontrols/contactlist/contactmodel.h b/examples/quickcontrols/contactlist/contactmodel.h index 564ec0fab..78a06b813 100644 --- a/examples/quickcontrols/contactlist/contactmodel.h +++ b/examples/quickcontrols/contactlist/contactmodel.h @@ -1,14 +1,16 @@ -// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #ifndef CONTACTMODEL_H #define CONTACTMODEL_H #include +#include class ContactModel : public QAbstractListModel { Q_OBJECT + QML_ELEMENT public: enum ContactRole { diff --git a/examples/quickcontrols/contactlist/designer/Backend/ContactModel.qml b/examples/quickcontrols/contactlist/designer/Backend/ContactModel.qml index c7a3f4817..850b444d0 100644 --- a/examples/quickcontrols/contactlist/designer/Backend/ContactModel.qml +++ b/examples/quickcontrols/contactlist/designer/Backend/ContactModel.qml @@ -1,4 +1,4 @@ -// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick diff --git a/examples/quickcontrols/contactlist/main.cpp b/examples/quickcontrols/contactlist/main.cpp index 32a88def4..2f9f15fd3 100644 --- a/examples/quickcontrols/contactlist/main.cpp +++ b/examples/quickcontrols/contactlist/main.cpp @@ -1,19 +1,15 @@ -// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include #include -#include "contactmodel.h" - int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); - qmlRegisterType("Backend", 1, 0, "ContactModel"); - QQmlApplicationEngine engine; - engine.load(QUrl(QStringLiteral("qrc:/contactlist.qml"))); + engine.loadFromModule("contactlist", "ContactList"); return app.exec(); } diff --git a/examples/quickcontrols/contactlist/qmldir b/examples/quickcontrols/contactlist/qmldir new file mode 100644 index 000000000..2d0af6824 --- /dev/null +++ b/examples/quickcontrols/contactlist/qmldir @@ -0,0 +1,8 @@ +module contactlist + +ContactDelegate 1.0 ContactDelegate.ui.qml +ContactDialog 1.0 ContactDialog.qml +ContactForm 1.0 ContactForm.ui.qml +ContactList 1.0 ContactList.qml +ContactView 1.0 ContactView.ui.qml +SectionDelegate 1.0 SectionDelegate.ui.qml diff --git a/examples/quickcontrols/filesystemexplorer/CMakeLists.txt b/examples/quickcontrols/filesystemexplorer/CMakeLists.txt index 53eeb7b4e..4a676d28d 100644 --- a/examples/quickcontrols/filesystemexplorer/CMakeLists.txt +++ b/examples/quickcontrols/filesystemexplorer/CMakeLists.txt @@ -4,6 +4,11 @@ cmake_minimum_required(VERSION 3.16) project(filesystemexplorer LANGUAGES CXX) +if (ANDROID OR IOS) + message(FATAL_ERROR "Platform is not supported") + return() +endif () + if (NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") endif () diff --git a/examples/quickcontrols/filesystemexplorer/doc/src/qtquickcontrols-filesystemexplorer.qdoc b/examples/quickcontrols/filesystemexplorer/doc/src/qtquickcontrols-filesystemexplorer.qdoc index 8c950a67c..686c2ab48 100644 --- a/examples/quickcontrols/filesystemexplorer/doc/src/qtquickcontrols-filesystemexplorer.qdoc +++ b/examples/quickcontrols/filesystemexplorer/doc/src/qtquickcontrols-filesystemexplorer.qdoc @@ -6,8 +6,8 @@ \meta tags {quickcontrols, layout, styling, treeview} \title File System Explorer \ingroup qtquickcontrols-examples - \brief A QML app utilizing customized Qt Quick Controls to display text - files from a filesystem. + \brief A desktop QML app utilizing customized Qt Quick Controls to display + text files from a filesystem. In this example, a modern layout is used that consists of three major components. There is an icon-based \e {Sidebar} to the left, followed by a diff --git a/examples/quickcontrols/filesystemexplorer/filesystemexplorer.pro b/examples/quickcontrols/filesystemexplorer/filesystemexplorer.pro index 3748d9577..817c03c0d 100644 --- a/examples/quickcontrols/filesystemexplorer/filesystemexplorer.pro +++ b/examples/quickcontrols/filesystemexplorer/filesystemexplorer.pro @@ -1,6 +1,10 @@ # Copyright (C) 2023 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause +android|ios { + error( "Platform not supported" ) +} + QT += quick CONFIG += qmltypes diff --git a/examples/quickcontrols/imagine/automotive/qtquickcontrols2.conf b/examples/quickcontrols/imagine/automotive/qtquickcontrols2.conf index c7fc7a616..94601428d 100644 --- a/examples/quickcontrols/imagine/automotive/qtquickcontrols2.conf +++ b/examples/quickcontrols/imagine/automotive/qtquickcontrols2.conf @@ -3,8 +3,6 @@ Style=Imagine [Imagine] Path=:/imagine-assets - -[Imagine\Palette] -Text=#6affcd -ButtonText=#6affcd -WindowText=#6affcd +Palette\Text=#6affcd +Palette\ButtonText=#6affcd +Palette\WindowText=#6affcd diff --git a/examples/quickcontrols/quickcontrols.pro b/examples/quickcontrols/quickcontrols.pro index 44644e9ba..7baf73121 100644 --- a/examples/quickcontrols/quickcontrols.pro +++ b/examples/quickcontrols/quickcontrols.pro @@ -5,8 +5,11 @@ SUBDIRS += \ texteditor \ contactlist \ wearable \ - filesystemexplorer \ imagine/automotive +win32|macos|unix { + qtHaveModule(svg): SUBDIRS += filesystemexplorer +} + qtHaveModule(sql): SUBDIRS += eventcalendar qtHaveModule(widgets): SUBDIRS += flatstyle diff --git a/examples/quickcontrols/wearable/CMakeLists.txt b/examples/quickcontrols/wearable/CMakeLists.txt index c293d64ef..eccbea20a 100644 --- a/examples/quickcontrols/wearable/CMakeLists.txt +++ b/examples/quickcontrols/wearable/CMakeLists.txt @@ -54,6 +54,6 @@ install(TARGETS wearableexample include(../../quick/shared/QtBundleQmlModuleForMacOS.cmake) set(app_target "wearableexample") -add_qml_module_to_macos_app_bundle("${app_target}" "wearable" "Wearable") -add_qml_module_to_macos_app_bundle("${app_target}" "wearablesettings" "WearableSettings") -add_qml_module_to_macos_app_bundle("${app_target}" "wearablestyle" "WearableStyle") +add_qml_module_to_macos_app_bundle("${app_target}" "wearable") +add_qml_module_to_macos_app_bundle("${app_target}" "wearablesettings") +add_qml_module_to_macos_app_bundle("${app_target}" "wearablestyle") diff --git a/examples/quickcontrols/wearable/Wearable/Main.qml b/examples/quickcontrols/wearable/Wearable/Main.qml index bc6e36112..ae9d800dc 100644 --- a/examples/quickcontrols/wearable/Wearable/Main.qml +++ b/examples/quickcontrols/wearable/Wearable/Main.qml @@ -17,6 +17,8 @@ QQC2.ApplicationWindow { background: Image { source: UIStyle.themeImagePath("background") + width : parent.width + height : parent.height } header: NaviButton { diff --git a/src/3rdparty/masm/WeakRandom.h b/src/3rdparty/masm/WeakRandom.h index 924bac00c..435f5861f 100644 --- a/src/3rdparty/masm/WeakRandom.h +++ b/src/3rdparty/masm/WeakRandom.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef MASM_WEAKRANDOM_H #define MASM_WEAKRANDOM_H diff --git a/src/3rdparty/masm/config.h b/src/3rdparty/masm/config.h index 72035f6a6..f765c0525 100644 --- a/src/3rdparty/masm/config.h +++ b/src/3rdparty/masm/config.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef MASM_CONFIG_H #define MASM_CONFIG_H diff --git a/src/3rdparty/masm/qt_attribution.json b/src/3rdparty/masm/qt_attribution.json index aab413ad4..77b144d73 100644 --- a/src/3rdparty/masm/qt_attribution.json +++ b/src/3rdparty/masm/qt_attribution.json @@ -8,17 +8,17 @@ "License": "BSD 2-clause \"Simplified\" License", "LicenseId": "BSD-2-Clause", "LicenseFile": "LICENSE", - "Copyright": "Copyright (C) 2003-2018 Apple Inc. All rights reserved. -Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) -Copyright (C) 2007-2009 Torch Mobile, Inc. All rights reserved. (http://www.torchmobile.com/) -Copyright (C) 2009, 2010 University of Szeged -Copyright (C) 2009-2011 STMicroelectronics. All rights reserved. -Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved. -Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged -Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved. -Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved. -Copyright (C) 2011 Google Inc. All rights reserved. -Copyright (C) 2013 Samsung Electronics. All rights reserved. -Copyright (C) 2015 Cisco Systems, Inc. All rights reserved. -Copyright (c) 2002-2009 Vivek Thampi" + "Copyright": ["Copyright (C) 2003-2018 Apple Inc. All rights reserved.", + "Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)", + "Copyright (C) 2007-2009 Torch Mobile, Inc. All rights reserved. (http://www.torchmobile.com/)", + "Copyright (C) 2009, 2010 University of Szeged", + "Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.", + "Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved.", + "Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged", + "Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved.", + "Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved.", + "Copyright (C) 2011 Google Inc. All rights reserved.", + "Copyright (C) 2013 Samsung Electronics. All rights reserved.", + "Copyright (C) 2015 Cisco Systems, Inc. All rights reserved.", + "Copyright (c) 2002-2009 Vivek Thampi"] } diff --git a/src/3rdparty/masm/stubs/ExecutableAllocator.h b/src/3rdparty/masm/stubs/ExecutableAllocator.h index 9ab19871c..876a12fce 100644 --- a/src/3rdparty/masm/stubs/ExecutableAllocator.h +++ b/src/3rdparty/masm/stubs/ExecutableAllocator.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef MASM_EXECUTABLEALLOCATOR_H #define MASM_EXECUTABLEALLOCATOR_H diff --git a/src/3rdparty/masm/stubs/JSGlobalData.h b/src/3rdparty/masm/stubs/JSGlobalData.h index 14c238acf..22b597d36 100644 --- a/src/3rdparty/masm/stubs/JSGlobalData.h +++ b/src/3rdparty/masm/stubs/JSGlobalData.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef MASM_JSGLOBALDATA_H #define MASM_JSGLOBALDATA_H diff --git a/src/3rdparty/masm/stubs/Options.cpp b/src/3rdparty/masm/stubs/Options.cpp index 6689aca38..639e0655d 100644 --- a/src/3rdparty/masm/stubs/Options.cpp +++ b/src/3rdparty/masm/stubs/Options.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "config.h" #include "Options.h" diff --git a/src/3rdparty/masm/stubs/Options.h b/src/3rdparty/masm/stubs/Options.h index 6339c0603..0f742fb6d 100644 --- a/src/3rdparty/masm/stubs/Options.h +++ b/src/3rdparty/masm/stubs/Options.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef OPTIONS_H #define OPTIONS_H diff --git a/src/3rdparty/masm/stubs/SuperSampler.h b/src/3rdparty/masm/stubs/SuperSampler.h index 422de528e..95d1739be 100644 --- a/src/3rdparty/masm/stubs/SuperSampler.h +++ b/src/3rdparty/masm/stubs/SuperSampler.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #pragma once diff --git a/src/3rdparty/masm/stubs/WTFStubs.cpp b/src/3rdparty/masm/stubs/WTFStubs.cpp index facba7d93..f876cda03 100644 --- a/src/3rdparty/masm/stubs/WTFStubs.cpp +++ b/src/3rdparty/masm/stubs/WTFStubs.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include #include #include diff --git a/src/3rdparty/masm/stubs/WTFStubs.h b/src/3rdparty/masm/stubs/WTFStubs.h index 91b883855..81f850dc1 100644 --- a/src/3rdparty/masm/stubs/WTFStubs.h +++ b/src/3rdparty/masm/stubs/WTFStubs.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef WTFSTUBS_H #define WTFSTUBS_H diff --git a/src/3rdparty/masm/stubs/runtime/ConcurrentJSLock.h b/src/3rdparty/masm/stubs/runtime/ConcurrentJSLock.h index 43868fead..206916e82 100644 --- a/src/3rdparty/masm/stubs/runtime/ConcurrentJSLock.h +++ b/src/3rdparty/masm/stubs/runtime/ConcurrentJSLock.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #pragma once diff --git a/src/3rdparty/masm/stubs/runtime/VM.h b/src/3rdparty/masm/stubs/runtime/VM.h index 94cce814f..e00ee543e 100644 --- a/src/3rdparty/masm/stubs/runtime/VM.h +++ b/src/3rdparty/masm/stubs/runtime/VM.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef MASM_VM_H #define MASM_VM_H diff --git a/src/3rdparty/masm/stubs/wtf/FastAllocBase.h b/src/3rdparty/masm/stubs/wtf/FastAllocBase.h index c7f99a30a..c8b468092 100644 --- a/src/3rdparty/masm/stubs/wtf/FastAllocBase.h +++ b/src/3rdparty/masm/stubs/wtf/FastAllocBase.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef FASTALLOCBASE_H #define FASTALLOCBASE_H diff --git a/src/3rdparty/masm/stubs/wtf/FastMalloc.h b/src/3rdparty/masm/stubs/wtf/FastMalloc.h index 7d6f86b32..f94a7b384 100644 --- a/src/3rdparty/masm/stubs/wtf/FastMalloc.h +++ b/src/3rdparty/masm/stubs/wtf/FastMalloc.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef FASTMALLOC_H #define FASTMALLOC_H diff --git a/src/3rdparty/masm/stubs/wtf/HashMap.h b/src/3rdparty/masm/stubs/wtf/HashMap.h index 888c6cceb..3f257412b 100644 --- a/src/3rdparty/masm/stubs/wtf/HashMap.h +++ b/src/3rdparty/masm/stubs/wtf/HashMap.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef HASHMAP_H #define HASHMAP_H diff --git a/src/3rdparty/masm/stubs/wtf/HashSet.h b/src/3rdparty/masm/stubs/wtf/HashSet.h index 3765c9a8b..741f448ff 100644 --- a/src/3rdparty/masm/stubs/wtf/HashSet.h +++ b/src/3rdparty/masm/stubs/wtf/HashSet.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef HASHSET_H #define HASHSET_H diff --git a/src/3rdparty/masm/stubs/wtf/Noncopyable.h b/src/3rdparty/masm/stubs/wtf/Noncopyable.h index 2d4de9cd8..d712bd9e7 100644 --- a/src/3rdparty/masm/stubs/wtf/Noncopyable.h +++ b/src/3rdparty/masm/stubs/wtf/Noncopyable.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef NONCOPYABLE_H #define NONCOPYABLE_H diff --git a/src/3rdparty/masm/stubs/wtf/Optional.h b/src/3rdparty/masm/stubs/wtf/Optional.h index c4064476c..3f7f99eb5 100644 --- a/src/3rdparty/masm/stubs/wtf/Optional.h +++ b/src/3rdparty/masm/stubs/wtf/Optional.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #pragma once diff --git a/src/3rdparty/masm/stubs/wtf/OwnPtr.h b/src/3rdparty/masm/stubs/wtf/OwnPtr.h index eee828bb6..980cec41c 100644 --- a/src/3rdparty/masm/stubs/wtf/OwnPtr.h +++ b/src/3rdparty/masm/stubs/wtf/OwnPtr.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef OWNPTR_H #define OWNPTR_H diff --git a/src/3rdparty/masm/stubs/wtf/PassOwnPtr.h b/src/3rdparty/masm/stubs/wtf/PassOwnPtr.h index 0e18132f7..a97990d9c 100644 --- a/src/3rdparty/masm/stubs/wtf/PassOwnPtr.h +++ b/src/3rdparty/masm/stubs/wtf/PassOwnPtr.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef PASSOWNPTR_H #define PASSOWNPTR_H diff --git a/src/3rdparty/masm/stubs/wtf/PassRefPtr.h b/src/3rdparty/masm/stubs/wtf/PassRefPtr.h index cc03a5d65..aec7d6c03 100644 --- a/src/3rdparty/masm/stubs/wtf/PassRefPtr.h +++ b/src/3rdparty/masm/stubs/wtf/PassRefPtr.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef PASSREFPTR_H #define PASSREFPTR_H diff --git a/src/3rdparty/masm/stubs/wtf/RefCounted.h b/src/3rdparty/masm/stubs/wtf/RefCounted.h index 332ef301a..5f62f7229 100644 --- a/src/3rdparty/masm/stubs/wtf/RefCounted.h +++ b/src/3rdparty/masm/stubs/wtf/RefCounted.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef REFCOUNTED_H #define REFCOUNTED_H diff --git a/src/3rdparty/masm/stubs/wtf/RefPtr.h b/src/3rdparty/masm/stubs/wtf/RefPtr.h index e7e918649..14e60ca23 100644 --- a/src/3rdparty/masm/stubs/wtf/RefPtr.h +++ b/src/3rdparty/masm/stubs/wtf/RefPtr.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef REFPTR_H #define REFPTR_H diff --git a/src/3rdparty/masm/stubs/wtf/TypeTraits.h b/src/3rdparty/masm/stubs/wtf/TypeTraits.h index 04c2608a4..c75bb2444 100644 --- a/src/3rdparty/masm/stubs/wtf/TypeTraits.h +++ b/src/3rdparty/masm/stubs/wtf/TypeTraits.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef TYPETRAITS_H #define TYPETRAITS_H diff --git a/src/3rdparty/masm/stubs/wtf/UnusedParam.h b/src/3rdparty/masm/stubs/wtf/UnusedParam.h index 6d80b5a90..4f1156060 100644 --- a/src/3rdparty/masm/stubs/wtf/UnusedParam.h +++ b/src/3rdparty/masm/stubs/wtf/UnusedParam.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef UNUSEDPARAM_H #define UNUSEDPARAM_H diff --git a/src/3rdparty/masm/stubs/wtf/Vector.h b/src/3rdparty/masm/stubs/wtf/Vector.h index cee647a4b..44b7e783c 100644 --- a/src/3rdparty/masm/stubs/wtf/Vector.h +++ b/src/3rdparty/masm/stubs/wtf/Vector.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef VECTOR_H #define VECTOR_H diff --git a/src/3rdparty/masm/stubs/wtf/text/CString.h b/src/3rdparty/masm/stubs/wtf/text/CString.h index 7129f5049..646d3367b 100644 --- a/src/3rdparty/masm/stubs/wtf/text/CString.h +++ b/src/3rdparty/masm/stubs/wtf/text/CString.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef CSTRING_H #define CSTRING_H diff --git a/src/3rdparty/masm/stubs/wtf/text/StringBuilder.h b/src/3rdparty/masm/stubs/wtf/text/StringBuilder.h index a382f6da8..d51c0c7c2 100644 --- a/src/3rdparty/masm/stubs/wtf/text/StringBuilder.h +++ b/src/3rdparty/masm/stubs/wtf/text/StringBuilder.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #pragma once #include diff --git a/src/3rdparty/masm/stubs/wtf/text/WTFString.h b/src/3rdparty/masm/stubs/wtf/text/WTFString.h index da5183f73..17346593f 100644 --- a/src/3rdparty/masm/stubs/wtf/text/WTFString.h +++ b/src/3rdparty/masm/stubs/wtf/text/WTFString.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef WTFSTRING_H #define WTFSTRING_H diff --git a/src/3rdparty/masm/stubs/wtf/unicode/Unicode.h b/src/3rdparty/masm/stubs/wtf/unicode/Unicode.h index 34e331f88..44a7d6557 100644 --- a/src/3rdparty/masm/stubs/wtf/unicode/Unicode.h +++ b/src/3rdparty/masm/stubs/wtf/unicode/Unicode.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef UNICODE_H #define UNICODE_H diff --git a/src/3rdparty/masm/stubs/yarr/YarrUnicodeProperties.cpp b/src/3rdparty/masm/stubs/yarr/YarrUnicodeProperties.cpp index 99c925f40..386536ed0 100644 --- a/src/3rdparty/masm/stubs/yarr/YarrUnicodeProperties.cpp +++ b/src/3rdparty/masm/stubs/yarr/YarrUnicodeProperties.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "config.h" #include "yarr/YarrUnicodeProperties.h" diff --git a/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp b/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp index 27f72073c..ae0f19281 100644 --- a/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp +++ b/src/3rdparty/masm/wtf/OSAllocatorIntegrity.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) Rolland Dudemaine All rights reserved. -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) Rolland Dudemaine All rights reserved. +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "config.h" #include "OSAllocator.h" diff --git a/src/qml/Qt6QmlDeploySupport.cmake b/src/qml/Qt6QmlDeploySupport.cmake index 21922c885..91c47e920 100644 --- a/src/qml/Qt6QmlDeploySupport.cmake +++ b/src/qml/Qt6QmlDeploySupport.cmake @@ -226,6 +226,16 @@ function(_qt_internal_deploy_qml_imports_for_target) endforeach() endif() + # Install runtime dependencies on Windows. + if(__QT_DEPLOY_SYSTEM_NAME STREQUAL "Windows") + foreach(file IN LISTS __QT_DEPLOY_TARGET_${entry_LINKTARGET}_RUNTIME_DLLS) + if(__QT_DEPLOY_VERBOSE) + message(STATUS "runtime dependency for QML plugin '${entry_PLUGIN}':") + endif() + file(INSTALL ${file} DESTINATION "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_BIN_DIR}") + endforeach() + endif() + if(__QT_DEPLOY_TOOL STREQUAL "GRD" AND __QT_DEPLOY_MUST_ADJUST_PLUGINS_RPATH) # The RPATHs of the installed plugins do not match Qt's original lib directory. # We must set the RPATH to point to QT_DEPLOY_LIBDIR. diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake index 52e91861e..eeb59898e 100644 --- a/src/qml/Qt6QmlMacros.cmake +++ b/src/qml/Qt6QmlMacros.cmake @@ -839,36 +839,68 @@ function(_qt_internal_target_enable_qmllint target) _qt_internal_extend_qml_import_paths(import_args) _qt_internal_get_tool_wrapper_script_path(tool_wrapper) - set(cmd - ${tool_wrapper} - $ + + set(qmllint_args --bare ${import_args} ${qrc_args} ${qmllint_files} ) + get_target_property(target_binary_dir ${target} BINARY_DIR) + set(qmllint_dir ${target_binary_dir}/.rcc/qmllint) + set(qmllint_rsp_path ${qmllint_dir}/${target}.rsp) + + file(GENERATE + OUTPUT "${qmllint_rsp_path}" + CONTENT "$\n" + ) + + set(cmd + ${tool_wrapper} + $ + @${qmllint_rsp_path} + ) + + set(cmd_dummy ${CMAKE_COMMAND} -E echo "Nothing to do for target ${lint_target}.") + # We need this target to depend on all qml type registrations. This is the # only way we can be sure that all *.qmltypes files for any QML modules we # depend on will have been generated. add_custom_target(${lint_target} - COMMAND "$<${have_qmllint_files}:${cmd}>" + COMMAND "$" COMMAND_EXPAND_LISTS DEPENDS ${QT_CMAKE_EXPORT_NAMESPACE}::qmllint ${qmllint_files} + ${qmllint_rsp_path} $ WORKING_DIRECTORY "$" ) _qt_internal_assign_to_qmllint_targets_folder(${lint_target}) - set(lint_args "--json" "${CMAKE_BINARY_DIR}/${lint_target}.json") + list(APPEND qmllint_args "--json" "${CMAKE_BINARY_DIR}/${lint_target}.json") + + set(qmllint_rsp_path ${qmllint_dir}/${target}_json.rsp) + + file(GENERATE + OUTPUT "${qmllint_rsp_path}" + CONTENT "$\n" + ) + + set(cmd + ${tool_wrapper} + $ + @${qmllint_rsp_path} + ) + add_custom_target(${lint_target_json} - COMMAND "$<${have_qmllint_files}:${cmd};${lint_args}>" + COMMAND "$<${have_qmllint_files}:${cmd}>" COMMAND_EXPAND_LISTS DEPENDS ${QT_CMAKE_EXPORT_NAMESPACE}::qmllint ${qmllint_files} + ${qmllint_rsp_path} $ WORKING_DIRECTORY "$" ) @@ -879,18 +911,34 @@ function(_qt_internal_target_enable_qmllint target) get_target_property(module_uri ${target} QT_QML_MODULE_URI) _qt_internal_get_tool_wrapper_script_path(tool_wrapper) + + set(qmllint_args + ${import_args} + ${qrc_args} + --module + ${module_uri} + ) + + set(qmllint_rsp_path ${qmllint_dir}/${target}_module.rsp) + + file(GENERATE + OUTPUT "${qmllint_rsp_path}" + CONTENT "$\n" + ) + + set(cmd + ${tool_wrapper} + $ + @${qmllint_rsp_path} + ) + add_custom_target(${lint_target_module} - COMMAND - ${tool_wrapper} - $ - ${import_args} - ${qrc_args} - --module - ${module_uri} + COMMAND ${cmd} COMMAND_EXPAND_LISTS DEPENDS ${QT_CMAKE_EXPORT_NAMESPACE}::qmllint ${qmllint_files} + ${qmllint_rsp_path} $ WORKING_DIRECTORY "$" ) @@ -900,32 +948,12 @@ function(_qt_internal_target_enable_qmllint target) # Note that the caller is free to change the value of QT_QMLLINT_ALL_TARGET # for different QML modules if they wish, which means they can implement # their own grouping of the ${target}_qmllint targets. - if("${QT_QMLLINT_ALL_TARGET}" STREQUAL "") - set(QT_QMLLINT_ALL_TARGET all_qmllint) - endif() - if(NOT TARGET ${QT_QMLLINT_ALL_TARGET}) - add_custom_target(${QT_QMLLINT_ALL_TARGET}) - endif() - add_dependencies(${QT_QMLLINT_ALL_TARGET} ${lint_target}) - - if("${QT_QMLLINT_JSON_ALL_TARGET}" STREQUAL "") - set(QT_QMLLINT_JSON_ALL_TARGET all_qmllint_json) - endif() - if(NOT TARGET ${QT_QMLLINT_JSON_ALL_TARGET}) - add_custom_target(${QT_QMLLINT_JSON_ALL_TARGET}) - _qt_internal_assign_to_qmllint_targets_folder(${QT_QMLLINT_JSON_ALL_TARGET}) - endif() - add_dependencies(${QT_QMLLINT_JSON_ALL_TARGET} ${lint_target_json}) - - if("${QT_QMLLINT_MODULE_ALL_TARGET}" STREQUAL "") - set(QT_QMLLINT_MODULE_ALL_TARGET all_qmllint_module) - endif() - if(NOT TARGET ${QT_QMLLINT_MODULE_ALL_TARGET}) - add_custom_target(${QT_QMLLINT_MODULE_ALL_TARGET}) - _qt_internal_assign_to_qmllint_targets_folder(${QT_QMLLINT_MODULE_ALL_TARGET}) - endif() - add_dependencies(${QT_QMLLINT_MODULE_ALL_TARGET} ${lint_target_module}) - + _qt_internal_add_all_qmllint_target(QT_QMLLINT_ALL_TARGET + all_qmllint ${lint_target}) + _qt_internal_add_all_qmllint_target(QT_QMLLINT_JSON_ALL_TARGET + all_qmllint_json ${lint_target_json}) + _qt_internal_add_all_qmllint_target(QT_QMLLINT_MODULE_ALL_TARGET + all_qmllint_module ${lint_target_module}) endfunction() # This is a modified version of __qt_propagate_generated_resource from qtbase. @@ -977,6 +1005,62 @@ function(_qt_internal_propagate_qmlcache_object_lib set(${output_generated_target} "${resource_target}" PARENT_SCOPE) endfunction() +# Create an 'all_qmllint' target. The target's name can be user-controlled by ${target_var} with the +# default name ${default_target_name}. The parameter ${lint_target} holds the name of the single +# foo_qmllint target that should be triggered by the all_qmllint target. +function(_qt_internal_add_all_qmllint_target target_var default_target_name lint_target) + set(target_name "${${target_var}}") + if("${target_name}" STREQUAL "") + set(target_name ${default_target_name}) + endif() + if(CMAKE_GENERATOR MATCHES "^Visual Studio ") + # For the Visual Studio generators we cannot use add_dependencies, because this would enable + # ${lint_target} in the default build of the solution. See QTBUG-115166 and upstream CMake + # issue #16668 for details. Instead, we record ${lint_target} and create an all_qmllint + # target at the end of the top-level directory scope. + if(${CMAKE_VERSION} VERSION_LESS "3.19.0") + if(NOT QT_NO_QMLLINT_CREATION_WARNING) + message(WARNING "Cannot create target ${target_name} with this CMake version. " + "Please upgrade to CMake 3.19.0 or newer. " + "Set QT_NO_QMLLINT_CREATION_WARNING to ON to disable this warning." + ) + endif() + return() + endif() + set(property_name _qt_target_${target_name}_dependencies) + get_property(recorded_targets GLOBAL PROPERTY ${property_name}) + if("${recorded_targets}" STREQUAL "") + cmake_language(EVAL CODE + "cmake_language(DEFER DIRECTORY \"${CMAKE_SOURCE_DIR}\" CALL _qt_internal_add_all_qmllint_target_deferred \"${target_name}\")" + ) + endif() + set_property(GLOBAL APPEND PROPERTY ${property_name} ${lint_target}) + + # Exclude ${lint_target} from the solution's default build to avoid it being enabled should + # the user add a dependency to it. + set_property(TARGET ${lint_target} PROPERTY EXCLUDE_FROM_DEFAULT_BUILD ON) + else() + if(NOT TARGET ${target_name}) + add_custom_target(${target_name}) + _qt_internal_assign_to_qmllint_targets_folder(${target_name}) + endif() + add_dependencies(${target_name} ${lint_target}) + endif() +endfunction() + +# Hack for the Visual Studio generator. Create the all_qmllint target named ${target} and work +# around the lack of a working add_dependencies by calling 'cmake --build' for every dependency. +function(_qt_internal_add_all_qmllint_target_deferred target) + get_property(target_dependencies GLOBAL PROPERTY _qt_target_${target}_dependencies) + set(target_commands "") + foreach(dependency IN LISTS target_dependencies) + list(APPEND target_commands + COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" -t ${dependency} + ) + endforeach() + add_custom_target(${target} ${target_commands}) + _qt_internal_assign_to_qmllint_targets_folder(${target}) +endfunction() function(_qt_internal_target_enable_qmlcachegen target output_targets_var qmlcachegen) set(output_targets) @@ -1311,7 +1395,9 @@ function(_qt_internal_target_enable_qmltc target) endif() if(arg_EXPORT_MACRO_NAME) list(APPEND common_args --export "${arg_EXPORT_MACRO_NAME}") - list(APPEND common_args --exportInclude "${arg_EXPORT_FILE_NAME}") + if(arg_EXPORT_FILE_NAME) + list(APPEND common_args --exportInclude "${arg_EXPORT_FILE_NAME}") + endif() endif() get_target_property(output_dir ${target} QT_QML_MODULE_OUTPUT_DIRECTORY) @@ -1531,6 +1617,35 @@ if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS) endfunction() endif() +function(_qt_internal_set_qml_target_multi_config_output_directory target output_directory) + # In multi-config builds we need to make sure that at least one configuration has the dynamic + # plugin that is located next to qmldir file, otherwise QML engine won't be able to load the + # plugin. + get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG) + if(is_multi_config) + # We don't care about static plugins here since, they are linked at build time and + # their location doesn't affect the runtime. + get_target_property(target_type ${target} TYPE) + if(target_type STREQUAL "SHARED_LIBRARY" OR target_type STREQUAL "MODULE_LIBRARY") + if(NOT "${output_directory}") + set(output_directory "${CMAKE_CURRENT_BINARY_DIR}") + endif() + + list(GET CMAKE_CONFIGURATION_TYPES 0 default_config) + string(JOIN "" output_directory_with_default_config + "$," + "${output_directory}," + "${output_directory}/$" + ">" + ) + set_target_properties(${target} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${output_directory_with_default_config}" + LIBRARY_OUTPUT_DIRECTORY "${output_directory_with_default_config}" + ) + endif() + endif() +endfunction() + function(qt6_add_qml_plugin target) set(args_option STATIC @@ -1776,6 +1891,8 @@ function(qt6_add_qml_plugin target) ) endif() + _qt_internal_set_qml_target_multi_config_output_directory(${target} "${arg_OUTPUT_DIRECTORY}") + if(NOT arg_NO_GENERATE_PLUGIN_SOURCE) set(generated_cpp_file_name_base "${target}_${arg_CLASS_NAME}") set(register_types_function_name "qml_register_types_${escaped_uri}") @@ -1872,8 +1989,9 @@ function(qt6_target_qml_sources target) message(FATAL_ERROR "Unknown/unexpected arguments: ${arg_UNPARSED_ARGUMENTS}") endif() - if (NOT arg_QML_FILES AND NOT arg_RESOURCES) - if(NOT arg_NO_LINT) + get_target_property(no_lint ${target} QT_QML_MODULE_NO_LINT) + if(NOT arg_QML_FILES AND NOT arg_RESOURCES) + if(NOT arg_NO_LINT AND NOT no_lint) _qt_internal_target_enable_qmllint(${target}) endif() @@ -1892,7 +2010,6 @@ function(qt6_target_qml_sources target) ) endif() - get_target_property(no_lint ${target} QT_QML_MODULE_NO_LINT) get_target_property(no_cachegen ${target} QT_QML_MODULE_NO_CACHEGEN) get_target_property(no_qmldir ${target} QT_QML_MODULE_NO_GENERATE_QMLDIR) get_target_property(resource_prefix ${target} QT_QML_MODULE_RESOURCE_PREFIX) diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc index 1701d2766..6fa22541d 100644 --- a/src/qml/doc/src/cppintegration/definetypes.qdoc +++ b/src/qml/doc/src/cppintegration/definetypes.qdoc @@ -166,7 +166,7 @@ Message { \section2 Registering Value Types Any type with a \l{Q_GADGET} macro can the registered as a -\l{qtqml-typesystem-valuetypes.html}{QML value type}}. Once such a type is +\l{qtqml-typesystem-valuetypes.html}{QML value type}. Once such a type is registered with the QML type system it can be used as property type in QML code. Such an instance can be manipulated from QML; as \l{qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++ diff --git a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc index f7205f14e..7bcb1a5c8 100644 --- a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc +++ b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc @@ -20,18 +20,19 @@ particular, you may be interested in the sub-topics \l{qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++ Classes to QML} and \l {qtqml-cppintegration-definetypes.html}{Defining QML Types from C++}. -\section1 Running the Tutorial Examples +\section1 Opening the Tutorial Sources -The code in this tutorial is available as an example project with subprojects -associated with each tutorial chapter. In \l{Qt Creator Manual}{Qt Creator}, open -the \uicontrol Welcome mode and select the tutorial from \uicontrol Examples. In -\uicontrol Edit mode, expand the \e extending-qml project, right-click on the -subproject (chapter) you want to run and select \uicontrol Run. +The code in this tutorial is available as part of the Qt sources. +If you installed Qt with the \QOI, you can +find the sources in the Qt installation directory under +Examples/Qt-\QtVersion/qml/tutorials/extending-qml/. -\section1 Creating Tutorial Project +\section1 Creating Project from Scratch -We create a new project using the \e {Qt Quick Application} template in Qt Creator, -as instructed in \l {Qt Creator: Creating Qt Quick Projects}. +Alternatively, you can follow the tutorial by creating the sources from scratch: +For each chapter, create a new project using the \e {Qt Quick Application} template +in Qt Creator, as instructed in \l {Qt Creator: Creating Qt Quick Projects}. +Then follow along by adapting and extending the generated skeleton code. \section1 Chapter 1: Creating a New Type \c extending-qml/chapter1-basics @@ -54,7 +55,7 @@ a version of 1.0. We want this \c PieChart type to be usable from QML like this: \qml - import Charts 1.0 + import Charts PieChart { width: 100; height: 100 diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc index 070e3403f..9e5b197cb 100644 --- a/src/qml/doc/src/qmlfunctions.qdoc +++ b/src/qml/doc/src/qmlfunctions.qdoc @@ -528,7 +528,7 @@ \l QML_INTERFACE, \l QML_UNCREATABLE(), \l QML_SINGLETON, \l QML_ADDED_IN_VERSION(), \l QML_REMOVED_IN_VERSION(), \l QML_ADDED_IN_MINOR_VERSION(), \l QML_REMOVED_IN_MINOR_VERSION(), - \l QML_ATTACHED(), \l QML_EXTENDED(), or \l QML_EXTENDED_NAMESPACE() macros + \l QML_EXTENDED(), or \l QML_EXTENDED_NAMESPACE() macros in the enclosing C++ type do not apply to the enclosing type but instead to \a FOREIGN_TYPE. The enclosing type still needs to be registered with the \l {The Meta-Object System}{meta object system} using a \l Q_GADGET or @@ -542,6 +542,9 @@ the element will be named like the struct it is contained in, not the foreign type. See the \l {Extension Objects} for an example. + \note QML_ATTACHED() can currently not be redirected like this. It has to be + specificed in the same type that implements qmlAttachedProperties(). + \include {qualified-class-name.qdocinc} {class name must be qualified} \sa QML_ELEMENT, QML_NAMED_ELEMENT(), QML_FOREIGN_NAMESPACE() diff --git a/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc b/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc index d4089df90..7547287de 100644 --- a/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc +++ b/src/qml/doc/src/qmllanguageref/documents/definetypes.qdoc @@ -254,13 +254,23 @@ The same declaration can also be given for C++-defined types. See \section2 ComponentBehavior -With this pragma you can restrict components defined in this file to only -create objects within their original context. This holds for inline -components as well as Component elements explicitly or implicitly created -as properties. If a component is bound to its context, you can safely -use IDs from the rest of the file within the component. Otherwise, the -engine and the QML tooling cannot know in advance what type, if any, such -IDs will resolve to at run time. +You may have multiple components defined in the same QML file. The root +scope of the QML file is a component, and you may additionally have +elements of type \l QQmlComponent, explicitly or implicitly created +as properties, or inline components. Those components are nested. Each +of the inner components is within one specific outer component. Most of +the time, IDs defined in an outer component are accessible within all +its nested inner components. You can, however, create elements from a +component in any a different context, with different IDs available. +Doing so breaks the assumption that outer IDs are available. Therefore, +the engine and the QML tooling cannot generally know in advance what +type, if any, such IDs will resolve to at run time. + +With the ComponentBehavior pragma you can restrict all inner components +defined in a file to only create objects within their original context. +If a component is bound to its context, you can safely use IDs from +outer components in the same file within the component. QML tooling will +then assume the outer IDs with their specific types to be available. In order to bind the components to their context specify the \c{Bound} argument: @@ -269,8 +279,33 @@ argument: pragma ComponentBehavior: Bound \endqml -The default is \c{Unbound}. You can also specify it explicitly. In a -future version of Qt the default will change to \c{Bound}. +This implies that, in case of name clashes, IDs defined outside a bound +component override local properties of objects created from the +component. Otherwise it wouldn't actually be safe to use the IDs since +later versions of a module might add more properties to the component. +If the component is not bound, local properties override IDs defined +outside the component, but not IDs defined inside the component. + +The example below prints the \e r property of the ListView object with +the id \e color, not the \e r property of the rectangle's color. + +\qml +pragma ComponentBehavior: Bound +import QtQuick + +ListView { + id: color + property int r: 12 + model: 1 + delegate: Rectangle { + Component.onCompleted: console.log(color.r) + } +} +\endqml + +The default value of \c ComponentBehavior is \c{Unbound}. You can also +specify it explicitly. In a future version of Qt the default will change +to \c{Bound}. Delegate components bound to their context don't receive their own private contexts on instantiation. This means that model data can only diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc index 4d52842e4..36d1db4c4 100644 --- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc +++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc @@ -807,7 +807,7 @@ In order to be consistent with method declarations, you should prefer the type declarations using colons. If the signal has no parameters, the "()" brackets are optional. If parameters -are used, the parameter types must be declared, as for the \c string and \c var +are used, the parameter types must be declared, as for the \c string and \c int arguments for the \c actionPerformed signal above. The allowed parameter types are the same as those listed under \l {Defining Property Attributes} on this page. diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index dd3bb9800..f622c3fb2 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -372,8 +372,11 @@ bool QJSValue::isError() const } /*! - Returns true if this QJSValue is an object of the URL class; + Returns true if this QJSValue is an object of the URL JavaScript class; otherwise returns false. + + \note For a QJSValue that contains a QUrl, this function returns false. + However, \c{toVariant().value()} works in both cases. */ bool QJSValue::isUrl() const { @@ -635,8 +638,11 @@ QVariant QJSValue::toVariant(QJSValue::ObjectConversionBehavior behavior) const if (val.isString()) return QVariant(val.toQString()); if (val.as()) { - return QV4::ExecutionEngine::toVariant( - val, /*typeHint*/ QMetaType{}, behavior == RetainJSObjects); + if (behavior == RetainJSObjects) + return QV4::ExecutionEngine::toVariant( + val, /*typeHint*/ QMetaType{}, /*createJSValueForObjectsAndSymbols=*/ true); + else + return QV4::ExecutionEngine::toVariantLossy(val); } Q_ASSERT(false); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 8efc3c89f..f88753fbc 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1478,11 +1478,13 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError() // Variant conversion code typedef QSet V4ObjectSet; +enum class JSToQVariantConversionBehavior {Never, Safish, Aggressive }; static QVariant toVariant( - const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols, + const QV4::Value &value, QMetaType typeHint, JSToQVariantConversionBehavior conversionBehavior, V4ObjectSet *visitedObjects); static QObject *qtObjectFromJS(const QV4::Value &value); -static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects = nullptr); +static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects = nullptr, + JSToQVariantConversionBehavior behavior = JSToQVariantConversionBehavior::Safish); static bool convertToNativeQObject(const QV4::Value &value, QMetaType targetType, void **result); static QV4::ReturnedValue variantListToJS(QV4::ExecutionEngine *v4, const QVariantList &lst); static QV4::ReturnedValue sequentialIterableToJS(QV4::ExecutionEngine *v4, const QSequentialIterable &lst); @@ -1492,8 +1494,7 @@ static QV4::ReturnedValue variantToJS(QV4::ExecutionEngine *v4, const QVariant & return v4->metaTypeToJS(value.metaType(), value.constData()); } -static QVariant toVariant( - const QV4::Value &value, QMetaType metaType, bool createJSValueForObjectsAndSymbols, +static QVariant toVariant(const QV4::Value &value, QMetaType metaType, JSToQVariantConversionBehavior conversionBehavior, V4ObjectSet *visitedObjects) { Q_ASSERT (!value.isEmpty()); @@ -1590,7 +1591,7 @@ static QVariant toVariant( } } - asVariant = toVariant(arrayValue, valueMetaType, false, visitedObjects); + asVariant = toVariant(arrayValue, valueMetaType, JSToQVariantConversionBehavior::Never, visitedObjects); if (valueMetaType == QMetaType::fromType()) { retnAsIterable.metaContainer().addValue(retn.data(), &asVariant); } else { @@ -1655,7 +1656,7 @@ static QVariant toVariant( if (const ArrayBuffer *d = value.as()) return d->asByteArray(); if (const Symbol *symbol = value.as()) { - return createJSValueForObjectsAndSymbols + return conversionBehavior == JSToQVariantConversionBehavior::Never ? QVariant::fromValue(QJSValuePrivate::fromReturnedValue(symbol->asReturnedValue())) : symbol->descriptiveString(); } @@ -1676,20 +1677,27 @@ static QVariant toVariant( return result; } - if (createJSValueForObjectsAndSymbols) + if (conversionBehavior == JSToQVariantConversionBehavior::Never) return QVariant::fromValue(QJSValuePrivate::fromReturnedValue(o->asReturnedValue())); - return objectToVariant(o, visitedObjects); + return objectToVariant(o, visitedObjects, conversionBehavior); } +QVariant ExecutionEngine::toVariantLossy(const Value &value) +{ + return ::toVariant(value, QMetaType(), JSToQVariantConversionBehavior::Aggressive, nullptr); +} QVariant ExecutionEngine::toVariant( const Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols) { - return ::toVariant(value, typeHint, createJSValueForObjectsAndSymbols, nullptr); + auto behavior = createJSValueForObjectsAndSymbols ? JSToQVariantConversionBehavior::Never + : JSToQVariantConversionBehavior::Safish; + return ::toVariant(value, typeHint, behavior, nullptr); } -static QVariantMap objectToVariantMap(const QV4::Object *o, V4ObjectSet *visitedObjects) +static QVariantMap objectToVariantMap(const QV4::Object *o, V4ObjectSet *visitedObjects, + JSToQVariantConversionBehavior conversionBehvior) { QVariantMap map; QV4::Scope scope(o->engine()); @@ -1704,12 +1712,13 @@ static QVariantMap objectToVariantMap(const QV4::Object *o, V4ObjectSet *visited QString key = name->toQStringNoThrow(); map.insert(key, ::toVariant( val, /*type hint*/ QMetaType {}, - /*createJSValueForObjectsAndSymbols*/false, visitedObjects)); + conversionBehvior, visitedObjects)); } return map; } -static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects) +static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects, + JSToQVariantConversionBehavior conversionBehvior) { Q_ASSERT(o); @@ -1737,13 +1746,20 @@ static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObject int length = a->getLength(); for (int ii = 0; ii < length; ++ii) { v = a->get(ii); - list << ::toVariant(v, QMetaType {}, /*createJSValueForObjectsAndSymbols*/false, + list << ::toVariant(v, QMetaType {}, conversionBehvior, visitedObjects); } result = list; - } else if (o->getPrototypeOf() == o->engine()->objectPrototype()->d()) { - result = objectToVariantMap(o, visitedObjects); + } else if (o->getPrototypeOf() == o->engine()->objectPrototype()->d() + || (conversionBehvior == JSToQVariantConversionBehavior::Aggressive && + !o->as())) { + /* FunctionObject is excluded for historical reasons, even though + objects with a custom prototype risk losing information + But the Aggressive path is used only in QJSValue::toVariant + which is documented to be lossy + */ + result = objectToVariantMap(o, visitedObjects, conversionBehvior); } else { // If it's not a plain object, we can only save it as QJSValue. result = QVariant::fromValue(QJSValuePrivate::fromReturnedValue(o->asReturnedValue())); @@ -1973,7 +1989,7 @@ QVariantMap ExecutionEngine::variantMapFromJS(const Object *o) Q_ASSERT(o); V4ObjectSet visitedObjects; visitedObjects.insert(o->d()); - return objectToVariantMap(o, &visitedObjects); + return objectToVariantMap(o, &visitedObjects, JSToQVariantConversionBehavior::Safish); } diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 8590f330c..87b7e1fe6 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -664,6 +664,7 @@ struct Q_QML_EXPORT ExecutionEngine : public EngineBase // variant conversions static QVariant toVariant( const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols = true); + static QVariant toVariantLossy(const QV4::Value &value); QV4::ReturnedValue fromVariant(const QVariant &); QV4::ReturnedValue fromVariant( const QVariant &variant, Heap::Object *parent, int property, uint flags); diff --git a/src/qml/jsruntime/qv4executableallocator_p.h b/src/qml/jsruntime/qv4executableallocator_p.h index 2f97c9ae6..8181bf17a 100644 --- a/src/qml/jsruntime/qv4executableallocator_p.h +++ b/src/qml/jsruntime/qv4executableallocator_p.h @@ -100,7 +100,7 @@ class Q_QML_AUTOTEST_EXPORT ExecutableAllocator private: QMultiMap freeAllocations; QMap chunks; - mutable QRecursiveMutex mutex; + mutable QMutex mutex; }; } diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h index b9d21042a..002392d30 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit_p.h +++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h @@ -213,6 +213,11 @@ class Q_QML_PRIVATE_EXPORT ExecutableCompilationUnit final return data->flags & CompiledData::Unit::ValueTypesAddressable; } + bool componentsAreBound() const + { + return data->flags & CompiledData::Unit::ComponentsBound; + } + int objectCount() const { return qmlData->nObjects; } const CompiledObject *objectAt(int index) const { diff --git a/src/qml/jsruntime/qv4jscall_p.h b/src/qml/jsruntime/qv4jscall_p.h index 2f6af8dd8..f9c07e026 100644 --- a/src/qml/jsruntime/qv4jscall_p.h +++ b/src/qml/jsruntime/qv4jscall_p.h @@ -128,10 +128,13 @@ ReturnedValue convertAndCall( values[0] = nullptr; } - if (const QV4::QObjectWrapper *cppThisObject = thisObject->as()) + if (const QV4::QObjectWrapper *cppThisObject = thisObject + ? thisObject->as() + : nullptr) { call(cppThisObject->object(), values, types, argc); - else + } else { call(nullptr, values, types, argc); + } ReturnedValue result; if (values[0]) { @@ -228,6 +231,165 @@ ReturnedValue coerceAndCall( return result->asReturnedValue(); } +// Note: \a to is unininitialized here! This is in contrast to most other related functions. +inline void coerce( + ExecutionEngine *engine, QMetaType fromType, const void *from, QMetaType toType, void *to) +{ + if ((fromType.flags() & QMetaType::PointerToQObject) + && (toType.flags() & QMetaType::PointerToQObject)) { + QObject *fromObj = *static_cast(from); + *static_cast(to) + = (fromObj && fromObj->metaObject()->inherits(toType.metaObject())) + ? fromObj + : nullptr; + return; + } + + if (toType == QMetaType::fromType()) { + new (to) QVariant(fromType, from); + return; + } + + if (toType == QMetaType::fromType()) { + new (to) QJSPrimitiveValue(fromType, from); + return; + } + + if (fromType == QMetaType::fromType()) { + const QVariant *fromVariant = static_cast(from); + if (fromVariant->metaType() == toType) + toType.construct(to, fromVariant->data()); + else + coerce(engine, fromVariant->metaType(), fromVariant->data(), toType, to); + return; + } + + if (fromType == QMetaType::fromType()) { + const QJSPrimitiveValue *fromPrimitive = static_cast(from); + if (fromPrimitive->metaType() == toType) + toType.construct(to, fromPrimitive->data()); + else + coerce(engine, fromPrimitive->metaType(), fromPrimitive->data(), toType, to); + return; + } + + // TODO: This is expensive. We might establish a direct C++-to-C++ type coercion, like we have + // for JS-to-JS. However, we shouldn't need this very often. Most of the time the compiler + // will generate code that passes the right arguments. + if (toType.flags() & QMetaType::NeedsConstruction) + toType.construct(to); + QV4::Scope scope(engine); + QV4::ScopedValue value(scope, engine->fromData(fromType, from)); + if (!ExecutionEngine::metaTypeFromJS(value, toType, to)) + QMetaType::convert(fromType, from, toType, to); +} + +template +void coerceAndCall( + ExecutionEngine *engine, const TypedFunction *typedFunction, + void **argv, const QMetaType *types, int argc, Callable call) +{ + const qsizetype numFunctionArguments = typedFunction->parameterCount(); + + Q_ALLOCA_DECLARE(void *, transformedArguments); + Q_ALLOCA_DECLARE(void, transformedResult); + + const QMetaType returnType = typedFunction->returnMetaType(); + const QMetaType frameReturn = types[0]; + bool returnsQVariantWrapper = false; + if (argv[0] && returnType != frameReturn) { + Q_ALLOCA_ASSIGN(void *, transformedArguments, (numFunctionArguments + 1) * sizeof(void *)); + memcpy(transformedArguments, argv, (argc + 1) * sizeof(void *)); + + if (frameReturn == QMetaType::fromType()) { + QVariant *returnValue = static_cast(argv[0]); + *returnValue = QVariant(returnType); + transformedResult = transformedArguments[0] = returnValue->data(); + returnsQVariantWrapper = true; + } else if (returnType.sizeOf() > 0) { + Q_ALLOCA_ASSIGN(void, transformedResult, returnType.sizeOf()); + transformedArguments[0] = transformedResult; + if (returnType.flags() & QMetaType::NeedsConstruction) + returnType.construct(transformedResult); + } else { + transformedResult = transformedArguments[0] = &argc; // Some non-null marker value + } + } + + for (qsizetype i = 0; i < numFunctionArguments; ++i) { + const bool isValid = argc > i; + const QMetaType frameType = isValid ? types[i + 1] : QMetaType(); + + const QMetaType argumentType = typedFunction->parameterMetaType(i); + if (isValid && argumentType == frameType) + continue; + + if (transformedArguments == nullptr) { + Q_ALLOCA_ASSIGN(void *, transformedArguments, (numFunctionArguments + 1) * sizeof(void *)); + memcpy(transformedArguments, argv, (argc + 1) * sizeof(void *)); + } + + if (argumentType.sizeOf() == 0) { + transformedArguments[i + 1] = nullptr; + continue; + } + + void *frameVal = isValid ? argv[i + 1] : nullptr; + if (isValid && frameType == QMetaType::fromType()) { + QVariant *variant = static_cast(frameVal); + + const QMetaType variantType = variant->metaType(); + if (variantType == argumentType) { + // Slightly nasty, but we're allowed to do this. + // We don't want to destruct() the QVariant's data() below. + transformedArguments[i + 1] = argv[i + 1] = variant->data(); + } else { + Q_ALLOCA_VAR(void, arg, argumentType.sizeOf()); + coerce(engine, variantType, variant->constData(), argumentType, arg); + transformedArguments[i + 1] = arg; + } + continue; + } + + Q_ALLOCA_VAR(void, arg, argumentType.sizeOf()); + + if (isValid) + coerce(engine, frameType, frameVal, argumentType, arg); + else + argumentType.construct(arg); + + transformedArguments[i + 1] = arg; + } + + if (!transformedArguments) { + call(argv, numFunctionArguments); + return; + } + + call(transformedArguments, numFunctionArguments); + + if (transformedResult && !returnsQVariantWrapper) { + if (frameReturn.sizeOf() > 0) { + if (frameReturn.flags() & QMetaType::NeedsDestruction) + frameReturn.destruct(argv[0]); + coerce(engine, returnType, transformedResult, frameReturn, argv[0]); + } + if (returnType.flags() & QMetaType::NeedsDestruction) + returnType.destruct(transformedResult); + } + + for (qsizetype i = 0; i < numFunctionArguments; ++i) { + void *arg = transformedArguments[i + 1]; + if (arg == nullptr) + continue; + if (i >= argc || arg != argv[i + 1]) { + const QMetaType argumentType = typedFunction->parameterMetaType(i); + if (argumentType.flags() & QMetaType::NeedsDestruction) + argumentType.destruct(arg); + } + } +} + } // namespace QV4 QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index d9d0fe09b..7b4e5e738 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -269,9 +269,33 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r contextGetterFunction = QQmlContextWrapper::lookupScopeObjectProperty; } + QQmlRefPointer outer = context; while (context) { - if (auto property = searchContextProperties(v4, context, name, hasProperty, base, lookup, originalLookup, ep)) - return *property; + if (outer == context) { + if (auto property = searchContextProperties( + v4, context, name, hasProperty, base, lookup, originalLookup, ep)) { + return *property; + } + + outer = outer->parent(); + + if (const auto cu = context->typeCompilationUnit(); cu && cu->componentsAreBound()) { + // If components are bound in this CU, we can search the whole context hierarchy + // of the file. Bound components' contexts override their local properties. + // You also can't instantiate bound components outside of their creation + // context. Therefore this is safe. + + for (; + outer && outer->typeCompilationUnit() == cu; + outer = outer->parent()) { + if (auto property = searchContextProperties( + v4, outer, name, hasProperty, base, + nullptr, originalLookup, ep)) { + return *property; + } + } + } + } // Search scope object if (scopeObject) { @@ -476,8 +500,8 @@ ReturnedValue QQmlContextWrapper::resolveQmlContextPropertyLookupGetter(Lookup * { Scope scope(engine); auto *func = engine->currentStackFrame->v4Function; - PropertyKey name =engine->identifierTable->asPropertyKey( - func->compilationUnit->runtimeStrings[l->nameIndex]); + ScopedPropertyKey name(scope, engine->identifierTable->asPropertyKey( + func->compilationUnit->runtimeStrings[l->nameIndex])); // Special hack for bounded signal expressions, where the parameters of signals are injected // into the handler expression through the locals of the call context. So for onClicked: { ... } @@ -491,7 +515,7 @@ ReturnedValue QQmlContextWrapper::resolveQmlContextPropertyLookupGetter(Lookup * const auto location = func->sourceLocation(); qCWarning(lcQmlContext).nospace().noquote() << location.sourceFile << ":" << location.line << ":" << location.column - << " Parameter \"" << name.toQString() << "\" is not declared." + << " Parameter \"" << name->toQString() << "\" is not declared." << " Injection of parameters into signal handlers is deprecated." << " Use JavaScript functions with formal parameters instead."; @@ -527,7 +551,7 @@ ReturnedValue QQmlContextWrapper::resolveQmlContextPropertyLookupGetter(Lookup * } } if (!hasProperty) - return engine->throwReferenceError(name.toQString()); + return engine->throwReferenceError(name->toQString()); return result->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 3caad8bde..4b7258ad6 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1085,13 +1085,15 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase static void impl(int which, QSlotObjectBase *this_, QObject *receiver, void **metaArgs, bool *ret) { - Q_UNUSED(receiver); switch (which) { case Destroy: { delete static_cast(this_); } break; case Call: { + if (QQmlData::wasDeleted(receiver)) + break; + QObjectSlotDispatcher *This = static_cast(this_); ExecutionEngine *v4 = This->function.engine(); // Might be that we're still connected to a signal that's emitted long @@ -1100,7 +1102,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase if (!v4) break; - QQmlMetaObject::ArgTypeStorage storage; + QQmlMetaObject::ArgTypeStorage<9> storage; QQmlMetaObject::methodParameterTypes(This->signal, &storage, nullptr); int argCount = storage.size(); @@ -1240,7 +1242,16 @@ ReturnedValue QObjectWrapper::method_connect(const FunctionObject *b, const Valu } QPair functionData = QObjectMethod::extractQtMethod(f); // align with disconnect - if (QObject *receiver = functionData.first) { + QObject *receiver = nullptr; + + if (functionData.first) + receiver = functionData.first; + else if (auto qobjectWrapper = object->as()) + receiver = qobjectWrapper->object(); + else if (auto typeWrapper = object->as()) + receiver = typeWrapper->object(); + + if (receiver) { QObjectPrivate::connect(signalObject, signalIndex, receiver, slot, Qt::AutoConnection); } else { qCInfo(lcObjectConnect, @@ -1298,7 +1309,16 @@ ReturnedValue QObjectWrapper::method_disconnect(const FunctionObject *b, const V &functionData.second }; - if (QObject *receiver = functionData.first) { + QObject *receiver = nullptr; + + if (functionData.first) + receiver = functionData.first; + else if (auto qobjectWrapper = functionThisValue->as()) + receiver = qobjectWrapper->object(); + else if (auto typeWrapper = functionThisValue->as()) + receiver = typeWrapper->object(); + + if (receiver) { QObjectPrivate::disconnect(signalObject, signalIndex, receiver, reinterpret_cast(&a)); } else { @@ -1803,7 +1823,7 @@ static ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQmlPro if (data.hasArguments()) { - QQmlMetaObject::ArgTypeStorage storage; + QQmlMetaObject::ArgTypeStorage<9> storage; bool ok = false; if (data.isConstructor()) @@ -1884,7 +1904,7 @@ static const QQmlPropertyData *ResolveOverloaded( int sumMethodMatchScore = bestSumMatchScore; if (!attempt->isV4Function()) { - QQmlMetaObject::ArgTypeStorage storage; + QQmlMetaObject::ArgTypeStorage<9> storage; int methodArgumentCount = 0; if (attempt->hasArguments()) { if (attempt->isConstructor()) { diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index e422ca5ee..3f9ce2676 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -179,7 +179,7 @@ void QQmlBoundSignalExpression::evaluate(void **a) QMetaObjectPrivate::signal(targetMeta, m_index).methodIndex()); int argCount = metaMethod.parameterCount(); - QQmlMetaObject::ArgTypeStorage storage; + QQmlMetaObject::ArgTypeStorage<9> storage; storage.reserve(argCount + 1); storage.append(QMetaType()); // We're not interested in the return value for (int i = 0; i < argCount; ++i) { diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index 8607cf7f3..1d3f1d03a 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -167,10 +167,7 @@ class Q_QML_PRIVATE_EXPORT QQmlComponentPrivate : public QObjectPrivate, public QObject *createWithProperties(QObject *parent, const QVariantMap &properties, QQmlContext *context, CreateBehavior behavior = CreateDefault); - bool isBound() const { - return compilationUnit - && (compilationUnit->unitData()->flags & QV4::CompiledData::Unit::ComponentsBound); - } + bool isBound() const { return compilationUnit && (compilationUnit->componentsAreBound()); } }; QQmlComponentPrivate::ConstructionState::~ConstructionState() diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp index 319accb76..441fc6200 100644 --- a/src/qml/qml/qqmlextensionplugin.cpp +++ b/src/qml/qml/qqmlextensionplugin.cpp @@ -166,8 +166,20 @@ void QQmlEngineExtensionPlugin::initializeEngine(QQmlEngine *engine, const char \since 6.2 \relates QQmlEngineExtensionPlugin - Ensures the plugin whose metadata-declaring class is named \a PluginName - is linked into static builds. + Ensures the plugin whose metadata-declaring plugin extension class is named + \a PluginName is linked into static builds. For the modules created using + \l qt_add_qml_module, the default plugin extension class name is computed + from the QML module URI by replacing dots with underscores, unless the + \c CLASS_NAME argument is specified. + + For example: + \badcode + qt_add_qml_module(myplugin + # The plugin extension class name in this case is my_Company_QmlComponents. + URI my.Company.QmlComponents + ... + ) + \endcode \sa Q_IMPORT_PLUGIN */ diff --git a/src/qml/qml/qqmlmetaobject.cpp b/src/qml/qml/qqmlmetaobject.cpp index 82903f80b..352db7bd6 100644 --- a/src/qml/qml/qqmlmetaobject.cpp +++ b/src/qml/qml/qqmlmetaobject.cpp @@ -56,42 +56,4 @@ QMetaType QQmlMetaObject::methodReturnType(const QQmlPropertyData &data, QByteAr return QMetaType(); } -bool QQmlMetaObject::methodParameterTypes(int index, ArgTypeStorage *argStorage, - QByteArray *unknownTypeError) const -{ - Q_ASSERT(_m && index >= 0); - - QMetaMethod m = _m->method(index); - return methodParameterTypes(m, argStorage, unknownTypeError); -} - -bool QQmlMetaObject::constructorParameterTypes(int index, ArgTypeStorage *dummy, - QByteArray *unknownTypeError) const -{ - QMetaMethod m = _m->constructor(index); - return methodParameterTypes(m, dummy, unknownTypeError); -} - -bool QQmlMetaObject::methodParameterTypes(const QMetaMethod &m, ArgTypeStorage *argStorage, - QByteArray *unknownTypeError) -{ - Q_ASSERT(argStorage); - - int argc = m.parameterCount(); - argStorage->resize(argc); - for (int ii = 0; ii < argc; ++ii) { - QMetaType type = m.parameterMetaType(ii); - // we treat enumerations as int - if (type.flags().testFlag(QMetaType::IsEnumeration)) - type = type.underlyingType(); - if (!type.isValid()) { - if (unknownTypeError) - *unknownTypeError = m.parameterTypeName(ii); - return false; - } - argStorage->operator[](ii) = type; - } - return true; -} - QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlmetaobject_p.h b/src/qml/qml/qqmlmetaobject_p.h index 288779c74..498c27884 100644 --- a/src/qml/qml/qqmlmetaobject_p.h +++ b/src/qml/qml/qqmlmetaobject_p.h @@ -34,7 +34,8 @@ class QQmlPropertyData; class Q_QML_EXPORT QQmlMetaObject { public: - typedef QVarLengthArray ArgTypeStorage; + template + using ArgTypeStorage = QVarLengthArray; inline QQmlMetaObject() = default; inline QQmlMetaObject(const QObject *); @@ -52,19 +53,34 @@ class Q_QML_EXPORT QQmlMetaObject inline const QMetaObject *metaObject() const; QMetaType methodReturnType(const QQmlPropertyData &data, QByteArray *unknownTypeError) const; + /*! \internal Returns false if one of the types is unknown. Otherwise, fills \a argstorage with the metatypes of the function. */ - bool methodParameterTypes(int index, ArgTypeStorage *argStorage, - QByteArray *unknownTypeError) const; + template + bool methodParameterTypes( + int index, ArgTypeStorage *argStorage, QByteArray *unknownTypeError) const + { + Q_ASSERT(_m && index >= 0); + + QMetaMethod m = _m->method(index); + return methodParameterTypes(m, argStorage, unknownTypeError); + } + /*! \internal Returns false if one of the types is unknown. Otherwise, fills \a argstorage with the metatypes of the function. */ - bool constructorParameterTypes(int index, ArgTypeStorage *dummy, QByteArray *unknownTypeError) const; + template + bool constructorParameterTypes( + int index, ArgTypeStorage *dummy, QByteArray *unknownTypeError) const + { + QMetaMethod m = _m->constructor(index); + return methodParameterTypes(m, dummy, unknownTypeError); + } static bool canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to) @@ -75,11 +91,82 @@ class Q_QML_EXPORT QQmlMetaObject // static_metacall (on Gadgets) doesn't call the base implementation and therefore // we need a helper to find the correct meta object and property/method index. - static void resolveGadgetMethodOrPropertyIndex(QMetaObject::Call type, const QMetaObject **metaObject, int *index); + static void resolveGadgetMethodOrPropertyIndex( + QMetaObject::Call type, const QMetaObject **metaObject, int *index); + + template + static bool methodParameterTypes( + const QMetaMethod &method, ArgTypeStorage *argStorage, QByteArray *unknownTypeError) + { + Q_ASSERT(argStorage); + + const int argc = method.parameterCount(); + argStorage->resize(argc); + for (int ii = 0; ii < argc; ++ii) { + if (!parameterType(method, ii, unknownTypeError, [argStorage](int ii, QMetaType &&type) { + argStorage->operator[](ii) = std::forward(type); + })) { + return false; + } + } + return true; + } + + template + static bool methodReturnAndParameterTypes( + const QMetaMethod &method, ArgTypeStorage *argStorage, QByteArray *unknownTypeError) + { + Q_ASSERT(argStorage); + + const int argc = method.parameterCount(); + argStorage->resize(argc + 1); + + QMetaType type = method.returnMetaType(); + if (type.flags().testFlag(QMetaType::IsEnumeration)) + type = type.underlyingType(); + + if (!type.isValid()) { + if (unknownTypeError) + *unknownTypeError = "return type"; + return false; + } + + argStorage->operator[](0) = type; + + for (int ii = 0; ii < argc; ++ii) { + if (!parameterType( + method, ii, unknownTypeError, [argStorage](int ii, QMetaType &&type) { + argStorage->operator[](ii + 1) = std::forward(type); + })) { + return false; + } + } + + return true; + } - static bool methodParameterTypes(const QMetaMethod &method, ArgTypeStorage *argStorage, - QByteArray *unknownTypeError); protected: + template + static bool parameterType( + const QMetaMethod &method, int ii, QByteArray *unknownTypeError, const Store &store) + { + QMetaType type = method.parameterMetaType(ii); + + // we treat enumerations as their underlying type + if (type.flags().testFlag(QMetaType::IsEnumeration)) + type = type.underlyingType(); + + if (!type.isValid()) { + if (unknownTypeError) + *unknownTypeError = method.parameterTypeName(ii); + return false; + } + + store(ii, std::move(type)); + return true; + } + + const QMetaObject *_m = nullptr; }; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 2cfccf14d..21e475fcc 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -154,7 +154,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI } else { Q_ASSERT(subComponentIndex >= 0); if (flags & CreationFlags::InlineComponent) { - if (compilationUnit->unitData()->flags & QV4::CompiledData::Unit::ComponentsBound + if (compilationUnit->componentsAreBound() && compilationUnit != parentContext->typeCompilationUnit()) { recordError({}, tr("Cannot instantiate bound inline component in different file")); phase = ObjectsCreated; @@ -164,7 +164,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI isComponentRoot = true; } else { Q_ASSERT(flags & CreationFlags::NormalObject); - if (compilationUnit->unitData()->flags & QV4::CompiledData::Unit::ComponentsBound + if (compilationUnit->componentsAreBound() && sharedState->creationContext != parentContext) { recordError({}, tr("Cannot instantiate bound component " "outside its creation context")); diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index 23cfaef2e..76b93cde6 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -365,8 +365,8 @@ namespace QQmlPrivate struct Properties { using Func = QQmlAttachedPropertiesFunc; - static const QMetaObject *staticMetaObject() { return nullptr; }; - static Func attachedPropertiesFunc() { return nullptr; }; + static const QMetaObject *staticMetaObject() { return nullptr; } + static Func attachedPropertiesFunc() { return nullptr; } }; using Type = typename std::conditional< diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h index 9d15c3eb8..5b9a9abf6 100644 --- a/src/qml/qml/qqmlpropertycachecreator_p.h +++ b/src/qml/qml/qqmlpropertycachecreator_p.h @@ -860,15 +860,8 @@ inline QQmlError QQmlPropertyCacheAliasCreator::propertyDataFor const QMetaType targetPropType = targetProperty->propType(); - const auto resolveType = [](QMetaType targetPropType) { - if (targetPropType.flags() & QMetaType::IsEnumeration) - return targetPropType.underlyingType(); - else - return targetPropType; - }; - const auto populateWithPropertyData = [&](const QQmlPropertyData *property) { - *type = resolveType(property->propType()); + *type = property->propType(); writable = property->isWritable(); resettable = property->isResettable(); bindable = property->isBindable(); @@ -912,7 +905,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator::propertyDataFor = QQmlMetaType::metaObjectForValueType(*type); const QMetaProperty valueTypeMetaProperty = valueTypeMetaObject->property(valueTypeIndex); - *type = resolveType(valueTypeMetaProperty.metaType()); + *type = valueTypeMetaProperty.metaType(); // We can only write or reset the value type property if we can write // the value type itself. diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index 53f1a90c8..e400c3a51 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2024 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qqmlbind_p.h" @@ -429,9 +429,9 @@ void QQmlBind::setWhen(bool v) /*! \qmlproperty QtObject QtQml::Binding::target - The object to be updated. You only need to use this property if you can't - supply the binding target declaratively. The following two pieces of code - are equivalent. + The object to be updated. You need to use this property if the binding target + does not have an \c id attribute (for example, when the target is a singleton). + Otherwise, the following two pieces of code are equivalent: \qml Binding { contactName.text: name } diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp index e69e0087e..e26d39aac 100644 --- a/src/qml/types/qqmlconnections.cpp +++ b/src/qml/types/qqmlconnections.cpp @@ -3,16 +3,19 @@ #include "qqmlconnections_p.h" -#include -#include #include -#include #include +#include +#include #include -#include +#include +#include + +#include +#include -#include #include +#include #include #include @@ -21,10 +24,110 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQmlConnections, "qt.qml.connections") +// This is the equivalent of QQmlBoundSignal for C++ methods as as slots. +// If a type derived from QQmlConnnections is compiled using qmltc, the +// JavaScript functions it contains are turned into C++ methods and we cannot +// use QQmlBoundSignal to connect to those. +struct QQmlConnectionSlotDispatcher : public QtPrivate::QSlotObjectBase +{ + QV4::ExecutionEngine *v4 = nullptr; + QObject *receiver = nullptr; + + // Signals rarely have more than one argument. + QQmlMetaObject::ArgTypeStorage<2> signalMetaTypes; + QQmlMetaObject::ArgTypeStorage<2> slotMetaTypes; + + QMetaObject::Connection connection; + + int slotIndex = -1; + bool enabled = true; + + QQmlConnectionSlotDispatcher( + QV4::ExecutionEngine *v4, QObject *sender, int signalIndex, + QObject *receiver, int slotIndex, bool enabled) + : QtPrivate::QSlotObjectBase(&impl) + , v4(v4) + , receiver(receiver) + , slotIndex(slotIndex) + , enabled(enabled) + { + QMetaMethod signal = sender->metaObject()->method(signalIndex); + QQmlMetaObject::methodReturnAndParameterTypes(signal, &signalMetaTypes, nullptr); + + QMetaMethod slot = receiver->metaObject()->method(slotIndex); + QQmlMetaObject::methodReturnAndParameterTypes(slot, &slotMetaTypes, nullptr); + } + + template + struct TypedFunction + { + Q_DISABLE_COPY_MOVE(TypedFunction) + public: + TypedFunction(const ArgTypeStorage *storage) : storage(storage) {} + + QMetaType returnMetaType() const { return storage->at(0); } + qsizetype parameterCount() const { return storage->size() - 1; } + QMetaType parameterMetaType(qsizetype i) const { return storage->at(i + 1); } + + private: + const ArgTypeStorage *storage; + }; + + static void impl(int which, QSlotObjectBase *base, QObject *, void **metaArgs, bool *ret) + { + switch (which) { + case Destroy: { + delete static_cast(base); + break; + } + case Call: { + QQmlConnectionSlotDispatcher *self = static_cast(base); + QV4::ExecutionEngine *v4 = self->v4; + if (!v4) + break; + + if (!self->enabled) + break; + + TypedFunction typedFunction(&self->slotMetaTypes); + QV4::coerceAndCall( + v4, &typedFunction, metaArgs, + self->signalMetaTypes.data(), self->signalMetaTypes.size() - 1, + [&](void **argv, int) { + self->receiver->metaObject()->metacall( + self->receiver, QMetaObject::InvokeMetaMethod, + self->slotIndex, argv); + }); + + if (v4->hasException) { + QQmlError error = v4->catchExceptionAsQmlError(); + if (QQmlEngine *qmlEngine = v4->qmlEngine()) { + QQmlEnginePrivate::get(qmlEngine)->warning(error); + } else { + QMessageLogger( + qPrintable(error.url().toString()), error.line(), nullptr) + .warning().noquote() + << error.toString(); + } + } + break; + } + case Compare: + // We're not implementing the Compare protocol here. It's insane. + // QQmlConnectionSlotDispatcher compares false to anything. We use + // the regular QObject::disconnect with QMetaObject::Connection. + *ret = false; + break; + case NumOperations: + break; + } + }; +}; + class QQmlConnectionsPrivate : public QObjectPrivate { public: - QList boundsignals; + QList> boundsignals; QQmlGuard target; bool enabled = true; @@ -105,6 +208,22 @@ QQmlConnections::QQmlConnections(QObject *parent) : { } +QQmlConnections::~QQmlConnections() +{ + Q_D(QQmlConnections); + + // The slot dispatchers hold cyclic references to their connections. Clear them. + for (const auto &bound : std::as_const(d->boundsignals)) { + if (QQmlConnectionSlotDispatcher *dispatcher = bound.isT2() ? bound.asT2() : nullptr) { + // No need to explicitly disconnect anymore since 'this' is the receiver. + // But to be safe, explicitly break any cyclic references between the connection + // and the slot object. + dispatcher->connection = {}; + dispatcher->destroyIfLastRef(); + } + } +} + /*! \qmlproperty QtObject QtQml::Connections::target This property holds the object that sends the signal. @@ -136,13 +255,19 @@ void QQmlConnections::setTarget(QObject *obj) if (d->targetSet && d->target == obj) return; d->targetSet = true; // even if setting to 0, it is *set* - for (QQmlBoundSignal *s : std::as_const(d->boundsignals)) { + for (const auto &bound : std::as_const(d->boundsignals)) { // It is possible that target is being changed due to one of our signal // handlers -> use deleteLater(). - if (s->isNotifying()) - (new QQmlBoundSignalDeleter(s))->deleteLater(); - else - delete s; + if (QQmlBoundSignal *signal = bound.isT1() ? bound.asT1() : nullptr) { + if (signal->isNotifying()) + (new QQmlBoundSignalDeleter(signal))->deleteLater(); + else + delete signal; + } else { + QQmlConnectionSlotDispatcher *dispatcher = bound.asT2(); + QObject::disconnect(std::exchange(dispatcher->connection, {})); + dispatcher->destroyIfLastRef(); + } } d->boundsignals.clear(); d->target = obj; @@ -172,8 +297,12 @@ void QQmlConnections::setEnabled(bool enabled) d->enabled = enabled; - for (QQmlBoundSignal *s : std::as_const(d->boundsignals)) - s->setEnabled(d->enabled); + for (const auto &bound : std::as_const(d->boundsignals)) { + if (QQmlBoundSignal *signal = bound.isT1() ? bound.asT1() : nullptr) + signal->setEnabled(d->enabled); + else + bound.asT2()->enabled = enabled; + } emit enabledChanged(); } @@ -272,33 +401,41 @@ void QQmlConnections::connectSignalsToMethods() ++i) { const QQmlPropertyData *handler = ddata->propertyCache->method(i); - if (!handler || !handler->isVMEFunction()) + if (!handler) continue; const QString propName = handler->name(this); QQmlProperty prop(target, propName); if (prop.isValid() && (prop.type() & QQmlProperty::SignalProperty)) { - int signalIndex = QQmlPropertyPrivate::get(prop)->signalIndex(); - auto *signal = new QQmlBoundSignal(target, signalIndex, this, qmlEngine(this)); - signal->setEnabled(d->enabled); - QV4::Scope scope(engine); QV4::ScopedContext global(scope, engine->rootContext()); - QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(this); - Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this - - QV4::ScopedFunctionObject method(scope, vmeMetaObject->vmeMethod(handler->coreIndex())); - - QQmlBoundSignalExpression *expression = - ctxtdata ? new QQmlBoundSignalExpression( - target, signalIndex, ctxtdata, this, - method->as()->function()) - : nullptr; - - signal->takeExpression(expression); - d->boundsignals += signal; + if (QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(this)) { + int signalIndex = QQmlPropertyPrivate::get(prop)->signalIndex(); + auto *signal = new QQmlBoundSignal(target, signalIndex, this, qmlEngine(this)); + signal->setEnabled(d->enabled); + + QV4::ScopedFunctionObject method( + scope, vmeMetaObject->vmeMethod(handler->coreIndex())); + + QQmlBoundSignalExpression *expression = ctxtdata + ? new QQmlBoundSignalExpression( + target, signalIndex, ctxtdata, this, + method->as()->function()) + : nullptr; + + signal->takeExpression(expression); + d->boundsignals += signal; + } else { + QQmlConnectionSlotDispatcher *slot = new QQmlConnectionSlotDispatcher( + scope.engine, target, prop.index(), + this, handler->coreIndex(), d->enabled); + slot->connection = QObjectPrivate::connect( + target, prop.index(), slot, Qt::AutoConnection); + slot->ref(); + d->boundsignals += slot; + } } else if (!d->ignoreUnknownSignals && propName.startsWith(QLatin1String("on")) && propName.size() > 2 && propName.at(2).isUpper()) { diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h index bb23caecf..99d04c616 100644 --- a/src/qml/types/qqmlconnections_p.h +++ b/src/qml/types/qqmlconnections_p.h @@ -40,7 +40,8 @@ class Q_QML_PRIVATE_EXPORT QQmlConnections : public QObject, public QQmlParserSt QML_CUSTOMPARSER public: - QQmlConnections(QObject *parent=nullptr); + QQmlConnections(QObject *parent = nullptr); + ~QQmlConnections(); QObject *target() const; void setTarget(QObject *); diff --git a/src/qmlcompiler/doc/qtqmlcompiler-index.qdoc b/src/qmlcompiler/doc/qtqmlcompiler-index.qdoc index d9d9a4e2a..03a2eafbb 100644 --- a/src/qmlcompiler/doc/qtqmlcompiler-index.qdoc +++ b/src/qmlcompiler/doc/qtqmlcompiler-index.qdoc @@ -6,15 +6,32 @@ \title Qt QML Compiler \brief Provides tools for static analysis of QML code. + The Qt QML Compiler module contains shared functionality needed by QML + tooling like the \l{Qt Quick Compiler} and \l{qmllint}. + It also provides the QQmlSA framework, which can be used to extend the + built-in analysis capabilities of the tools. + + \section1 Using the Module + + \include {module-use.qdocinc} {using the c++ api} + + \section2 Building with CMake + + \include {module-use.qdocinc} {building with cmake} {QmlCompiler} + + \section2 Building with qmake + + \include {module-use.qdocinc} {building_with_qmake} {QmlCompiler} + + \section1 Using the QQmlSA framework + The Qt QML Compiler module offers the QQmlSA framework which provides tools for static analysis of QML code. These tools can help ensure syntactic validity and warn about QML anti-patterns. - Adding static analysis to a QML program is done by writing plugins. They will run a collection of analysis passes over the elements and properties of the QML code. The passes can be registered with a PassManager which holds the passes and can be called to analyze an element and its children. - A pass is a check for a certain rule or condition evaluated on elements or properties. If the condition is met, the pass can warn the user of an indentified issue in the code and maybe even suggest a fix. It is called a @@ -22,18 +39,15 @@ running a collection of passes on them in succesion. Each pass should be responsible for identifying one specific issue only. Combining a set of passes can perform more complex analysis and, together, form a plugin. - Element passes are defined by two main components, namely \c shouldRun() and \c run(). When performing the analysis, the pass manager will execute the pass over every element it encounters while traversing the children of the root element. For each element, if \c shouldRun() evaluated on that element returns \c true then \c run() is executed on it. - Passes on properties trigger on three different events, namely when the property is bound, when it is read, and when it is written to. These can be implemented by overriding the \c onBinding(), \c onRead() and \c onWrite() functions respectively. - As the code grows, so does the number of elements and properties. Performing the static analysis passes on all of them can become expensive. That's why it is good to be granular when deciding which elements and @@ -44,4 +58,24 @@ \c moduleName, \c typeName and \c propertyName strings as arguments. These are used to filter down the set of properties affected by the registered pass. + + + \section1 Examples + + The \l{QML Static Analysis Tutorial} shows how to use the \c{QQmlSA} + framework to create a custom \l{qmllint} pass. + + \section1 Reference + + \list + \li \l {Qt QML Compiler C++ Classes} + - the C++ API provided by the QmlCompiler module + \li QML tooling using the static analysis capabilities + \list + \li \l{QML script compiler} + \li \l{qmllint} + \li \l{QML Language Server} + \li \l{QML type compiler} + \endlist + \endlist */ diff --git a/src/qmlcompiler/doc/qtqmlcompiler.qdocconf b/src/qmlcompiler/doc/qtqmlcompiler.qdocconf index f94c25b23..a1d38d8ad 100644 --- a/src/qmlcompiler/doc/qtqmlcompiler.qdocconf +++ b/src/qmlcompiler/doc/qtqmlcompiler.qdocconf @@ -45,3 +45,5 @@ navigation.cppclassespage = "Qt QML Compiler C++ Classes" # Fail the documentation build if there are more warnings than the limit warninglimit = 0 +exampledirs += \ + ../../../examples/qmlcompiler diff --git a/src/qmlcompiler/doc/src/qtqmlcompiler-module.qdoc b/src/qmlcompiler/doc/src/qtqmlcompiler-module.qdoc index ed7ef11d4..152fc94cd 100644 --- a/src/qmlcompiler/doc/src/qtqmlcompiler-module.qdoc +++ b/src/qmlcompiler/doc/src/qtqmlcompiler-module.qdoc @@ -5,6 +5,9 @@ \module QtQmlCompiler \modulestate Technical Preview \title Qt QML Compiler C++ Classes + \qtcmakepackage QmlCompiler - \brief The Qt QML Compiler module provides tools for static analysis of QML code. + For more information on the Qt QmlCompiler module, see the + \l{Qt QML Compiler} module documentation.\brief The Qt QML Compiler module provides tools + for static analysis of QML code. */ diff --git a/src/qmlcompiler/doc/src/tutorial.qdoc b/src/qmlcompiler/doc/src/tutorial.qdoc new file mode 100644 index 000000000..53a648373 --- /dev/null +++ b/src/qmlcompiler/doc/src/tutorial.qdoc @@ -0,0 +1,229 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! +\page qqmlsa-tutorial.html +\title QML Static Analysis Tutorial +\brief An introduction on writing your own qmllint checks +\nextpage QML Static Analysis 1 - Basic Setup + +This tutorial gives an introduction to QQmlSA, the API to statically analyze QML code. + +Through the different steps of this tutorial we will learn about how to set up a basic qmllint +plugin, we will create our own custom analysis pass, and we will add support for fixit-hints. + +Chapter one starts with a minimal plugin and the following chapters introduce new concepts. + +The tutorial's source code is located in the \c{examples/qmlcompiler/tutorials/helloworld} directory. + +Tutorial chapters: + +\list 1 +\li \l {QML Static Analysis 1 - Basic Setup}{Basic Setup} +\li \l {QML Static Analysis 2 - Custom Pass}{Custom Pass} +\li \l {QML Static Analysis 3 - Fixit Hints}{Fixit Hints} +\endlist + +*/ + +/*! +\page qqmlsa-tutorial1.html +\title QML Static Analysis 1 - Basic Setup +\previouspage QML Static Analysis Tutorial +\nextpage QML Static Analysis 2 - Custom Pass + +This chapter introduces the basic structure of a qmllint extension plugin, +and how it can be used with qmllint. + +To create our plugin, we first need to make the QmlCompiler module available: +\quotefromfile tutorials/helloworld/chapter1/CMakeLists.txt +\skipto find_package +\printline find_package + +We then create a plugin, and link it against the QmlCompiler module. + +\skipto qt_add_plugin(HelloWorldPlugin) +\printuntil + +The implementation follows the pattern for \l{The High-Level API: Writing Qt Extensions}{extending +Qt with a plugin}: We subclass the \l{QQmlSA::LintPlugin}, +\quotefromfile tutorials/helloworld/chapter1/helloplugin.h +\skipto class HelloWorldPlugin +\printuntil }; + +The plugin references a \c{plugin.json} file, which contains some important information: +\quotefile tutorials/helloworld/chapter1/plugin.json +\c{name}, \c{author}, \c{version} and \c{description} are meta-data to describe the plugin. + +Each plugin can have one or more logging categories, which are used to thematically group +warnings. +\c{loggingCategories} takes an array of categories, each consisting of +\list + \li \c{name}, which is used to identify the category, and as the flag name in qmllint, + \li \c{settingsName}, which is used to configure the category in qmllint.ini + \li \c{description}, which should describe what kind of warning messages are tagged with the category +\endlist + +In our example, we have only one logging category, \c{hello-world}. For each category, we have to +create a \l{QQmlJS::LoggerWarningId}{LoggerWarningId} object in our plugin. + +\quotefromfile tutorials/helloworld/chapter1/helloplugin.cpp +\skipto static constexpr QQmlSA::LoggerWarningId +\printline static constexpr QQmlSA::LoggerWarningId + +We construct it with a string literal which should have the format +\c{Plugin..}. + +Lastly, for our plugin to actually do anything useful, we have to implement the +\c{registerPasses} function. + +\skipto void HelloWorldPlugin::registerPasses( +\printuntil } + +We check whether our category is enabled, and print a diagnostic indicating its status +via \l{qDebug}. +Note that the plugin currently does not do anything useful, as we do not register any +passes. This will done in the next part of this tutorial. + +We can however already verify that our plugin is correctly detected. We use the following command to +check it: + +\badcode +qmllint -P /path/to/the/directory/containing/the/plugin --Plugin.HelloWorld.hello-world info test.qml +\endcode + +The \c{-P} options tells qmllint to look for plugins in the specified folder. To avoid conflicts +with Qt internal categories, plugin categories are always prefixed with "Plugin", then followed by +a dot, the plugin name, another dot and finally the category. +Running the command should print \c{Hello World Plugin is enabled}. + +*/ + + +/*! +\page qqmlsa-tutorial2.html +\title QML Static Analysis 2 - Custom Pass +\previouspage QML Static Analysis 1 - Basic Setup +\nextpage QML Static Analysis 3 - Fixit Hints + +This chapter shows how custom analysis passes can be added to \l{qmllint}, +by extending the plugin we've created in the last chapter. +For demonstration purposes, we will create a plugin which checks whether +\l{Text} elements have "Hello world!" assigned to their text property. + +To do this, we create a new class derived from +\l{QQmlSA::ElementPass}{ElementPass}. + +\note There are two types of passes that +plugins can register, \l{QQmlSA::ElementPass}{ElementPasses}, and \l{QQmlSA::PropertyPass}{PropertyPasses}. +In this tutorial, we will only consider the simpler \c{ElementPass}. + +\quotefromfile tutorials/helloworld/chapter2/helloplugin.cpp +\skipto class HelloWorldElementPass : public QQmlSA::ElementPass +\printuntil }; + +As our \c{HelloWorldElementPass} should analyze \c{Text} elements, +we need a reference to the \c{Text} type. We can use the +\l{QQmlSA::GenericPass::resolveType}{resolveType} function to obtain it. +As we don't want to constantly re-resolve the type, we do this +once in the constructor, and store the type in a member variable. + +\skipto HelloWorldElementPass::HelloWorldElementPass( +\printuntil } + +The actual logic of our pass happens in two functions: +\l{QQmlSA::ElementPass::shouldRun}{shouldRun} and +\l{QQmlSA::ElementPass::run}{run}. They will run on +all Elements in the file that gets analyzed by qmllint. + +In our \c{shouldRun} method, we check whether the current +Element is derived from Text, and check whether it has +a binding on the text property. +\skipto bool HelloWorldElementPass::shouldRun +\printuntil } + +Only elements passing the checks there will then be analyzed by our +pass via its \c{run} method. It would be possible to do all checking +inside of \c{run} itself, but it is generally preferable to have +a separation of concerns – both for performance and to enhance +code readability. + +In our \c{run} function, we retrieve the bindings to the text +property. If the bound value is a string literal, we check +if it's the greeting we expect. + +\skipto void HelloWorldElementPass::run +\printuntil /^}/ + +\note Most of the time, a property will only have one +binding assigned to it. However, there might be for +instance a literal binding and a \l{Behavior} assigned +to the same property. + +Lastly, we need to create an instance of our pass, and +register it with the \l{QQmlSA::PassManager}{PassManager}. This is done by +adding +\skipto manager->registerElementPass +\printline manager->registerElementPass +to the \c{registerPasses} functions of our plugin. + +We can test our plugin by invoking \l{qmllint} on an example +file via +\badcode +qmllint -P /path/to/the/directory/containing/the/plugin --Plugin.HelloWorld.hello-world info test.qml +\endcode + +If \c{test.qml} looks like +\quotefromfile{tutorials/helloworld/chapter2/test.qml} +\skipto import +\printuntil + +we will get +\badcode +Info: test.qml:22:26: Incorrect greeting [Plugin.HelloWorld.hello-world] + MyText { text: "Goodbye world!" } + ^^^^^^^^^^^^^^^^ +Info: test.qml:19:19: Incorrect greeting [Plugin.HelloWorld.hello-world] + Text { text: "Goodbye world!" } +\endcode + +as the output. We can make a few observations here: +\list +\li The first \c{Text} does contain the expected greeting, so there's no warning +\li The second \c{Text} would at runtime have the wrong warning (\c{"Hello"} + instead of \c{"Hello world"}. However, this cannot be detected by qmllint + (in general), as there's no literal binding, but a binding to another property. + As we only check literal bindings, we simply skip over this binding. +\li For the literal binding in the third \c{Text} element, we correctly warn about + the wrong greeting. +\li As \c{NotText} does not derive from \c{Text}, the analysis will skip it, as + the \c{inherits} check will discard it. +\li The custom \c{MyText} element inherits from \c{Text}, and consequently we + see the expected warning. +\endlist + +In summary, we've seen the steps necessary to extend \c{qmllint} with custom passes, +and have also become aware of the limitations of static checks. + +*/ + +/*! +\page qqmlsa-tutorial3.html +\title QML Static Analysis 3 - Fixit Hints +\previouspage QML Static Analysis 2 - Custom Pass + +In this chapter we learn how to improve our custom warnings by amending them +with fixit hints. + +So far, we only created warning messages. However, sometimes we also want to +add a tip for the user how to fix the code. For that, we can pass an instance +of \c FixSuggestion to \l{QQmlSA::GenericPass::emitWarning}{emitWarning}. +A fix suggestion always consists of a description of what should be fixed, and +the location where it should apply. It can also feature a replacement text. +By default, the replacement text is only shown in the diagnostic message. +By calling \c{setAutoApplicable(true)} on the \c{FixSuggestion}, the user +can however apply the fix automatically via qmllint or the QML language +server. +It is important to only mark the suggestion as auto-applicable if the +resulting code is valid. +*/ diff --git a/src/qmlcompiler/qqmljsbasicblocks.cpp b/src/qmlcompiler/qqmljsbasicblocks.cpp index e0a9934ae..1db12e952 100644 --- a/src/qmlcompiler/qqmljsbasicblocks.cpp +++ b/src/qmlcompiler/qqmljsbasicblocks.cpp @@ -157,16 +157,6 @@ static bool containsAny(const ContainerA &container, const ContainerB &elements) return false; } -template -static bool containsAll(const ContainerA &container, const ContainerB &elements) -{ - for (const auto &element : elements) { - if (!container.contains(element)) - return false; - } - return true; -} - template, class KeyContainer = QList, class MappedContainer = QList> class NewFlatMap @@ -193,7 +183,7 @@ class NewFlatMap struct PendingBlock { - QList conversions; + QQmlJSBasicBlocks::Conversions conversions; int start = -1; bool registerActive = false; }; @@ -283,7 +273,7 @@ void QQmlJSBasicBlocks::populateReaderLocations() auto nextBlock = m_basicBlocks.find(block.start); auto currentBlock = nextBlock++; bool registerActive = block.registerActive; - QList conversions = block.conversions; + Conversions conversions = block.conversions; const auto blockEnd = (nextBlock == m_basicBlocks.end()) ? m_annotations.end() @@ -295,7 +285,7 @@ void QQmlJSBasicBlocks::populateReaderLocations() for (; blockInstr != blockEnd; ++blockInstr) { if (registerActive && blockInstr->second.typeConversions.contains(writtenRegister)) { - conversions.append(blockInstr.key()); + conversions.insert(blockInstr.key()); } for (auto readIt = blockInstr->second.readRegisters.constBegin(), @@ -322,12 +312,26 @@ void QQmlJSBasicBlocks::populateReaderLocations() // If we find that an already processed block has the register activated by this jump, // we need to re-evaluate it. We also need to propagate any newly found conversions. const auto processed = processedBlocks.find(blockStart); - if (processed == processedBlocks.end()) + if (processed == processedBlocks.end()) { blocks.append({conversions, blockStart, registerActive}); - else if (registerActive && !processed->registerActive) + } else if (registerActive && !processed->registerActive) { blocks.append({conversions, blockStart, registerActive}); - else if (!containsAll(processed->conversions, conversions)) - blocks.append({processed->conversions + conversions, blockStart, registerActive}); + } else { + + // TODO: Use unite() once it is fixed. + // We don't use unite() here since it would be more expensive. unite() + // effectively loops on only insert() and insert() does a number of checks + // each time. We trade those checks for calculating the hash twice on each + // iteration. Calculating the hash is very cheap for integers. + Conversions merged = processed->conversions; + for (const int conversion : std::as_const(conversions)) { + if (!merged.contains(conversion)) + merged.insert(conversion); + } + + if (merged.size() > processed->conversions.size()) + blocks.append({std::move(merged), blockStart, registerActive}); + } }; if (!currentBlock->second.jumpIsUnconditional && nextBlock != m_basicBlocks.end()) @@ -479,6 +483,11 @@ void QQmlJSBasicBlocks::adjustTypes() if (it->trackedTypes.size() != 1) continue; + // Don't adjust renamed values. We only adjust the originals. + const int writeLocation = it.key(); + if (writeLocation >= 0 && m_annotations[writeLocation].isRename) + continue; + if (!m_typeResolver->adjustTrackedType(it->trackedTypes[0], it->typeReaders.values())) setError(adjustErrorMessage(it->trackedTypes[0], it->typeReaders.values())); } diff --git a/src/qmlcompiler/qqmljsbasicblocks_p.h b/src/qmlcompiler/qqmljsbasicblocks_p.h index 7a3d39454..1053733eb 100644 --- a/src/qmlcompiler/qqmljsbasicblocks_p.h +++ b/src/qmlcompiler/qqmljsbasicblocks_p.h @@ -23,6 +23,8 @@ QT_BEGIN_NAMESPACE class Q_QMLCOMPILER_PRIVATE_EXPORT QQmlJSBasicBlocks : public QQmlJSCompilePass { public: + using Conversions = QSet; + struct BasicBlock { QList jumpOrigins; QList readRegisters; @@ -48,7 +50,7 @@ class Q_QMLCOMPILER_PRIVATE_EXPORT QQmlJSBasicBlocks : public QQmlJSCompilePass { QList trackedTypes; QHash typeReaders; - QHash> registerReadersAndConversions; + QHash registerReadersAndConversions; int trackedRegister; }; diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index 7ee6e24cb..313eac1bf 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -198,8 +198,9 @@ QT_WARNING_POP result.code += registerIt->variableName + u" = "_s; - const QString originalValue = u"*static_cast<"_s + castTargetName(original.storedType()) - + u"*>(argumentsPtr["_s + QString::number(argumentIndex) + u"])"_s; + const QString originalValue + = u"(*static_cast<"_s + castTargetName(original.storedType()) + + u"*>(argumentsPtr["_s + QString::number(argumentIndex) + u"]))"_s; if (needsConversion) result.code += conversion(original, argument, originalValue); @@ -448,6 +449,7 @@ void QQmlJSCodeGenerator::generate_MoveConst(int constIndex, int destTemp) input = toNumericString(v4Value.doubleValue()); } else { reject(u"unknown const type"_s); + return; } m_body += conversion(contained, changed, input) + u";\n"_s; } @@ -781,9 +783,15 @@ void QQmlJSCodeGenerator::generateEnumLookup(int index) { const QString enumMember = m_state.accumulatorOut().enumMember(); - // If we're referring to the type, there's nothing to do. - if (enumMember.isEmpty()) + if (enumMember.isEmpty()) { + // If we're referring to the type, there's nothing to do. + // However, we should not get here since no one can ever use the enum metatype. + // The lookup is dead code and should be optimized away. + // ... unless you are actually trying to store the metatype itself in a property. + // We cannot compile such code. + reject(u"Lookup of enum metatype"_s); return; + } // If the metaenum has the value, just use it and skip all the rest. const QQmlJSMetaEnum metaEnum = m_state.accumulatorOut().enumeration(); @@ -2484,9 +2492,8 @@ void QQmlJSCodeGenerator::generate_As(int lhs) : convertStored(inputContent.storedType(), genericContained, input); m_body += m_state.accumulatorVariableOut + u" = "_s; - if (m_typeResolver->equals( - m_state.accumulatorIn().storedType(), m_typeResolver->metaObjectType()) - && contained->isComposite()) { + if (contained->isComposite() && m_typeResolver->equals( + m_state.accumulatorIn().storedType(), m_typeResolver->metaObjectType())) { m_body += conversion( genericContained, outputContent, m_state.accumulatorVariableIn + u"->cast("_s + inputConversion + u')'); diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp index f68faf98d..95f944a43 100644 --- a/src/qmlcompiler/qqmljstyperesolver.cpp +++ b/src/qmlcompiler/qqmljstyperesolver.cpp @@ -719,14 +719,6 @@ QQmlJSScope::ConstPtr QQmlJSTypeResolver::merge(const QQmlJSScope::ConstPtr &a, if (isNumeric(a) && isNumeric(b)) return realType(); - const auto isStringCompatible = [&](const QQmlJSScope::ConstPtr &type) { - // TODO: We can losslessly coerce more types to string. Should we? - return isIntegral(type) || equals(type, stringType()); - }; - - if (isStringCompatible(a) && isStringCompatible(b)) - return stringType(); - if (isPrimitive(a) && isPrimitive(b)) return jsPrimitiveType(); diff --git a/src/qmldom/qqmldomreformatter.cpp b/src/qmldom/qqmldomreformatter.cpp index b0d61dafd..98ce433b8 100644 --- a/src/qmldom/qqmldomreformatter.cpp +++ b/src/qmldom/qqmldomreformatter.cpp @@ -267,9 +267,16 @@ class Rewriter : protected BaseVisitor { out(ast->lbracketToken); int baseIndent = lw.increaseIndent(1); - if (ast->elements) + if (ast->elements) { accept(ast->elements); - out(ast->commaToken); + out(ast->commaToken); + auto lastElement = lastListElement(ast->elements); + if (lastElement->element && cast(lastElement->element->initializer)) { + newLine(); + } + } else { + out(ast->commaToken); + } lw.decreaseIndent(1, baseIndent); out(ast->rbracketToken); return false; @@ -291,14 +298,22 @@ class Rewriter : protected BaseVisitor bool visit(PatternElementList *ast) override { for (PatternElementList *it = ast; it; it = it->next) { + const bool isObjectInitializer = + it->element && cast(it->element->initializer); + if (isObjectInitializer) + newLine(); + if (it->elision) accept(it->elision); if (it->elision && it->element) out(", "); if (it->element) accept(it->element); - if (it->next) + if (it->next) { out(", "); + if (isObjectInitializer) + newLine(); + } } return false; } @@ -309,23 +324,7 @@ class Rewriter : protected BaseVisitor PatternProperty *assignment = AST::cast(it->property); if (assignment) { preVisit(assignment); - const bool isStringLike = [this](const SourceLocation &loc) { - const auto name = loc2Str(loc); - if (name.first() == name.last()) { - if (name.first() == QStringLiteral("\'") - || name.first() == QStringLiteral("\"")) - return true; - } - return false; - }(assignment->name->propertyNameToken); - - if (isStringLike) - out("\""); - accept(assignment->name); - if (isStringLike) - out("\""); - bool useInitializer = false; const bool bindingIdentifierExist = !assignment->bindingIdentifier.isEmpty(); if (assignment->colonToken.length > 0) { @@ -396,7 +395,7 @@ class Rewriter : protected BaseVisitor } bool visit(StringLiteralPropertyName *ast) override { - out(ast->id.toString()); + out(ast->propertyNameToken); return true; } bool visit(NumericLiteralPropertyName *ast) override @@ -463,9 +462,7 @@ class Rewriter : protected BaseVisitor { accept(ast->base); out(ast->lparenToken); - int baseIndent = lw.increaseIndent(1); accept(ast->arguments); - lw.decreaseIndent(1, baseIndent); out(ast->rparenToken); return false; } diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp index 581c62036..9ab7a8a54 100644 --- a/src/qmlmodels/qqmldelegatemodel.cpp +++ b/src/qmlmodels/qqmldelegatemodel.cpp @@ -2060,26 +2060,28 @@ QQmlDelegateModelAttached *QQmlDelegateModel::qmlAttachedProperties(QObject *obj return new QQmlDelegateModelAttached(obj); } -bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups) +QQmlDelegateModelPrivate::InsertionResult +QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups) { if (!m_context || !m_context->isValid()) - return false; + return InsertionResult::Error; QQmlDelegateModelItem *cacheItem = m_adaptorModel.createItem(m_cacheMetaType, -1); if (!cacheItem) - return false; + return InsertionResult::Error; if (!object.isObject()) - return false; + return InsertionResult::Error; QV4::ExecutionEngine *v4 = object.as()->engine(); QV4::Scope scope(v4); QV4::ScopedObject o(scope, object); if (!o) - return false; + return InsertionResult::Error; QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly); QV4::ScopedValue propertyName(scope); QV4::ScopedValue v(scope); + const auto oldCache = m_cache; while (1) { propertyName = it.nextPropertyNameAsString(v); if (propertyName->isNull()) @@ -2088,6 +2090,9 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const propertyName->toQStringNoThrow(), QV4::ExecutionEngine::toVariant(v, QMetaType {})); } + const bool cacheModified = !m_cache.isSharedWith(oldCache); + if (cacheModified) + return InsertionResult::Retry; cacheItem->groups = groups | Compositor::UnresolvedFlag | Compositor::CacheFlag; @@ -2097,7 +2102,7 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const m_cache.insert(before.cacheIndex(), cacheItem); m_compositor.insert(before, nullptr, 0, 1, cacheItem->groups); - return true; + return InsertionResult::Success; } //============================================================================ @@ -3098,9 +3103,8 @@ void QQmlDelegateModelGroup::insert(QQmlV4Function *args) v = (*args)[i]; } - Compositor::insert_iterator before = index < model->m_compositor.count(group) - ? model->m_compositor.findInsertPosition(group, index) - : model->m_compositor.end(); + if (v->as()) + return; int groups = 1 << d->group; if (++i < args->length()) { @@ -3108,11 +3112,16 @@ void QQmlDelegateModelGroup::insert(QQmlV4Function *args) groups |= model->m_cacheMetaType->parseGroups(val); } - if (v->as()) { - return; - } else if (v->as()) { - model->insert(before, v, groups); - model->emitChanges(); + if (v->as()) { + auto insertionResult = QQmlDelegateModelPrivate::InsertionResult::Retry; + do { + Compositor::insert_iterator before = index < model->m_compositor.count(group) + ? model->m_compositor.findInsertPosition(group, index) + : model->m_compositor.end(); + insertionResult = model->insert(before, v, groups); + } while (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Retry); + if (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Success) + model->emitChanges(); } } @@ -3162,16 +3171,19 @@ void QQmlDelegateModelGroup::create(QQmlV4Function *args) groups |= model->m_cacheMetaType->parseGroups(val); } - Compositor::insert_iterator before = index < model->m_compositor.count(group) - ? model->m_compositor.findInsertPosition(group, index) - : model->m_compositor.end(); + auto insertionResult = QQmlDelegateModelPrivate::InsertionResult::Retry; + do { + Compositor::insert_iterator before = index < model->m_compositor.count(group) + ? model->m_compositor.findInsertPosition(group, index) + : model->m_compositor.end(); - index = before.index[d->group]; - group = d->group; + index = before.index[d->group]; + group = d->group; - if (!model->insert(before, v, groups)) { + insertionResult = model->insert(before, v, groups); + } while (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Retry); + if (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Error) return; - } } } if (index < 0 || index >= model->m_compositor.count(group)) { diff --git a/src/qmlmodels/qqmldelegatemodel_p_p.h b/src/qmlmodels/qqmldelegatemodel_p_p.h index 2c63859d4..247a56167 100644 --- a/src/qmlmodels/qqmldelegatemodel_p_p.h +++ b/src/qmlmodels/qqmldelegatemodel_p_p.h @@ -302,7 +302,12 @@ class QQmlDelegateModelPrivate : public QObjectPrivate, public QQmlDelegateModel void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) override; void delegateChanged(bool add = true, bool remove = true); - bool insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups); + enum class InsertionResult { + Success, + Error, + Retry + }; + InsertionResult insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups); int adaptorModelCount() const; diff --git a/src/qmltest/SignalSpy.qml b/src/qmltest/SignalSpy.qml index ca92f9113..88e0d431e 100644 --- a/src/qmltest/SignalSpy.qml +++ b/src/qmltest/SignalSpy.qml @@ -50,7 +50,7 @@ Item { // and since only the sender (target) being destroyed destroys a connection // in QML, and not the receiver (us/"spy"), we need to manually disconnect. // When QTBUG-118166 is implemented, we can remove this. - let signalFunc = target ? target[signalName] : null + let signalFunc = target ? qttest_signalFunc(target, signalName) : null if (signalFunc) signalFunc.disconnect(spy.qtest_activated) } @@ -201,8 +201,7 @@ Item { qtest_reentrancy_guard = true; if (qtest_prevTarget != null) { - var prevHandlerName = qtest_signalHandlerName(qtest_prevSignalName) - var prevFunc = qtest_prevTarget[prevHandlerName] + let prevFunc = qttest_signalFunc(qtest_prevTarget, qtest_prevSignalName) if (prevFunc) prevFunc.disconnect(spy.qtest_activated) qtest_prevTarget = null @@ -210,22 +209,16 @@ Item { } if (target != null && signalName != "") { // Look for the signal name in the object - var func = target[signalName] - if (typeof func !== "function") { - // If it is not a function, try looking for signal handler - // i.e. (onSignal) this is needed for cases where there is a property - // and a signal with the same name, e.g. Mousearea.pressed - func = target[qtest_signalHandlerName(signalName)] - } - if (func === undefined) { - spy.qtest_valid = false - console.log("Signal '" + signalName + "' not found") - } else { + let func = qttest_signalFunc(target, signalName) + if (func) { qtest_prevTarget = target qtest_prevSignalName = signalName func.connect(spy.qtest_activated) spy.qtest_valid = true spy.qtest_signalArguments = [] + } else { + spy.qtest_valid = false + console.log("Signal '" + signalName + "' not found") } } else { spy.qtest_valid = false @@ -246,4 +239,16 @@ Item { return sn return "on" + sn.substr(0, 1).toUpperCase() + sn.substr(1) } + + /*! \internal */ + function qttest_signalFunc(_target, _signalName) { + let signalFunc = _target[_signalName] + if (typeof signalFunc !== "function") { + // If it is not a function, try looking for signal handler + // i.e. (onSignal) this is needed for cases where there is a property + // and a signal with the same name, e.g. Mousearea.pressed + signalFunc = _target[qtest_signalHandlerName(_signalName)] + } + return signalFunc + } } diff --git a/src/qmltest/TestCase.qml b/src/qmltest/TestCase.qml index 66fd474e1..36f6226a3 100644 --- a/src/qmltest/TestCase.qml +++ b/src/qmltest/TestCase.qml @@ -165,6 +165,15 @@ import "testlogger.js" as TestLogger and mouseMove() methods can be used to simulate mouse events in a similar fashion. + If your test creates other windows, it's possible that those windows + become active, stealing the focus from the TestCase's window. To ensure + that the TestCase's window is active, use the following code: + + \code + testCase.Window.window.requestActivate() + tryCompare(testCase.Window.window, "active", true) + \endcode + \b{Note:} keyboard and mouse events can only be delivered once the main window has been shown. Attempts to deliver events before then will fail. Use the \l when and windowShown properties to track @@ -1895,10 +1904,12 @@ Item { qtest_results.finishTestData() qtest_runInternal("cleanup") qtest_destroyTemporaryObjects() - qtest_results.finishTestDataCleanup() + // wait(0) will call processEvents() so objects marked for deletion // in the test function will be deleted. wait(0) + + qtest_results.finishTestDataCleanup() } } diff --git a/src/qmltest/doc/src/qtquicktest-index.qdoc b/src/qmltest/doc/src/qtquicktest-index.qdoc index d5534052a..b65697927 100644 --- a/src/qmltest/doc/src/qtquicktest-index.qdoc +++ b/src/qmltest/doc/src/qtquicktest-index.qdoc @@ -168,7 +168,7 @@ setting context properties on the QML engine, amongst other things. The macro is identical to \c QUICK_TEST_MAIN, except that it takes an - additional \c QObject* argument. The test framework will call slots and + additional type argument. The test framework will call slots and invokable functions with the following names: \table diff --git a/src/qmltest/doc/src/qtquicktest.qdoc b/src/qmltest/doc/src/qtquicktest.qdoc index 357aa9b52..d349a725f 100644 --- a/src/qmltest/doc/src/qtquicktest.qdoc +++ b/src/qmltest/doc/src/qtquicktest.qdoc @@ -41,9 +41,9 @@ The \a name argument uniquely identifies this set of tests. This macro is identical to QUICK_TEST_MAIN(), except that it takes an - additional argument \a QuickTestSetupClass, a pointer to a QObject-derived - class. With this class it is possible to define additional setup code to - execute before running the QML test. + additional argument \a QuickTestSetupClass, the type of a QObject-derived + class which will be instantiated. With this class it is possible to define + additional setup code to execute before running the QML test. \note The macro assumes that your test sources are in the current directory, unless the \c QUICK_TEST_SOURCE_DIR environment variable is set. diff --git a/src/qmltoolingsettings/qqmltoolingsettings.cpp b/src/qmltoolingsettings/qqmltoolingsettings.cpp index 624d7675f..967318f18 100644 --- a/src/qmltoolingsettings/qqmltoolingsettings.cpp +++ b/src/qmltoolingsettings/qqmltoolingsettings.cpp @@ -18,7 +18,9 @@ using namespace Qt::StringLiterals; void QQmlToolingSettings::addOption(const QString &name, QVariant defaultValue) { - m_values[name] = defaultValue; + if (defaultValue.isValid()) { + m_values[name] = defaultValue; + } } bool QQmlToolingSettings::read(const QString &settingsFilePath) diff --git a/src/qmltyperegistrar/qqmltyperegistrar.cpp b/src/qmltyperegistrar/qqmltyperegistrar.cpp index ce201b776..001194669 100644 --- a/src/qmltyperegistrar/qqmltyperegistrar.cpp +++ b/src/qmltyperegistrar/qqmltyperegistrar.cpp @@ -83,11 +83,16 @@ int QmlTypeRegistrar::runExtract(const QString &baseName, const MetaTypesJsonPro fprintf(stderr, "Error: Cannot open %s for writing\n", qPrintable(headerFile.fileName())); return EXIT_FAILURE; } + + QString includeGuard = baseName; + static const QRegularExpression nonAlNum(QLatin1String("[^a-zA-Z0-9_]")); + includeGuard.replace(nonAlNum, QLatin1String("_")); + auto prefix = QString::fromLatin1( "#ifndef %1_H\n" "#define %1_H\n" "#include \n" - "#include \n").arg(baseName.toUpper()); + "#include \n").arg(includeGuard); const QStringList includes = processor.includes(); for (const QString &include: includes) prefix += u"\n#include <%1>"_s.arg(include); diff --git a/src/quick/doc/snippets/qml/externaldrag.qml b/src/quick/doc/snippets/qml/externaldrag.qml index 072612f0c..723701a7a 100644 --- a/src/quick/doc/snippets/qml/externaldrag.qml +++ b/src/quick/doc/snippets/qml/externaldrag.qml @@ -12,7 +12,6 @@ Item { color: "green" radius: 5 - Drag.active: dragHandler.active Drag.dragType: Drag.Automatic Drag.supportedActions: Qt.CopyAction Drag.mimeData: { @@ -30,8 +29,11 @@ Item { onActiveChanged: if (active) { parent.grabToImage(function(result) { - parent.Drag.imageSource = result.url; + parent.Drag.imageSource = result.url + parent.Drag.active = true }) + } else { + parent.Drag.active = false } } } diff --git a/src/quick/doc/snippets/qml/treeview/qml-customdelegate.qml b/src/quick/doc/snippets/qml/treeview/qml-customdelegate.qml index 97574487e..68f757f31 100644 --- a/src/quick/doc/snippets/qml/treeview/qml-customdelegate.qml +++ b/src/quick/doc/snippets/qml/treeview/qml-customdelegate.qml @@ -1,26 +1,31 @@ -// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only //![0] import QtQuick +import QtQuick.Controls -Window { - width: 600 - height: 400 +ApplicationWindow { + width: 800 + height: 600 visible: true TreeView { + id: treeView anchors.fill: parent + anchors.margins: 10 + clip: true + + selectionModel: ItemSelectionModel {} + // The model needs to be a QAbstractItemModel // model: yourTreeModel delegate: Item { - id: treeDelegate - implicitWidth: padding + label.x + label.implicitWidth + padding implicitHeight: label.implicitHeight * 1.5 - readonly property real indent: 20 + readonly property real indentation: 20 readonly property real padding: 5 // Assigned to by TreeView: @@ -29,24 +34,52 @@ Window { required property bool expanded required property int hasChildren required property int depth + required property int row + required property int column + required property bool current - TapHandler { - onTapped: treeView.toggleExpanded(row) + // Rotate indicator when expanded by the user + // (requires TreeView to have a selectionModel) + property Animation indicatorAnimation: NumberAnimation { + target: indicator + property: "rotation" + from: expanded ? 0 : 90 + to: expanded ? 90 : 0 + duration: 100 + easing.type: Easing.OutQuart } + TableView.onPooled: indicatorAnimation.complete() + TableView.onReused: if (current) indicatorAnimation.start() + onExpandedChanged: indicator.rotation = expanded ? 90 : 0 - Text { + Rectangle { + id: background + anchors.fill: parent + color: row === treeView.currentRow ? palette.highlight : "black" + opacity: (treeView.alternatingRows && row % 2 !== 0) ? 0.3 : 0.1 + } + + Label { id: indicator - visible: treeDelegate.isTreeNode && treeDelegate.hasChildren - x: padding + (treeDelegate.depth * treeDelegate.indent) - anchors.verticalCenter: label.verticalCenter - text: "▸" - rotation: treeDelegate.expanded ? 90 : 0 + x: padding + (depth * indentation) + anchors.verticalCenter: parent.verticalCenter + visible: isTreeNode && hasChildren + text: "▶" + + TapHandler { + onSingleTapped: { + let index = treeView.index(row, column) + treeView.selectionModel.setCurrentIndex(index, ItemSelectionModel.NoUpdate) + treeView.toggleExpanded(row) + } + } } - Text { + Label { id: label - x: padding + (treeDelegate.isTreeNode ? (treeDelegate.depth + 1) * treeDelegate.indent : 0) - width: treeDelegate.width - treeDelegate.padding - x + x: padding + (isTreeNode ? (depth + 1) * indentation : 0) + anchors.verticalCenter: parent.verticalCenter + width: parent.width - padding - x clip: true text: model.display } diff --git a/src/quick/doc/src/concepts/input/focus.qdoc b/src/quick/doc/src/concepts/input/focus.qdoc index 225eea778..8c6f73024 100644 --- a/src/quick/doc/src/concepts/input/focus.qdoc +++ b/src/quick/doc/src/concepts/input/focus.qdoc @@ -18,8 +18,8 @@ scope based extension to Qt's traditional keyboard focus model. When the user presses or releases a key, the following occurs: \list 1 \li Qt receives the key action and generates a key event. -\li If a \l QQuickWindow is the active window, the key event -is delivered to it. +\li If a \l QQuickWindow is the \l{QGuiApplication::focusWindow()}{focus window} +of the application, the key event is delivered to it. \li The key event is delivered by the scene to the \l Item with \e {active focus}. If no item has active focus, the key event is ignored. \li If the \l QQuickItem with active focus accepts the key event, propagation diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp index c5b7f1250..9372c30b7 100644 --- a/src/quick/handlers/qquickpointerhandler.cpp +++ b/src/quick/handlers/qquickpointerhandler.cpp @@ -195,11 +195,13 @@ void QQuickPointerHandler::setCursorShape(Qt::CursorShape shape) return; d->cursorShape = shape; d->cursorSet = true; + d->cursorDirty = true; if (auto *parent = parentItem()) { QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parent); itemPriv->hasCursorHandler = true; itemPriv->setHasCursorInChild(true); } + emit cursorShapeChanged(); } @@ -875,6 +877,7 @@ QQuickPointerHandlerPrivate::QQuickPointerHandlerPrivate() , hadKeepMouseGrab(false) , hadKeepTouchGrab(false) , cursorSet(false) + , cursorDirty(false) { } diff --git a/src/quick/handlers/qquickpointerhandler_p_p.h b/src/quick/handlers/qquickpointerhandler_p_p.h index 36797ef8b..6ff2e133e 100644 --- a/src/quick/handlers/qquickpointerhandler_p_p.h +++ b/src/quick/handlers/qquickpointerhandler_p_p.h @@ -57,6 +57,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerHandlerPrivate : public QObjectPrivate bool hadKeepMouseGrab : 1; // some handlers override target()->setKeepMouseGrab(); this remembers previous state bool hadKeepTouchGrab : 1; // some handlers override target()->setKeepTouchGrab(); this remembers previous state bool cursorSet : 1; + bool cursorDirty : 1; }; QT_END_NAMESPACE diff --git a/src/quick/handlers/qquicksinglepointhandler.cpp b/src/quick/handlers/qquicksinglepointhandler.cpp index 44db9d4f8..d2c38179a 100644 --- a/src/quick/handlers/qquicksinglepointhandler.cpp +++ b/src/quick/handlers/qquicksinglepointhandler.cpp @@ -117,11 +117,16 @@ void QQuickSinglePointHandler::handlePointerEventImpl(QPointerEvent *event) void QQuickSinglePointHandler::handleEventPoint(QPointerEvent *event, QEventPoint &point) { - if (point.state() != QEventPoint::Released) - return; + if (point.state() == QEventPoint::Released) { + // If it's a mouse or tablet event, with buttons, + // do not deactivate unless all acceptable buttons are released. + if (event->isSinglePointEvent()) { + const Qt::MouseButtons releasedButtons = static_cast(event)->buttons(); + if ((releasedButtons & acceptedButtons()) != Qt::NoButton) + return; + } - const Qt::MouseButtons releasedButtons = static_cast(event)->buttons(); - if ((releasedButtons & acceptedButtons()) == Qt::NoButton) { + // Deactivate this handler on release setExclusiveGrab(event, point, false); d_func()->reset(); } diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp index 5c1b59cf6..f662bcbc2 100644 --- a/src/quick/handlers/qquicktaphandler.cpp +++ b/src/quick/handlers/qquicktaphandler.cpp @@ -55,6 +55,7 @@ int QQuickTapHandler::m_touchMultiTapDistanceSquared(-1); QQuickTapHandler::QQuickTapHandler(QQuickItem *parent) : QQuickSinglePointHandler(parent) + , m_longPressThreshold(QGuiApplication::styleHints()->mousePressAndHoldInterval()) { if (m_mouseMultiClickDistanceSquared < 0) { m_multiTapInterval = qApp->styleHints()->mouseDoubleClickInterval(); @@ -78,6 +79,8 @@ bool QQuickTapHandler::wantsEventPoint(const QPointerEvent *event, const QEventP bool ret = false; bool overThreshold = d_func()->dragOverThreshold(point); if (overThreshold && m_gesturePolicy != DragWithinBounds) { + if (m_longPressTimer.isActive()) + qCDebug(lcTapHandler) << objectName() << "drag threshold exceeded"; m_longPressTimer.stop(); m_holdTimer.invalidate(); } @@ -146,18 +149,27 @@ void QQuickTapHandler::handleEventPoint(QPointerEvent *event, QEventPoint &point \qmlproperty real QtQuick::TapHandler::longPressThreshold The time in seconds that an \l eventPoint must be pressed in order to - trigger a long press gesture and emit the \l longPressed() signal. - If the point is released before this time limit, a tap can be detected - if the \l gesturePolicy constraint is satisfied. The default value is - QStyleHints::mousePressAndHoldInterval() converted to seconds. + trigger a long press gesture and emit the \l longPressed() signal, if the + value is greater than \c 0. If the point is released before this time + limit, a tap can be detected if the \l gesturePolicy constraint is + satisfied. If \c longPressThreshold is \c 0, the timer is disabled and the + signal will not be emitted. If \c longPressThreshold is set to \c undefined, + the default value is used instead, and can be read back from this property. + + The default value is QStyleHints::mousePressAndHoldInterval() converted to + seconds. */ qreal QQuickTapHandler::longPressThreshold() const { - return longPressThresholdMilliseconds() / 1000.0; + return m_longPressThreshold / qreal(1000); } void QQuickTapHandler::setLongPressThreshold(qreal longPressThreshold) { + if (longPressThreshold < 0) { + resetLongPressThreshold(); + return; + } int ms = qRound(longPressThreshold * 1000); if (m_longPressThreshold == ms) return; @@ -166,9 +178,14 @@ void QQuickTapHandler::setLongPressThreshold(qreal longPressThreshold) emit longPressThresholdChanged(); } -int QQuickTapHandler::longPressThresholdMilliseconds() const +void QQuickTapHandler::resetLongPressThreshold() { - return (m_longPressThreshold < 0 ? QGuiApplication::styleHints()->mousePressAndHoldInterval() : m_longPressThreshold); + int ms = QGuiApplication::styleHints()->mousePressAndHoldInterval(); + if (m_longPressThreshold == ms) + return; + + m_longPressThreshold = ms; + emit longPressThresholdChanged(); } void QQuickTapHandler::timerEvent(QTimerEvent *event) @@ -176,6 +193,7 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event) if (event->timerId() == m_longPressTimer.timerId()) { m_longPressTimer.stop(); qCDebug(lcTapHandler) << objectName() << "longPressed"; + m_longPressed = true; emit longPressed(); } else if (event->timerId() == m_doubleTapTimer.timerId()) { m_doubleTapTimer.stop(); @@ -350,7 +368,8 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event, connectPreRenderSignal(press); updateTimeHeld(); if (press) { - m_longPressTimer.start(longPressThresholdMilliseconds(), this); + if (m_longPressThreshold > 0) + m_longPressTimer.start(m_longPressThreshold, this); m_holdTimer.start(); } else { m_longPressTimer.stop(); @@ -364,7 +383,9 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event, setExclusiveGrab(event, point, press); } if (!cancel && !press && parentContains(point)) { - if (point.timeHeld() < longPressThreshold()) { + if (m_longPressed) { + qCDebug(lcTapHandler) << objectName() << "long press threshold" << longPressThreshold() << "exceeded:" << point.timeHeld(); + } else { // Assuming here that pointerEvent()->timestamp() is in ms. const quint64 ts = event->timestamp(); const quint64 interval = ts - m_lastTapTimestamp; @@ -410,10 +431,9 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QPointerEvent *event, m_lastTapTimestamp = ts; m_lastTapPos = point.scenePosition(); - } else { - qCDebug(lcTapHandler) << objectName() << "tap threshold" << longPressThreshold() << "exceeded:" << point.timeHeld(); } } + m_longPressed = false; emit pressedChanged(); if (!press && m_gesturePolicy != DragThreshold) { // on release, ungrab after emitting changed signals diff --git a/src/quick/handlers/qquicktaphandler_p.h b/src/quick/handlers/qquicktaphandler_p.h index 8c6b6d162..c37901b92 100644 --- a/src/quick/handlers/qquicktaphandler_p.h +++ b/src/quick/handlers/qquicktaphandler_p.h @@ -30,7 +30,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTapHandler : public QQuickSinglePointHandler Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged FINAL) Q_PROPERTY(int tapCount READ tapCount NOTIFY tapCountChanged FINAL) Q_PROPERTY(qreal timeHeld READ timeHeld NOTIFY timeHeldChanged FINAL) - Q_PROPERTY(qreal longPressThreshold READ longPressThreshold WRITE setLongPressThreshold NOTIFY longPressThresholdChanged FINAL) + Q_PROPERTY(qreal longPressThreshold READ longPressThreshold WRITE setLongPressThreshold NOTIFY longPressThresholdChanged RESET resetLongPressThreshold FINAL) Q_PROPERTY(GesturePolicy gesturePolicy READ gesturePolicy WRITE setGesturePolicy NOTIFY gesturePolicyChanged FINAL) Q_PROPERTY(QQuickTapHandler::ExclusiveSignals exclusiveSignals READ exclusiveSignals WRITE setExclusiveSignals NOTIFY exclusiveSignalsChanged REVISION(6, 5) FINAL) @@ -63,6 +63,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTapHandler : public QQuickSinglePointHandler qreal longPressThreshold() const; void setLongPressThreshold(qreal longPressThreshold); + void resetLongPressThreshold(); GesturePolicy gesturePolicy() const { return m_gesturePolicy; } void setGesturePolicy(GesturePolicy gesturePolicy); @@ -92,7 +93,6 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTapHandler : public QQuickSinglePointHandler private: void setPressed(bool press, bool cancel, QPointerEvent *event, QEventPoint &point); - int longPressThresholdMilliseconds() const; void connectPreRenderSignal(bool conn = true); void updateTimeHeld(); @@ -109,6 +109,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTapHandler : public QQuickSinglePointHandler GesturePolicy m_gesturePolicy = GesturePolicy::DragThreshold; ExclusiveSignals m_exclusiveSignals = NotExclusive; bool m_pressed = false; + bool m_longPressed = false; static quint64 m_multiTapInterval; static int m_mouseMultiClickDistanceSquared; diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp index e77998222..6218b3791 100644 --- a/src/quick/items/qquickanimatedimage.cpp +++ b/src/quick/items/qquickanimatedimage.cpp @@ -335,6 +335,9 @@ void QQuickAnimatedImage::load() movieRequestFinished(); } else { #if QT_CONFIG(qml_network) + if (d->reply) + return; + d->setStatus(Loading); d->setProgress(0); QNetworkRequest req(d->url); @@ -368,7 +371,16 @@ void QQuickAnimatedImage::movieRequestFinished() } d->redirectCount=0; - d->setMovie(new QMovie(d->reply)); + + auto movie = new QMovie(d->reply); + // From this point, we no longer need to handle the reply. + // I.e. it will be used only as a data source for QMovie, + // so it should live as long as the movie lives. + d->reply->disconnect(this); + d->reply->setParent(movie); + d->reply = nullptr; + + d->setMovie(movie); } #endif diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp index 628676a64..d171a7209 100644 --- a/src/quick/items/qquickborderimage.cpp +++ b/src/quick/items/qquickborderimage.cpp @@ -398,7 +398,9 @@ void QQuickBorderImage::requestFinished() { Q_D(QQuickBorderImage); - QSize impsize = d->pix.implicitSize(); + const QSize impsize = d->pix.implicitSize(); + setImplicitSize(impsize.width() / d->devicePixelRatio, impsize.height() / d->devicePixelRatio); + if (d->pix.isError()) { qmlWarning(this) << d->pix.error(); d->setStatus(Error); @@ -408,8 +410,6 @@ void QQuickBorderImage::requestFinished() d->setProgress(1); } - setImplicitSize(impsize.width() / d->devicePixelRatio, impsize.height() / d->devicePixelRatio); - if (sourceSize() != d->oldSourceSize) { d->oldSourceSize = sourceSize(); emit sourceSizeChanged(); diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index dee761622..3ab8efe0c 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -704,8 +704,7 @@ QMimeData *QQuickDragAttachedPrivate::createMimeData() const mimeData->setData(mimeType, text.toUtf8().constData()); } } else { - qmlWarning(q) << "Mime data contains a string, but mime type " << mimeType - << " is not a supported text type"; + mimeData->setData(mimeType, text.toUtf8()); } break; } diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index 7d3525212..26d53f6f0 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -274,10 +274,11 @@ void QQuickImageBase::loadEmptyUrl() Q_D(QQuickImageBase); d->pix.clear(this); d->setProgress(0); - d->setStatus(Null); + d->status = Null; // do not emit statusChanged until after setImplicitSize setImplicitSize(0, 0); // also called in QQuickImageBase::pixmapChange, but not QQuickImage/QQuickBorderImage overrides pixmapChange(); // This calls update() in QQuickBorderImage and QQuickImage, not in QQuickImageBase... + emit statusChanged(d->status); if (sourceSize() != d->oldSourceSize) { d->oldSourceSize = sourceSize(); emit sourceSizeChanged(); @@ -371,13 +372,15 @@ void QQuickImageBase::requestFinished() if (d->pix.isError()) { qmlWarning(this) << d->pix.error(); d->pix.clear(this); - d->setStatus(Error); + d->status = Error; d->setProgress(0); } else { - d->setStatus(Ready); + d->status = Ready; // do not emit statusChanged until after setImplicitSize d->setProgress(1); } + pixmapChange(); + emit statusChanged(d->status); if (sourceSize() != d->oldSourceSize) { d->oldSourceSize = sourceSize(); diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index e87aa54bd..c299ec514 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -4653,7 +4653,7 @@ static bool unwrapMapFromToFromItemArgs(QQmlV4Function *args, const QQuickItem * \input item.qdocinc mapping If \a item is a \c null value, this maps the point or rect from the coordinate system of - the root QML view. + the \l{Scene Coordinates}{scene}. The versions accepting point and rect are since Qt 5.15. */ @@ -4711,7 +4711,7 @@ QTransform QQuickItem::itemTransform(QQuickItem *other, bool *ok) const \input item.qdocinc mapping If \a item is a \c null value, this maps the point or rect to the coordinate system of the - root QML view. + \l{Scene Coordinates}{scene}. The versions accepting point and rect are since Qt 5.15. */ @@ -8961,6 +8961,16 @@ QDebug operator<<(QDebug debug, const QRectF rect(item->position(), QSizeF(item->width(), item->height())); debug << item->metaObject()->className() << '(' << static_cast(item); + + // Deferred properties will cause recursion when calling nameForObject + // before the component is completed, so guard against this situation. + if (item->isComponentComplete()) { + if (QQmlContext *context = qmlContext(item)) { + const auto objectId = context->nameForObject(item); + if (!objectId.isEmpty()) + debug << ", id=" << objectId; + } + } if (!item->objectName().isEmpty()) debug << ", name=" << item->objectName(); debug << ", parent=" << static_cast(item->parentItem()) diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 4a7b0d852..782e19024 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -473,6 +473,10 @@ public Q_SLOTS: friend class QAccessibleQuickItem; friend class QQuickAccessibleAttached; friend class QQuickAnchorChanges; +#ifndef QT_NO_DEBUG_STREAM + friend Q_QUICK_EXPORT QDebug operator<<(QDebug debug, QQuickItem *item); +#endif + Q_DISABLE_COPY(QQuickItem) Q_DECLARE_PRIVATE(QQuickItem) }; diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 6b95d366d..35613d60e 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -325,21 +325,21 @@ class FxListItemSG : public FxViewItem if (view->verticalLayoutDirection() == QQuickItemView::BottomToTop) { if (section()) pos += section()->height(); - return QPointF(itemX(), -itemHeight() - pos); + return QPointF(0, -itemHeight() - pos); } else { if (section()) pos += section()->height(); - return QPointF(itemX(), pos); + return QPointF(0, pos); } } else { if (view->effectiveLayoutDirection() == Qt::RightToLeft) { if (section()) pos += section()->width(); - return QPointF(-itemWidth() - pos, itemY()); + return QPointF(-itemWidth() - pos, 0); } else { if (section()) pos += section()->width(); - return QPointF(pos, itemY()); + return QPointF(pos, 0); } } } diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index 4b87f7b5f..5db6959ba 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -1848,7 +1848,8 @@ bool QQuickPathView::childMouseEventFilter(QQuickItem *i, QEvent *e) const bool filtered = stealThisEvent || grabberDisabled; if (filtered) - pe->setAccepted(false); + pe->setAccepted(stealThisEvent && grabber == this && grabber->isEnabled()); + return filtered; } else if (d->timer.isValid()) { d->timer.invalidate(); diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index 2e2be9200..325ca66ed 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -1636,6 +1636,8 @@ bool QQuickTableViewPrivate::startSelection(const QPointF &pos) if (selectionMode == QQuickTableView::SingleSelection || selectionMode == QQuickTableView::ContiguousSelection) clearSelection(); + else if (selectionModel) + existingSelection = selectionModel->selection(); selectionStartCell = QPoint(-1, -1); selectionEndCell = QPoint(-1, -1); @@ -1645,6 +1647,7 @@ bool QQuickTableViewPrivate::startSelection(const QPointF &pos) void QQuickTableViewPrivate::setSelectionStartPos(const QPointF &pos) { + Q_Q(QQuickTableView); if (loadedItems.isEmpty()) return; if (!selectionModel) { @@ -1663,12 +1666,20 @@ void QQuickTableViewPrivate::setSelectionStartPos(const QPointF &pos) } const QRect prevSelection = selection(); - const QPoint clampedCell = clampedCellAtPos(pos); + + QPoint clampedCell; + if (pos.x() == -1) { + // Special case: use current cell as start cell + clampedCell = q->cellAtIndex(selectionModel->currentIndex()); + } else { + clampedCell = clampedCellAtPos(pos); + if (cellIsValid(clampedCell)) + setCurrentIndex(clampedCell); + } + if (!cellIsValid(clampedCell)) return; - setCurrentIndex(clampedCell); - switch (selectionBehavior) { case QQuickTableView::SelectCells: selectionStartCell = clampedCell; @@ -1765,39 +1776,49 @@ void QQuickTableViewPrivate::updateSelection(const QRect &oldSelection, const QR const QRect oldRect = oldSelection.normalized(); const QRect newRect = newSelection.normalized(); + QItemSelection select; + QItemSelection deselect; + // Select cells inside the new selection rect { const QModelIndex startIndex = qaim->index(newRect.y(), newRect.x()); const QModelIndex endIndex = qaim->index(newRect.y() + newRect.height(), newRect.x() + newRect.width()); - selectionModel->select(QItemSelection(startIndex, endIndex), QItemSelectionModel::Select); + select = QItemSelection(startIndex, endIndex); } // Unselect cells in the new minus old rects if (oldRect.x() < newRect.x()) { const QModelIndex startIndex = qaim->index(oldRect.y(), oldRect.x()); const QModelIndex endIndex = qaim->index(oldRect.y() + oldRect.height(), newRect.x() - 1); - selectionModel->select(QItemSelection(startIndex, endIndex), QItemSelectionModel::Deselect); + deselect.merge(QItemSelection(startIndex, endIndex), QItemSelectionModel::Select); } else if (oldRect.x() + oldRect.width() > newRect.x() + newRect.width()) { const QModelIndex startIndex = qaim->index(oldRect.y(), newRect.x() + newRect.width() + 1); const QModelIndex endIndex = qaim->index(oldRect.y() + oldRect.height(), oldRect.x() + oldRect.width()); - selectionModel->select(QItemSelection(startIndex, endIndex), QItemSelectionModel::Deselect); + deselect.merge(QItemSelection(startIndex, endIndex), QItemSelectionModel::Select); } if (oldRect.y() < newRect.y()) { const QModelIndex startIndex = qaim->index(oldRect.y(), oldRect.x()); const QModelIndex endIndex = qaim->index(newRect.y() - 1, oldRect.x() + oldRect.width()); - selectionModel->select(QItemSelection(startIndex, endIndex), QItemSelectionModel::Deselect); + deselect.merge(QItemSelection(startIndex, endIndex), QItemSelectionModel::Select); } else if (oldRect.y() + oldRect.height() > newRect.y() + newRect.height()) { const QModelIndex startIndex = qaim->index(newRect.y() + newRect.height() + 1, oldRect.x()); const QModelIndex endIndex = qaim->index(oldRect.y() + oldRect.height(), oldRect.x() + oldRect.width()); - selectionModel->select(QItemSelection(startIndex, endIndex), QItemSelectionModel::Deselect); + deselect.merge(QItemSelection(startIndex, endIndex), QItemSelectionModel::Select); } + + // Don't clear the selection that existed before the user started a new selection block + deselect.merge(existingSelection, QItemSelectionModel::Deselect); + + selectionModel->select(deselect, QItemSelectionModel::Deselect); + selectionModel->select(select, QItemSelectionModel::Select); } void QQuickTableViewPrivate::clearSelection() { selectionStartCell = QPoint(-1, -1); selectionEndCell = QPoint(-1, -1); + existingSelection.clear(); if (selectionModel) selectionModel->clearSelection(); diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h index 60ccb26c9..a3768fda7 100644 --- a/src/quick/items/qquicktableview_p_p.h +++ b/src/quick/items/qquicktableview_p_p.h @@ -377,6 +377,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTableViewPrivate : public QQuickFlickablePriv QPoint selectionStartCell = {-1, -1}; QPoint selectionEndCell = {-1, -1}; + QItemSelection existingSelection; QMargins edgesBeforeRebuild; QSize tableSizeBeforeRebuild; diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index ed1b70fb1..85c4c54b2 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -204,7 +204,7 @@ void QQuickTextPrivate::setBottomPadding(qreal value, bool reset) Used to decide if the Text should use antialiasing or not. Only Text with renderType of Text.NativeRendering can disable antialiasing. - The default is true. + The default is \c true. */ void QQuickText::q_updateLayout() @@ -1301,8 +1301,8 @@ void QQuickTextPrivate::updateDocumentText() \inherits Item \brief Specifies how to add formatted text to a scene. - Text items can display both plain and rich text. For example, red text with - a specific font and size can be defined like this: + Text items can display both plain and rich text. For example, you can define + red text with a specific font and size like this: \qml Text { @@ -1313,25 +1313,47 @@ void QQuickTextPrivate::updateDocumentText() } \endqml - Rich text is defined using HTML-style markup: + Use HTML-style markup or Markdown to define rich text: + \if defined(onlinedocs) + \tab {build-qt-app}{tab-html}{HTML-style}{checked} + \tab {build-qt-app}{tab-md}{Markdown}{} + \tabcontent {tab-html} + \else + \section1 Using HTML-style + \endif \qml Text { text: "Hello World!" } \endqml + \if defined(onlinedocs) + \endtabcontent + \tabcontent {tab-md} + \else + \section1 Using Markdown + \endif + \qml + Text { + text: "**Hello** *World!*" + } + \endqml + \if defined(onlinedocs) + \endtabcontent + \endif \image declarative-text.png - If height and width are not explicitly set, Text will attempt to determine how - much room is needed and set it accordingly. Unless \l wrapMode is set, it will always - prefer width to height (all text will be placed on a single line). + If height and width are not explicitly set, Text will try to determine how + much room is needed and set it accordingly. Unless \l wrapMode is set, it + will always prefer width to height (all text will be placed on a single + line). - The \l elide property can alternatively be used to fit a single line of - plain text to a set width. + To fit a single line of plain text to a set width, you can use the \l elide + property. - Note that the \l{Supported HTML Subset} is limited. Also, if the text contains - HTML img tags that load remote images, the text is reloaded. + Note that the \l{Supported HTML Subset} is limited. Also, if the text + contains HTML img tags that load remote images, the text is reloaded. Text provides read-only text. For editable text, see \l TextEdit. @@ -1359,7 +1381,7 @@ QQuickText::~QQuickText() \qmlproperty bool QtQuick::Text::clip This property holds whether the text is clipped. - Note that if the text does not fit in the bounding rectangle it will be abruptly chopped. + Note that if the text does not fit in the bounding rectangle, it will be abruptly chopped. If you want to display potentially long text in a limited space, you probably want to use \c elide instead. */ @@ -1448,7 +1470,8 @@ QQuickText::~QQuickText() Sets the family name of the font. - The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]". + The family name is case insensitive and may optionally include a foundry + name, for example "Helvetica [Cronyx]". If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen. If the family isn't available a family will be set using the font matching algorithm. */ @@ -1572,7 +1595,7 @@ QQuickText::~QQuickText() \value Font.PreferDefaultHinting Use the default hinting level for the target platform. \value Font.PreferNoHinting If possible, render text without hinting the outlines of the glyphs. The text layout will be typographically accurate, using the same metrics - as are used e.g. when printing. + as are used, for example, when printing. \value Font.PreferVerticalHinting If possible, render text with no horizontal hinting, but align glyphs to the pixel grid in the vertical direction. The text will appear crisper on displays where the density is too low to give an accurate rendering @@ -1609,7 +1632,7 @@ QQuickText::~QQuickText() Sometimes, a font will apply complex rules to a set of characters in order to display them correctly. In some writing systems, such as Brahmic scripts, this is - required in order for the text to be legible, but in e.g. Latin script, it is merely + required in order for the text to be legible, but in for example Latin script, it is merely a cosmetic feature. Setting the \c preferShaping property to false will disable all such features when they are not required, which will improve performance in most cases. @@ -1632,7 +1655,7 @@ QQuickText::~QQuickText() The font features are represented by a map from four-letter tags to integer values. This integer value passed along with the tag in most cases represents a boolean value: A zero value means the feature is disabled, and a non-zero value means it is enabled. For certain font features, - however, it may have other intepretations. For example, when applied to the \c salt feature, the + however, it may have other interpretations. For example, when applied to the \c salt feature, the value is an index that specifies the stylistic alternative to use. For example, the \c frac font feature will convert diagonal fractions separated with a slash @@ -1650,8 +1673,9 @@ QQuickText::~QQuickText() } \endqml - Multiple features can be assigned values in the same mapping. For instance, if we would like - to also disable kerning for the font, we can explicitly disable this as follows: + Multiple features can be assigned values in the same mapping. For instance, + if you would like to also disable kerning for the font, you can explicitly + disable this as follows: \qml Text { @@ -1680,8 +1704,8 @@ QQuickText::~QQuickText() systems where the use of ligature is cosmetic. For writing systems where ligatures are required, the features will remain in their default state. The values set using \c font.features will override the default behavior. If, for instance, \c{"kern"} is set to 1, then kerning will - always be enabled, egardless of whether the \l font.kerning property is set to false. Similarly, - if it is set to 0, then it will always be disabled. + always be enabled, regardless of whether the \l font.kerning property is set to false. Similarly, + if it is set to \c 0, it will always be disabled. \sa QFont::setFeature() //! [qml-font-features] @@ -2206,7 +2230,7 @@ void QQuickText::resetMaximumLineCount() \l {https://guides.github.com/features/mastering-markdown/}{GitHub} extensions for tables and task lists (since 5.14) - If the text format is \c Text.AutoText the Text item + If the text format is \c Text.AutoText, the Text item will automatically determine whether the text should be treated as styled text. This determination is made using Qt::mightBeRichText(), which can detect the presence of an HTML tag on the first line of text, @@ -2335,7 +2359,7 @@ void QQuickText::setElideMode(QQuickText::TextElideMode mode) /*! \qmlproperty url QtQuick::Text::baseUrl - This property specifies a base URL which is used to resolve relative URLs + This property specifies a base URL that is used to resolve relative URLs within the text. Urls are resolved to be within the same directory as the target of the base @@ -2627,7 +2651,7 @@ void QQuickText::updatePolish() \qmlproperty real QtQuick::Text::contentWidth Returns the width of the text, including width past the width - which is covered due to insufficient wrapping if WrapMode is set. + that is covered due to insufficient wrapping if WrapMode is set. */ qreal QQuickText::contentWidth() const { @@ -2639,7 +2663,7 @@ qreal QQuickText::contentWidth() const \qmlproperty real QtQuick::Text::contentHeight Returns the height of the text, including height past the height - which is covered due to there being more text than fits in the set height. + that is covered due to there being more text than fits in the set height. */ qreal QQuickText::contentHeight() const { @@ -3377,7 +3401,7 @@ void QQuickText::resetBottomPadding() */ /*! - \qmlproperty string QtQuick::Text::fontInfo.pixelSize + \qmlproperty int QtQuick::Text::fontInfo.pixelSize \since 5.9 The pixel size of the font info that has been resolved for the current font @@ -3414,7 +3438,7 @@ QJSValue QQuickText::fontInfo() const in a text flow. Note that the advance can be negative if the text flows from - the right to the left. + right to left. */ QSizeF QQuickText::advance() const { diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 990b6ec10..50e9d1feb 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -715,9 +715,8 @@ QQuickTextEdit::HAlignment QQuickTextEdit::hAlign() const void QQuickTextEdit::setHAlign(HAlignment align) { Q_D(QQuickTextEdit); - bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror; - d->hAlignImplicit = false; - if (d->setHAlign(align, forceAlign) && isComponentComplete()) { + + if (d->setHAlign(align, true) && isComponentComplete()) { d->updateDefaultTextOption(); updateSize(); } @@ -752,21 +751,34 @@ QQuickTextEdit::HAlignment QQuickTextEdit::effectiveHAlign() const return effectiveAlignment; } -bool QQuickTextEditPrivate::setHAlign(QQuickTextEdit::HAlignment alignment, bool forceAlign) +bool QQuickTextEditPrivate::setHAlign(QQuickTextEdit::HAlignment align, bool forceAlign) { Q_Q(QQuickTextEdit); - if (hAlign != alignment || forceAlign) { - QQuickTextEdit::HAlignment oldEffectiveHAlign = q->effectiveHAlign(); - hAlign = alignment; - emit q->horizontalAlignmentChanged(alignment); - if (oldEffectiveHAlign != q->effectiveHAlign()) - emit q->effectiveHorizontalAlignmentChanged(); + if (hAlign == align && !forceAlign) + return false; + + const bool wasImplicit = hAlignImplicit; + const auto oldEffectiveHAlign = q->effectiveHAlign(); + + hAlignImplicit = !forceAlign; + if (hAlign != align) { + hAlign = align; + emit q->horizontalAlignmentChanged(align); + } + + if (q->effectiveHAlign() != oldEffectiveHAlign) { + emit q->effectiveHorizontalAlignmentChanged(); return true; } + + if (forceAlign && wasImplicit) { + // QTBUG-120052 - when horizontal text alignment is set explicitly, + // we need notify any other controls that may depend on it, like QQuickPlaceholderText + emit q->effectiveHorizontalAlignmentChanged(); + } return false; } - Qt::LayoutDirection QQuickTextEditPrivate::textDirection(const QString &text) const { const QChar *character = text.constData(); @@ -789,20 +801,22 @@ Qt::LayoutDirection QQuickTextEditPrivate::textDirection(const QString &text) co bool QQuickTextEditPrivate::determineHorizontalAlignment() { Q_Q(QQuickTextEdit); - if (hAlignImplicit && q->isComponentComplete()) { - Qt::LayoutDirection direction = contentDirection; + if (!hAlignImplicit || !q->isComponentComplete()) + return false; + + Qt::LayoutDirection direction = contentDirection; #if QT_CONFIG(im) - if (direction == Qt::LayoutDirectionAuto) { - const QString preeditText = control->textCursor().block().layout()->preeditAreaText(); - direction = textDirection(preeditText); - } - if (direction == Qt::LayoutDirectionAuto) - direction = qGuiApp->inputMethod()->inputDirection(); + if (direction == Qt::LayoutDirectionAuto) { + const QString preeditText = control->textCursor().block().layout()->preeditAreaText(); + direction = textDirection(preeditText); + } + if (direction == Qt::LayoutDirectionAuto) + direction = qGuiApp->inputMethod()->inputDirection(); #endif - return setHAlign(direction == Qt::RightToLeft ? QQuickTextEdit::AlignRight : QQuickTextEdit::AlignLeft); - } - return false; + const auto implicitHAlign = direction == Qt::RightToLeft ? + QQuickTextEdit::AlignRight : QQuickTextEdit::AlignLeft; + return setHAlign(implicitHAlign); } void QQuickTextEditPrivate::mirrorChange() @@ -1513,14 +1527,35 @@ void QQuickTextEdit::setInputMethodHints(Qt::InputMethodHints hints) void QQuickTextEdit::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) { Q_D(QQuickTextEdit); - if (!d->inLayout && ((newGeometry.width() != oldGeometry.width() && widthValid()) - || (newGeometry.height() != oldGeometry.height() && heightValid()))) { + if (!d->inLayout && ((newGeometry.width() != oldGeometry.width()) + || (newGeometry.height() != oldGeometry.height()))) { updateSize(); updateWholeDocument(); - moveCursorDelegate(); + if (widthValid() || heightValid()) + moveCursorDelegate(); } QQuickImplicitSizeItem::geometryChange(newGeometry, oldGeometry); +} + +void QQuickTextEdit::itemChange(ItemChange change, const ItemChangeData &value) +{ + Q_D(QQuickTextEdit); + Q_UNUSED(value); + switch (change) { + case ItemDevicePixelRatioHasChanged: + if (d->renderType == NativeRendering) { + // Native rendering optimizes for a given pixel grid, so its results must not be scaled. + // Text layout code respects the current device pixel ratio automatically, we only need + // to rerun layout after the ratio changed. + updateSize(); + updateWholeDocument(); + } + break; + default: + break; + } + QQuickImplicitSizeItem::itemChange(change, value); } /*! diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h index f64332d50..49d014b3e 100644 --- a/src/quick/items/qquicktextedit_p.h +++ b/src/quick/items/qquicktextedit_p.h @@ -366,6 +366,7 @@ private Q_SLOTS: #endif void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; + void itemChange(ItemChange change, const ItemChangeData &value) override; bool event(QEvent *) override; void keyPressEvent(QKeyEvent *) override; diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 5bd17f1aa..f8c68b3f7 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -540,9 +540,8 @@ QQuickTextInput::HAlignment QQuickTextInput::hAlign() const void QQuickTextInput::setHAlign(HAlignment align) { Q_D(QQuickTextInput); - bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror; - d->hAlignImplicit = false; - if (d->setHAlign(align, forceAlign) && isComponentComplete()) { + + if (d->setHAlign(align, true) && isComponentComplete()) { d->updateLayout(); updateCursorRectangle(); } @@ -577,17 +576,34 @@ QQuickTextInput::HAlignment QQuickTextInput::effectiveHAlign() const return effectiveAlignment; } -bool QQuickTextInputPrivate::setHAlign(QQuickTextInput::HAlignment alignment, bool forceAlign) +bool QQuickTextInputPrivate::setHAlign(QQuickTextInput::HAlignment align, bool forceAlign) { Q_Q(QQuickTextInput); - if ((hAlign != alignment || forceAlign) && alignment <= QQuickTextInput::AlignHCenter) { // justify not supported - QQuickTextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign(); - hAlign = alignment; - emit q->horizontalAlignmentChanged(alignment); - if (oldEffectiveHAlign != q->effectiveHAlign()) - emit q->effectiveHorizontalAlignmentChanged(); + if (align > QQuickTextInput::AlignHCenter) + return false; // justify is not supported + + if (hAlign == align && !forceAlign) + return false; + + const bool wasImplicit = hAlignImplicit; + const auto oldEffectiveHAlign = q->effectiveHAlign(); + + hAlignImplicit = !forceAlign; + if (hAlign != align) { + hAlign = align; + emit q->horizontalAlignmentChanged(align); + } + + if (q->effectiveHAlign() != oldEffectiveHAlign) { + emit q->effectiveHorizontalAlignmentChanged(); return true; } + + if (forceAlign && wasImplicit) { + // QTBUG-120052 - when horizontal text alignment is set explicitly, + // we need notify any other controls that may depend on it, like QQuickPlaceholderText + emit q->effectiveHorizontalAlignmentChanged(); + } return false; } @@ -631,16 +647,19 @@ Qt::LayoutDirection QQuickTextInputPrivate::layoutDirection() const bool QQuickTextInputPrivate::determineHorizontalAlignment() { - if (hAlignImplicit) { - // if no explicit alignment has been set, follow the natural layout direction of the text - Qt::LayoutDirection direction = textDirection(); + if (!hAlignImplicit) + return false; + + // if no explicit alignment has been set, follow the natural layout direction of the text + Qt::LayoutDirection direction = textDirection(); #if QT_CONFIG(im) - if (direction == Qt::LayoutDirectionAuto) - direction = QGuiApplication::inputMethod()->inputDirection(); + if (direction == Qt::LayoutDirectionAuto) + direction = QGuiApplication::inputMethod()->inputDirection(); #endif - return setHAlign(direction == Qt::RightToLeft ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft); - } - return false; + + const auto implicitHAlign = direction == Qt::RightToLeft ? + QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft; + return setHAlign(implicitHAlign); } QQuickTextInput::VAlignment QQuickTextInput::vAlign() const @@ -1760,6 +1779,26 @@ void QQuickTextInput::geometryChange(const QRectF &newGeometry, QQuickImplicitSizeItem::geometryChange(newGeometry, oldGeometry); } +void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value) +{ + Q_D(QQuickTextInput); + Q_UNUSED(value); + switch (change) { + case ItemDevicePixelRatioHasChanged: + if (d->renderType == NativeRendering) { + // Native rendering optimizes for a given pixel grid, so its results must not be scaled. + // Text layout code respects the current device pixel ratio automatically, we only need + // to rerun layout after the ratio changed. + d->updateLayout(); + } + break; + + default: + break; + } + QQuickImplicitSizeItem::itemChange(change, value); +} + void QQuickTextInputPrivate::ensureVisible(int position, int preeditCursor, int preeditLength) { Q_Q(QQuickTextInput); diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h index 515c696b0..ca97d6fd0 100644 --- a/src/quick/items/qquicktextinput_p.h +++ b/src/quick/items/qquicktextinput_p.h @@ -349,6 +349,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem, pu #endif void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; + void itemChange(ItemChange change, const ItemChangeData &value) override; void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; diff --git a/src/quick/items/qquicktreeview.cpp b/src/quick/items/qquicktreeview.cpp index 488e9eaa4..f2613b4f4 100644 --- a/src/quick/items/qquicktreeview.cpp +++ b/src/quick/items/qquicktreeview.cpp @@ -42,7 +42,7 @@ a set of properties that can be used to position and render each node in the tree correctly. - An example of a custom delegate is shown below: + An example of a custom delegate with an animating indicator is shown below: \snippet qml/treeview/qml-customdelegate.qml 0 @@ -344,56 +344,33 @@ void QQuickTreeViewPrivate::updateSelection(const QRect &oldSelection, const QRe { Q_Q(QQuickTreeView); - const QRect oldRect = oldSelection.normalized(); - const QRect newRect = newSelection.normalized(); - if (oldSelection == newSelection) return; - // Select the rows inside newRect that doesn't overlap with oldRect - for (int row = newRect.y(); row <= newRect.y() + newRect.height(); ++row) { - if (oldRect.y() != -1 && oldRect.y() <= row && row <= oldRect.y() + oldRect.height()) - continue; - const QModelIndex startIndex = q->index(row, newRect.x()); - const QModelIndex endIndex = q->index(row, newRect.x() + newRect.width()); - selectionModel->select(QItemSelection(startIndex, endIndex), QItemSelectionModel::Select); + QItemSelection select; + QItemSelection deselect; + + // Because each row can have a different parent, we need to create separate QItemSelections + // per row. But all the cells in a given row have the same parent, so they can be combined. + // As a result, the final QItemSelection can end up more fragmented compared to a selection + // in QQuickTableView, where all cells have the same parent. In the end, if TreeView has + // a lot of columns and the selection mode is "SelectCells", using the mouse to adjust + // a selection containing a _large_ number of columns can be slow. + const QRect cells = newSelection.normalized(); + for (int row = cells.y(); row <= cells.y() + cells.height(); ++row) { + const QModelIndex startIndex = q->index(row, cells.x()); + const QModelIndex endIndex = q->index(row, cells.x() + cells.width()); + select.merge(QItemSelection(startIndex, endIndex), QItemSelectionModel::Select); } - if (oldRect.x() != -1) { - // Since oldRect is valid, this update is a continuation of an already existing selection! - - // Select the columns inside newRect that don't overlap with oldRect - for (int column = newRect.x(); column <= newRect.x() + newRect.width(); ++column) { - if (oldRect.x() <= column && column <= oldRect.x() + oldRect.width()) - continue; - for (int row = newRect.y(); row <= newRect.y() + newRect.height(); ++row) - selectionModel->select(q->index(row, column), QItemSelectionModel::Select); - } - - // Unselect the rows inside oldRect that don't overlap with newRect - for (int row = oldRect.y(); row <= oldRect.y() + oldRect.height(); ++row) { - if (newRect.y() <= row && row <= newRect.y() + newRect.height()) - continue; - const QModelIndex startIndex = q->index(row, oldRect.x()); - const QModelIndex endIndex = q->index(row, oldRect.x() + oldRect.width()); - selectionModel->select(QItemSelection(startIndex, endIndex), QItemSelectionModel::Deselect); - } - - // Unselect the columns inside oldRect that don't overlap with newRect - for (int column = oldRect.x(); column <= oldRect.x() + oldRect.width(); ++column) { - if (newRect.x() <= column && column <= newRect.x() + newRect.width()) - continue; - // Since we're not allowed to call select/unselect on the selectionModel with - // indices from different parents, and since indicies from different parents are - // expected when working with trees, we need to unselect the indices in the column - // one by one, rather than the whole column in one go. This, however, can cause a - // lot of selection fragments in the selectionModel, which eventually can hurt - // performance. But large selections containing a lot of columns is not normally - // the case for a treeview, so accept this potential corner case for now. - for (int row = newRect.y(); row <= newRect.y() + newRect.height(); ++row) - selectionModel->select(q->index(row, column), QItemSelectionModel::Deselect); - } + const QModelIndexList indexes = selectionModel->selection().indexes(); + for (const QModelIndex &index : indexes) { + if (!select.contains(index) && !existingSelection.contains(index)) + deselect.merge(QItemSelection(index, index), QItemSelectionModel::Select); } + + selectionModel->select(deselect, QItemSelectionModel::Deselect); + selectionModel->select(select, QItemSelectionModel::Select); } QQuickTreeView::QQuickTreeView(QQuickItem *parent) diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index c9fe19384..d433b2b12 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -1677,11 +1678,14 @@ void QQuickWindowPrivate::updateCursor(const QPointF &scenePos, QQuickItem *root if (!rootItem) rootItem = contentItem; auto cursorItemAndHandler = findCursorItemAndHandler(rootItem, scenePos); - if (cursorItem != cursorItemAndHandler.first || cursorHandler != cursorItemAndHandler.second) { + if (cursorItem != cursorItemAndHandler.first || cursorHandler != cursorItemAndHandler.second || + (cursorItemAndHandler.second && QQuickPointerHandlerPrivate::get(cursorItemAndHandler.second)->cursorDirty)) { QWindow *renderWindow = QQuickRenderControl::renderWindowFor(q); QWindow *window = renderWindow ? renderWindow : q; cursorItem = cursorItemAndHandler.first; cursorHandler = cursorItemAndHandler.second; + if (cursorHandler) + QQuickPointerHandlerPrivate::get(cursorItemAndHandler.second)->cursorDirty = false; if (cursorItem) { const auto cursor = QQuickItemPrivate::get(cursorItem)->effectiveCursor(cursorHandler); qCDebug(lcHoverTrace) << "setting cursor" << cursor << "from" << cursorHandler << "or" << cursorItem; @@ -3457,6 +3461,8 @@ void QQuickWindow::endExternalCommands() Setting visible to false is the same as setting \l visibility to \l {QWindow::}{Hidden}. + The default value is \c false, unless overridden by setting \l visibility. + \sa visibility */ diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index a034906c4..4baa1f0f6 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -1222,8 +1222,13 @@ void Renderer::nodeWasRemoved(Node *node) if (e) { e->removed = true; m_elementsToDelete.add(e); - if (m_renderNodeElements.isEmpty()) + if (m_renderNodeElements.isEmpty()) { m_forceNoDepthBuffer = false; + // Must have a full rebuild given useDepthBuffer() now returns + // a different value than before, meaning there can once again + // be an opaque pass. + m_rebuild |= FullRebuild; + } if (e->batch != nullptr) e->batch->needsPurge = true; diff --git a/src/quick/scenegraph/qsgdefaultglyphnode.cpp b/src/quick/scenegraph/qsgdefaultglyphnode.cpp index f9133455c..445f338bb 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode.cpp @@ -47,11 +47,14 @@ void QSGDefaultGlyphNode::update() QRawFont font = m_glyphs.rawFont(); QMargins margins(0, 0, 0, 0); - if (m_style == QQuickText::Normal) { + const auto *fontEngine = QRawFontPrivate::get(font)->fontEngine; + const bool isColorFont = fontEngine->glyphFormat == QFontEngine::Format_ARGB; + + if (m_style == QQuickText::Normal || isColorFont) { QFontEngine::GlyphFormat glyphFormat; // Don't try to override glyph format of color fonts - if (QRawFontPrivate::get(font)->fontEngine->glyphFormat == QFontEngine::Format_ARGB) { + if (isColorFont) { glyphFormat = QFontEngine::Format_None; } else { switch (m_preferredAntialiasingMode) { diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 8ecfd997c..58aa2d08c 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -258,6 +258,15 @@ void QSGRenderLoop::setInstance(QSGRenderLoop *instance) void QSGRenderLoop::handleContextCreationFailure(QQuickWindow *window) { + // Must always be called on the gui thread. + + // Guard for recursion; relevant due to the MessageBox() on Windows. + static QSet recurseGuard; + if (recurseGuard.contains(window)) + return; + + recurseGuard.insert(window); + QString translatedMessage; QString untranslatedMessage; QQuickWindowPrivate::rhiCreationFailureMessage(QSGRhiSupport::instance()->rhiBackendName(), @@ -278,6 +287,8 @@ void QSGRenderLoop::handleContextCreationFailure(QQuickWindow *window) #endif // Q_OS_WIN if (!signalEmitted) qFatal("%s", qPrintable(untranslatedMessage)); + + recurseGuard.remove(window); } #ifdef ENABLE_DEFAULT_BACKEND diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp index 1ac87b6b7..83d5181c3 100644 --- a/src/quick/util/qquickanimatorjob.cpp +++ b/src/quick/util/qquickanimatorjob.cpp @@ -592,7 +592,7 @@ void QQuickUniformAnimatorJob::setTarget(QQuickItem *target) void QQuickUniformAnimatorJob::updateCurrentTime(int time) { - if (!m_effect) + if (!m_effect || m_target != m_effect) return; m_value = m_from + (m_to - m_from) * progress(time); @@ -617,7 +617,7 @@ void QQuickUniformAnimatorJob::postSync() void QQuickUniformAnimatorJob::invalidate() { - m_effect = nullptr; + } #endif diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h index fef29ac38..9a1ad53e7 100644 --- a/src/quick/util/qquickanimatorjob_p.h +++ b/src/quick/util/qquickanimatorjob_p.h @@ -280,7 +280,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickUniformAnimatorJob : public QQuickAnimatorJob private: QByteArray m_uniform; - QQuickShaderEffect *m_effect = nullptr; + QPointer m_effect; }; #endif diff --git a/src/quick/util/qquickdeliveryagent.cpp b/src/quick/util/qquickdeliveryagent.cpp index 1b6a3bd61..41a39d6c6 100644 --- a/src/quick/util/qquickdeliveryagent.cpp +++ b/src/quick/util/qquickdeliveryagent.cpp @@ -1686,7 +1686,13 @@ void QQuickDeliveryAgentPrivate::flushFrameSynchronousEvents(QQuickWindow *win) if (frameSynchronousHoverEnabled && !win->mouseGrabberItem() && !lastMousePosition.isNull() && QQuickWindowPrivate::get(win)->dirtyItemList) { qCDebug(lcHoverTrace) << q << "delivering frame-sync hover to root @" << lastMousePosition; - deliverHoverEvent(lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), 0); + if (deliverHoverEvent(lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), 0)) { +#if QT_CONFIG(cursor) + QQuickWindowPrivate::get(rootItem->window())->updateCursor( + sceneTransform ? sceneTransform->map(lastMousePosition) : lastMousePosition, rootItem); +#endif + } + qCDebug(lcHoverTrace) << q << "frame-sync hover delivery done"; } #else @@ -2023,6 +2029,16 @@ void QQuickDeliveryAgentPrivate::deliverUpdatedPoints(QPointerEvent *event) } if (!relevantPassiveGrabbers.isEmpty()) deliverToPassiveGrabbers(relevantPassiveGrabbers, event); + + // Ensure that HoverHandlers are updated, in case no items got dirty so far and there's no update request + if (event->type() == QEvent::TouchUpdate) { + for (auto hoverItem : hoverItems) { + if (auto item = hoverItem.first) { + deliverHoverEventToItem(item, point.scenePosition(), point.sceneLastPosition(), + event->modifiers(), event->timestamp(), false); + } + } + } } if (done) diff --git a/src/quickcontrols/basic/Dial.qml b/src/quickcontrols/basic/Dial.qml index 8648c9944..6076f7b2a 100644 --- a/src/quickcontrols/basic/Dial.qml +++ b/src/quickcontrols/basic/Dial.qml @@ -36,12 +36,13 @@ T.Dial { opacity: control.enabled ? 1 : 0.3 transform: [ Translate { - y: -Math.min(control.background.width, control.background.height) * 0.4 + control.handle.height / 2 + y: -Math.min(control.background.width, control.background.height) * 0.4 + + (control.handle ? control.handle.height / 2 : 0) }, Rotation { angle: control.angle - origin.x: control.handle.width / 2 - origin.y: control.handle.height / 2 + origin.x: control.handle ? control.handle.width / 2 : 0 + origin.y: control.handle ? control.handle.height / 2 : 0 } ] } diff --git a/src/quickcontrols/basic/Menu.qml b/src/quickcontrols/basic/Menu.qml index fd21f5de5..8e0800033 100644 --- a/src/quickcontrols/basic/Menu.qml +++ b/src/quickcontrols/basic/Menu.qml @@ -22,8 +22,8 @@ T.Menu { implicitHeight: contentHeight model: control.contentModel interactive: Window.window - ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height - : false + ? contentHeight + control.topPadding + control.bottomPadding > control.height + : false clip: true currentIndex: control.currentIndex diff --git a/src/quickcontrols/doc/snippets/qtquickcontrols-progressbar-custom.qml b/src/quickcontrols/doc/snippets/qtquickcontrols-progressbar-custom.qml index 715823208..a961debd4 100644 --- a/src/quickcontrols/doc/snippets/qtquickcontrols-progressbar-custom.qml +++ b/src/quickcontrols/doc/snippets/qtquickcontrols-progressbar-custom.qml @@ -21,11 +21,40 @@ ProgressBar { implicitWidth: 200 implicitHeight: 4 + // Progress indicator for determinate state. Rectangle { width: control.visualPosition * parent.width height: parent.height radius: 2 color: "#17a81a" + visible: !control.indeterminate + } + + // Scrolling animation for indeterminate state. + Item { + anchors.fill: parent + visible: control.indeterminate + clip: true + + Row { + spacing: 20 + + Repeater { + model: control.width / 40 + 1 + + Rectangle { + color: "#17a81a" + width: 20 + height: control.height + } + } + XAnimator on x { + from: 0 + to: -40 + loops: Animation.Infinite + running: control.indeterminate + } + } } } } diff --git a/src/quickcontrols/doc/snippets/qtquickcontrols-selectionrectangle.qml b/src/quickcontrols/doc/snippets/qtquickcontrols-selectionrectangle.qml index a53941e82..472b1b79d 100644 --- a/src/quickcontrols/doc/snippets/qtquickcontrols-selectionrectangle.qml +++ b/src/quickcontrols/doc/snippets/qtquickcontrols-selectionrectangle.qml @@ -1,8 +1,6 @@ // Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - import QtQuick import QtQuick.Window import QtQuick.Controls diff --git a/src/quickcontrols/doc/src/qtquickcontrols-configuration.qdoc b/src/quickcontrols/doc/src/qtquickcontrols-configuration.qdoc index 26fab0a2c..bb341c7ad 100644 --- a/src/quickcontrols/doc/src/qtquickcontrols-configuration.qdoc +++ b/src/quickcontrols/doc/src/qtquickcontrols-configuration.qdoc @@ -80,17 +80,12 @@ \section1 Font Configuration The default \l {Control::font}{font} can be specified in a \c Font sub-group - in each style's section in the configuration file. The \c Font sub-group can - be defined in two alternative ways: + in each style's section in the configuration file: \code [Basic] Font\Family=Open Sans Font\PixelSize=20 - - [Material\Font] - Family=Open Sans - PixelSize=20 \endcode Supported font attributes: @@ -137,13 +132,6 @@ Palette\WindowText=#212121 \endcode - or: - \code - [Fusion\Palette] - Window=#dedede - WindowText=#212121 - \endcode - See \l [QtQuick]{Palette} QML type for more information. \section1 Using the Configuration File in a Project diff --git a/src/quickcontrols/doc/src/qtquickcontrols-customize.qdoc b/src/quickcontrols/doc/src/qtquickcontrols-customize.qdoc index adc97177c..0a76f0eb4 100644 --- a/src/quickcontrols/doc/src/qtquickcontrols-customize.qdoc +++ b/src/quickcontrols/doc/src/qtquickcontrols-customize.qdoc @@ -761,6 +761,9 @@ \snippet qtquickcontrols-progressbar-custom.qml file + Above, the content item is also animated to represent an + \l {ProgressBar::}{indeterminate} progress bar state. + \section2 Customizing RadioButton diff --git a/src/quickcontrols/doc/src/qtquickcontrols-fileselectors.qdoc b/src/quickcontrols/doc/src/qtquickcontrols-fileselectors.qdoc index 01c9b26bd..c2c7b63d1 100644 --- a/src/quickcontrols/doc/src/qtquickcontrols-fileselectors.qdoc +++ b/src/quickcontrols/doc/src/qtquickcontrols-fileselectors.qdoc @@ -77,7 +77,7 @@ \code // +Material/CustomButton.qml import QtQuick - import QtGraphicalEffects + import QtQuick.Effects import QtQuick.Controls import QtQuick.Controls.Material @@ -93,11 +93,12 @@ radius: width / 2 layer.enabled: control.enabled - layer.effect: DropShadow { - verticalOffset: 1 - color: Material.dropShadowColor - samples: control.pressed ? 20 : 10 - spread: 0.5 + layer.effect: MultiEffect { + shadowEnabled: true + shadowHorizontalOffset: 3 + shadowVerticalOffset: 3 + shadowColor: Material.dropShadowColor + shadowBlur: control.pressed ? 0.8 : 0.4 } } } diff --git a/src/quickcontrols/doc/src/qtquickcontrols-material.qdoc b/src/quickcontrols/doc/src/qtquickcontrols-material.qdoc index b919b2c1b..2359aae13 100644 --- a/src/quickcontrols/doc/src/qtquickcontrols-material.qdoc +++ b/src/quickcontrols/doc/src/qtquickcontrols-material.qdoc @@ -48,6 +48,10 @@ may occur due to differences in available system fonts and font rendering engines. + \note As the Material Design Guidelines change over time, this style may + change certain padding or font values, for example, in order to maintain + consistency with the guidelines. + \section2 Customization The Material style supports several customizable attributes. Some of these diff --git a/src/quickcontrols/fusion/Dial.qml b/src/quickcontrols/fusion/Dial.qml index 7fa0af337..5d16874f4 100644 --- a/src/quickcontrols/fusion/Dial.qml +++ b/src/quickcontrols/fusion/Dial.qml @@ -28,12 +28,13 @@ T.Dial { height: control.height / 7 transform: [ Translate { - y: -Math.min(control.background.width, control.background.height) * 0.42 + control.handle.height + y: -Math.min(control.background.width, control.background.height) * 0.42 + + (control.handle ? control.handle.height / 2 : 0) }, Rotation { angle: control.angle - origin.x: control.handle.width / 2 - origin.y: control.handle.height / 2 + origin.x: control.handle ? control.handle.width / 2 : 0 + origin.y: control.handle ? control.handle.height / 2 : 0 } ] } diff --git a/src/quickcontrols/fusion/Menu.qml b/src/quickcontrols/fusion/Menu.qml index e0f565a69..bfd1feddb 100644 --- a/src/quickcontrols/fusion/Menu.qml +++ b/src/quickcontrols/fusion/Menu.qml @@ -26,8 +26,8 @@ T.Menu { implicitHeight: contentHeight model: control.contentModel interactive: Window.window - ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height - : false + ? contentHeight + control.topPadding + control.bottomPadding > control.height + : false clip: true currentIndex: control.currentIndex diff --git a/src/quickcontrols/fusion/TabButton.qml b/src/quickcontrols/fusion/TabButton.qml index add96a8fa..088a6e452 100644 --- a/src/quickcontrols/fusion/TabButton.qml +++ b/src/quickcontrols/fusion/TabButton.qml @@ -24,6 +24,8 @@ T.TabButton { z: checked + topInset: control.checked || control.TabBar.position !== T.TabBar.Header ? 0 : 2 + contentItem: IconLabel { spacing: control.spacing mirrored: control.mirrored @@ -35,10 +37,15 @@ T.TabButton { color: control.palette.buttonText } + background: Rectangle { - y: control.checked || control.TabBar.position !== T.TabBar.Header ? 0 : 2 - implicitHeight: 21 - height: control.height - (control.checked ? 0 : 2) + implicitHeight: 19 + + // TODO: Find out why the following binding fails to update the first tab button + // See QTBUG-108807 + // y: control.checked || control.TabBar.position !== T.TabBar.Header ? 0 : 2 + // implicitHeight: 21 + // height: control.height - (control.checked ? 0 : 2) border.color: Qt.lighter(Fusion.outline(control.palette), 1.1) diff --git a/src/quickcontrols/fusion/impl/qquickfusionbusyindicator.cpp b/src/quickcontrols/fusion/impl/qquickfusionbusyindicator.cpp index cce69b0e4..8e58b09ed 100644 --- a/src/quickcontrols/fusion/impl/qquickfusionbusyindicator.cpp +++ b/src/quickcontrols/fusion/impl/qquickfusionbusyindicator.cpp @@ -71,8 +71,17 @@ void QQuickFusionBusyIndicator::itemChange(ItemChange change, const ItemChangeDa { QQuickPaintedItem::itemChange(change, data); - if (change == ItemOpacityHasChanged && qFuzzyIsNull(data.realValue)) - setVisible(false); + switch (change) { + case ItemOpacityHasChanged: + if (qFuzzyIsNull(data.realValue)) + setVisible(false); + break; + case ItemVisibleHasChanged: + update(); + break; + default: + break; + } } QT_END_NAMESPACE diff --git a/src/quickcontrols/imagine/Dial.qml b/src/quickcontrols/imagine/Dial.qml index 85eb0a842..d534fad44 100644 --- a/src/quickcontrols/imagine/Dial.qml +++ b/src/quickcontrols/imagine/Dial.qml @@ -41,12 +41,13 @@ T.Dial { transform: [ Translate { - y: -Math.min(control.background.width, control.background.height) * 0.4 + control.handle.height / 2 + y: -Math.min(control.background.width, control.background.height) * 0.4 + + (control.handle ? control.handle.height / 2 : 0) }, Rotation { angle: control.angle - origin.x: control.handle.width / 2 - origin.y: control.handle.height / 2 + origin.x: control.handle ? control.handle.width / 2 : 0 + origin.y: control.handle ? control.handle.height / 2 : 0 } ] } diff --git a/src/quickcontrols/imagine/Menu.qml b/src/quickcontrols/imagine/Menu.qml index 6c58ea729..3596ee997 100644 --- a/src/quickcontrols/imagine/Menu.qml +++ b/src/quickcontrols/imagine/Menu.qml @@ -36,8 +36,8 @@ T.Menu { implicitHeight: contentHeight model: control.contentModel interactive: Window.window - ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height - : false + ? contentHeight + control.topPadding + control.bottomPadding > control.height + : false clip: true currentIndex: control.currentIndex diff --git a/src/quickcontrols/imagine/qquickimaginetheme.cpp b/src/quickcontrols/imagine/qquickimaginetheme.cpp index 921034962..7df719c84 100644 --- a/src/quickcontrols/imagine/qquickimaginetheme.cpp +++ b/src/quickcontrols/imagine/qquickimaginetheme.cpp @@ -5,13 +5,17 @@ #include +#include + QT_BEGIN_NAMESPACE void QQuickImagineTheme::initialize(QQuickTheme *theme) { - QFont systemFont; - systemFont.setFamilies(QStringList{QLatin1String("Open Sans")}); - theme->setFont(QQuickTheme::System, systemFont); + const auto defaultFontFamily = QLatin1String("Open Sans"); + if (QFontDatabase::hasFamily(defaultFontFamily)) { + const QFont systemFont(QStringList{defaultFontFamily}); + theme->setFont(QQuickTheme::System, systemFont); + } const QColor accentColor = QColor::fromRgb(0x4fc1e9); const QColor windowTextColor = QColor::fromRgb(0x434a54); diff --git a/src/quickcontrols/ios/Menu.qml b/src/quickcontrols/ios/Menu.qml index c968561ca..752737f69 100644 --- a/src/quickcontrols/ios/Menu.qml +++ b/src/quickcontrols/ios/Menu.qml @@ -35,8 +35,8 @@ T.Menu { implicitHeight: contentHeight model: control.contentModel interactive: Window.window - ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height - : false + ? contentHeight + control.topPadding + control.bottomPadding > control.height + : false clip: true currentIndex: control.currentIndex diff --git a/src/quickcontrols/material/Button.qml b/src/quickcontrols/material/Button.qml index 45003898d..c02d9f426 100644 --- a/src/quickcontrols/material/Button.qml +++ b/src/quickcontrols/material/Button.qml @@ -17,10 +17,9 @@ T.Button { topInset: 6 bottomInset: 6 - verticalPadding: 14 - // https://m3.material.io/components/buttons/specs#256326ad-f934-40e7-b05f-0bcb41aa4382 - leftPadding: !flat ? (!hasIcon ? 24 : 16) : 12 - rightPadding: !flat ? (text === "" ? 16 : 24) : (!hasIcon ? 12 : (text === "" ? 12 : 16)) + verticalPadding: Material.buttonVerticalPadding + leftPadding: Material.buttonLeftPadding(flat, hasIcon) + rightPadding: Material.buttonRightPadding(flat, hasIcon, text !== "") spacing: 8 icon.width: 24 diff --git a/src/quickcontrols/material/Dial.qml b/src/quickcontrols/material/Dial.qml index a44938fe2..465c1f363 100644 --- a/src/quickcontrols/material/Dial.qml +++ b/src/quickcontrols/material/Dial.qml @@ -33,12 +33,13 @@ T.Dial { y: control.background.y + control.background.height / 2 - height / 2 transform: [ Translate { - y: -control.background.height * 0.4 + control.handle.height / 2 + y: -control.background.height * 0.4 + + (control.handle ? control.handle.height / 2 : 0) }, Rotation { angle: control.angle - origin.x: control.handle.width / 2 - origin.y: control.handle.height / 2 + origin.x: control.handle ? control.handle.width / 2 : 0 + origin.y: control.handle ? control.handle.height / 2 : 0 } ] implicitWidth: 10 diff --git a/src/quickcontrols/material/Dialog.qml b/src/quickcontrols/material/Dialog.qml index 33d8ce97d..014fcc67c 100644 --- a/src/quickcontrols/material/Dialog.qml +++ b/src/quickcontrols/material/Dialog.qml @@ -28,8 +28,7 @@ T.Dialog { // https://m3.material.io/components/dialogs/specs#401a48c3-f50c-4fa9-b798-701f5adcf155 // Specs say level 3 (6 dp) is the default, yet the screenshots there show 0. Native Android defaults to non-zero. Material.elevation: 6 - // https://m3.material.io/components/dialogs/specs#6771d107-624e-47cc-b6d8-2b7b620ba2f1 - Material.roundedScale: Material.ExtraLargeScale + Material.roundedScale: Material.dialogRoundedScale enter: Transition { // grow_fade_in @@ -63,7 +62,7 @@ T.Dialog { bottomPadding: 0 // TODO: QPlatformTheme::TitleBarFont // https://m3.material.io/components/dialogs/specs#401a48c3-f50c-4fa9-b798-701f5adcf155 - font.pixelSize: 24 + font.pixelSize: Material.dialogTitleFontPixelSize background: PaddedRectangle { radius: control.background.radius color: control.Material.dialogColor diff --git a/src/quickcontrols/material/Menu.qml b/src/quickcontrols/material/Menu.qml index 1f0ba3bc9..641bb7c07 100644 --- a/src/quickcontrols/material/Menu.qml +++ b/src/quickcontrols/material/Menu.qml @@ -42,8 +42,8 @@ T.Menu { model: control.contentModel interactive: Window.window - ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height - : false + ? contentHeight + control.topPadding + control.bottomPadding > control.height + : false clip: true currentIndex: control.currentIndex diff --git a/src/quickcontrols/material/qquickmaterialstyle.cpp b/src/quickcontrols/material/qquickmaterialstyle.cpp index 7338dde84..f8ced5821 100644 --- a/src/quickcontrols/material/qquickmaterialstyle.cpp +++ b/src/quickcontrols/material/qquickmaterialstyle.cpp @@ -1269,6 +1269,32 @@ int QQuickMaterialStyle::touchTarget() const return globalVariant == Dense ? 44 : 48; } +int QQuickMaterialStyle::buttonVerticalPadding() const +{ + return globalVariant == Dense ? 10 : 14; +} + +// https://m3.material.io/components/buttons/specs#256326ad-f934-40e7-b05f-0bcb41aa4382 +int QQuickMaterialStyle::buttonLeftPadding(bool flat, bool hasIcon) const +{ + static const int noIconPadding = globalVariant == Dense ? 12 : 24; + static const int iconPadding = globalVariant == Dense ? 8 : 16; + static const int flatPadding = globalVariant == Dense ? 6 : 12; + return !flat ? (!hasIcon ? noIconPadding : iconPadding) : flatPadding; +} + +int QQuickMaterialStyle::buttonRightPadding(bool flat, bool hasIcon, bool hasText) const +{ + static const int noTextPadding = globalVariant == Dense ? 8 : 16; + static const int textPadding = globalVariant == Dense ? 12 : 24; + static const int flatNoIconPadding = globalVariant == Dense ? 6 : 12; + static const int flatNoTextPadding = globalVariant == Dense ? 6 : 12; + static const int flatTextPadding = globalVariant == Dense ? 8 : 16; + return !flat + ? (!hasText ? noTextPadding : textPadding) + : (!hasIcon ? flatNoIconPadding : (!hasText ? flatNoTextPadding : flatTextPadding)); +} + int QQuickMaterialStyle::buttonHeight() const { // https://m3.material.io/components/buttons/specs#256326ad-f934-40e7-b05f-0bcb41aa4382 @@ -1286,6 +1312,19 @@ int QQuickMaterialStyle::dialogButtonBoxHeight() const return globalVariant == Dense ? 48 : 52; } +int QQuickMaterialStyle::dialogTitleFontPixelSize() const +{ + return globalVariant == Dense ? 16 : 24; +} + +// https://m3.material.io/components/dialogs/specs#6771d107-624e-47cc-b6d8-2b7b620ba2f1 +QQuickMaterialStyle::RoundedScale QQuickMaterialStyle::dialogRoundedScale() const +{ + return globalVariant == Dense + ? QQuickMaterialStyle::RoundedScale::LargeScale + : QQuickMaterialStyle::RoundedScale::ExtraLargeScale; +} + int QQuickMaterialStyle::frameVerticalPadding() const { return globalVariant == Dense ? 8 : 12; diff --git a/src/quickcontrols/material/qquickmaterialstyle_p.h b/src/quickcontrols/material/qquickmaterialstyle_p.h index 96d07179f..5ff27f532 100644 --- a/src/quickcontrols/material/qquickmaterialstyle_p.h +++ b/src/quickcontrols/material/qquickmaterialstyle_p.h @@ -76,9 +76,12 @@ class QQuickMaterialStyle : public QQuickAttachedPropertyPropagator Q_PROPERTY(QColor textFieldFilledContainerColor READ textFieldFilledContainerColor NOTIFY themeChanged FINAL) Q_PROPERTY(int touchTarget READ touchTarget CONSTANT FINAL) + Q_PROPERTY(int buttonVerticalPadding READ buttonVerticalPadding CONSTANT FINAL) Q_PROPERTY(int buttonHeight READ buttonHeight CONSTANT FINAL) Q_PROPERTY(int delegateHeight READ delegateHeight CONSTANT FINAL) Q_PROPERTY(int dialogButtonBoxHeight READ dialogButtonBoxHeight CONSTANT FINAL) + Q_PROPERTY(int dialogTitleFontPixelSize READ dialogTitleFontPixelSize CONSTANT FINAL) + Q_PROPERTY(RoundedScale dialogRoundedScale READ dialogRoundedScale CONSTANT FINAL) Q_PROPERTY(int frameVerticalPadding READ frameVerticalPadding CONSTANT FINAL) Q_PROPERTY(int menuItemHeight READ menuItemHeight CONSTANT FINAL) Q_PROPERTY(int menuItemVerticalPadding READ menuItemVerticalPadding CONSTANT FINAL) @@ -269,9 +272,14 @@ class QQuickMaterialStyle : public QQuickAttachedPropertyPropagator Q_INVOKABLE QColor shade(const QColor &color, Shade shade) const; int touchTarget() const; + int buttonVerticalPadding() const; + Q_INVOKABLE int buttonLeftPadding(bool flat, bool hasIcon) const; + Q_INVOKABLE int buttonRightPadding(bool flat, bool hasIcon, bool hasText) const; int buttonHeight() const; int delegateHeight() const; int dialogButtonBoxHeight() const; + int dialogTitleFontPixelSize() const; + RoundedScale dialogRoundedScale() const; int frameVerticalPadding() const; int menuItemHeight() const; int menuItemVerticalPadding() const; diff --git a/src/quickcontrols/material/qquickmaterialtheme.cpp b/src/quickcontrols/material/qquickmaterialtheme.cpp index da2cf0f89..d121a1a47 100644 --- a/src/quickcontrols/material/qquickmaterialtheme.cpp +++ b/src/quickcontrols/material/qquickmaterialtheme.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include QT_BEGIN_NAMESPACE @@ -21,17 +21,15 @@ void QQuickMaterialTheme::initialize(QQuickTheme *theme) QFont menuItemFont; QFont editorFont; - QFont font; - font.setFamilies(QStringList{QLatin1String("Roboto")}); - QString family = QFontInfo(font).family(); - - if (family != QLatin1String("Roboto")) { - font.setFamilies(QStringList{QLatin1String("Noto")}); - family = QFontInfo(font).family(); + auto defaultFontFamily = QLatin1String("Roboto"); + if (!QFontDatabase::hasFamily(defaultFontFamily)) { + defaultFontFamily = QLatin1String("Noto"); // fallback + if (!QFontDatabase::hasFamily(defaultFontFamily)) + defaultFontFamily = {}; } - if (family == QLatin1String("Roboto") || family == QLatin1String("Noto")) { - const QStringList families{family}; + if (!defaultFontFamily.isEmpty()) { + const QStringList families{defaultFontFamily}; systemFont.setFamilies(families); buttonFont.setFamilies(families); toolTipFont.setFamilies(families); diff --git a/src/quickcontrols/universal/Dial.qml b/src/quickcontrols/universal/Dial.qml index 6f86b0072..df52ea1aa 100644 --- a/src/quickcontrols/universal/Dial.qml +++ b/src/quickcontrols/universal/Dial.qml @@ -41,12 +41,13 @@ T.Dial { transform: [ Translate { - y: -control.background.height * 0.4 + control.handle.height / 2 + y: -control.background.height * 0.4 + + (control.handle ? control.handle.height / 2 : 0) }, Rotation { angle: control.angle - origin.x: control.handle.width / 2 - origin.y: control.handle.height / 2 + origin.x: control.handle ? control.handle.width / 2 : 0 + origin.y: control.handle ? control.handle.height / 2 : 0 } ] } diff --git a/src/quickcontrols/universal/Menu.qml b/src/quickcontrols/universal/Menu.qml index 64dac0c4b..03a5b2302 100644 --- a/src/quickcontrols/universal/Menu.qml +++ b/src/quickcontrols/universal/Menu.qml @@ -23,8 +23,8 @@ T.Menu { implicitHeight: contentHeight model: control.contentModel interactive: Window.window - ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height - : false + ? contentHeight + control.topPadding + control.bottomPadding > control.height + : false clip: true currentIndex: control.currentIndex diff --git a/src/quickdialogs/quickdialogs/qquickabstractdialog.cpp b/src/quickdialogs/quickdialogs/qquickabstractdialog.cpp index 857a75c7b..088e7ae8d 100644 --- a/src/quickdialogs/quickdialogs/qquickabstractdialog.cpp +++ b/src/quickdialogs/quickdialogs/qquickabstractdialog.cpp @@ -150,6 +150,8 @@ QWindow *QQuickAbstractDialog::parentWindow() const void QQuickAbstractDialog::setParentWindow(QWindow *window) { qCDebug(lcDialogs) << "set parent window to" << window; + m_parentWindowExplicitlySet = bool(window); + if (m_parentWindow == window) return; @@ -157,6 +159,17 @@ void QQuickAbstractDialog::setParentWindow(QWindow *window) emit parentWindowChanged(); } +void QQuickAbstractDialog::resetParentWindow() +{ + m_parentWindowExplicitlySet = false; + + if (!m_parentWindow) + return; + + m_parentWindow = nullptr; + emit parentWindowChanged(); +} + /*! \qmlproperty string QtQuick.Dialogs::Dialog::title @@ -287,7 +300,8 @@ void QQuickAbstractDialog::open() return; onShow(m_handle.get()); - m_visible = m_handle->show(m_flags, m_modality, m_parentWindow); + + m_visible = m_handle->show(m_flags, m_modality, windowForOpen()); if (m_visible) { m_result = Rejected; // in case an accepted dialog gets re-opened, then closed emit visibleChanged(); @@ -310,6 +324,8 @@ void QQuickAbstractDialog::close() onHide(m_handle.get()); m_handle->hide(); m_visible = false; + if (!m_parentWindowExplicitlySet) + m_parentWindow = nullptr; emit visibleChanged(); if (m_result == Accepted) @@ -364,16 +380,22 @@ void QQuickAbstractDialog::componentComplete() qCDebug(lcDialogs) << "componentComplete"; m_complete = true; - if (!m_parentWindow) { - qCDebug(lcDialogs) << "- no parent window; searching for one"; - setParentWindow(findParentWindow()); - } + if (!m_visibleRequested) + return; - if (m_visibleRequested) { - qCDebug(lcDialogs) << "visible was bound to true before component completion; opening dialog"; + m_visibleRequested = false; + + if (windowForOpen()) { open(); - m_visibleRequested = false; + return; } + + // Since visible were set to true by the user, we want the dialog to be open by default. + // There is no guarantee that the dialog will work when it exists in a object tree that lacks a window, + // and since qml components are sometimes instantiated before they're given a window + // (which is the case when using QQuickView), we want to delay the call to open(), until the window is provided. + if (const auto parentItem = findParentItem()) + connect(parentItem, &QQuickItem::windowChanged, this, &QQuickAbstractDialog::deferredOpen, Qt::SingleShotConnection); } static const char *qmlTypeName(const QObject *object) @@ -461,21 +483,33 @@ void QQuickAbstractDialog::onHide(QPlatformDialogHelper *dialog) Q_UNUSED(dialog); } -QWindow *QQuickAbstractDialog::findParentWindow() const +QQuickItem *QQuickAbstractDialog::findParentItem() const { QObject *obj = parent(); while (obj) { - QWindow *window = qobject_cast(obj); - if (window) - return window; QQuickItem *item = qobject_cast(obj); - if (item && item->window()) - return item->window(); + if (item) + return item; obj = obj->parent(); } return nullptr; } +QWindow *QQuickAbstractDialog::windowForOpen() const +{ + if (m_parentWindowExplicitlySet) + return m_parentWindow; + else if (auto parentItem = findParentItem()) + return parentItem->window(); + return m_parentWindow; +} + +void QQuickAbstractDialog::deferredOpen(QWindow *window) +{ + m_parentWindow = window; + open(); +} + QT_END_NAMESPACE #include "moc_qquickabstractdialog_p.cpp" diff --git a/src/quickdialogs/quickdialogs/qquickabstractdialog_p.h b/src/quickdialogs/quickdialogs/qquickabstractdialog_p.h index f1d046eb8..30f164b12 100644 --- a/src/quickdialogs/quickdialogs/qquickabstractdialog_p.h +++ b/src/quickdialogs/quickdialogs/qquickabstractdialog_p.h @@ -37,7 +37,7 @@ class Q_QUICKDIALOGS2_PRIVATE_EXPORT QQuickAbstractDialog : public QObject, publ Q_OBJECT Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QQmlListProperty data READ data FINAL) - Q_PROPERTY(QWindow *parentWindow READ parentWindow WRITE setParentWindow NOTIFY parentWindowChanged FINAL) + Q_PROPERTY(QWindow *parentWindow READ parentWindow WRITE setParentWindow NOTIFY parentWindowChanged RESET resetParentWindow FINAL) Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged FINAL) Q_PROPERTY(Qt::WindowFlags flags READ flags WRITE setFlags NOTIFY flagsChanged FINAL) Q_PROPERTY(Qt::WindowModality modality READ modality WRITE setModality NOTIFY modalityChanged FINAL) @@ -58,6 +58,7 @@ class Q_QUICKDIALOGS2_PRIVATE_EXPORT QQuickAbstractDialog : public QObject, publ QWindow *parentWindow() const; void setParentWindow(QWindow *window); + void resetParentWindow(); QString title() const; void setTitle(const QString &title); @@ -106,12 +107,10 @@ public Q_SLOTS: virtual void onShow(QPlatformDialogHelper *dialog); virtual void onHide(QPlatformDialogHelper *dialog); - QWindow *findParentWindow() const; + QQuickItem *findParentItem() const; + QWindow *windowForOpen() const; + void deferredOpen(QWindow *window); - bool m_visibleRequested = false; - bool m_visible = false; - bool m_complete = false; - bool m_firstShow = true; StandardCode m_result = Rejected; QWindow *m_parentWindow = nullptr; QString m_title; @@ -120,6 +119,11 @@ public Q_SLOTS: QQuickDialogType m_type = QQuickDialogType::FileDialog; QList m_data; std::unique_ptr m_handle; + bool m_visibleRequested = false; + bool m_visible = false; + bool m_complete = false; + bool m_parentWindowExplicitlySet = false; + bool m_firstShow = true; }; QT_END_NAMESPACE diff --git a/src/quickdialogs/quickdialogs/qquickmessagedialog.cpp b/src/quickdialogs/quickdialogs/qquickmessagedialog.cpp index 075ccd54d..3e71a9ac4 100644 --- a/src/quickdialogs/quickdialogs/qquickmessagedialog.cpp +++ b/src/quickdialogs/quickdialogs/qquickmessagedialog.cpp @@ -219,6 +219,7 @@ void QQuickMessageDialog::handleClick(QPlatformDialogHelper::StandardButton butt QPlatformDialogHelper::ButtonRole role) { emit buttonClicked(button, role); + close(); } void QQuickMessageDialog::onCreate(QPlatformDialogHelper *dialog) diff --git a/src/quickdialogs/quickdialogsquickimpl/qml/+Fusion/FileDialog.qml b/src/quickdialogs/quickdialogsquickimpl/qml/+Fusion/FileDialog.qml index a928a4b0c..965f56bdc 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qml/+Fusion/FileDialog.qml +++ b/src/quickdialogs/quickdialogsquickimpl/qml/+Fusion/FileDialog.qml @@ -31,6 +31,29 @@ FileDialogImpl { standardButtons: T.Dialog.Open | T.Dialog.Cancel + Dialog { + id: overwriteConfirmationDialog + objectName: "confirmationDialog" + anchors.centerIn: parent + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + dim: true + modal: true + title: qsTr("“%1” already exists. Do you want to replace it?").arg(control.fileName) + + Label { + text: qsTr("A file with the same name already exists in %1.\nReplacing it will overwrite its current contents.").arg(control.currentFolderName) + } + + footer: DialogButtonBox { + alignment: Qt.AlignHCenter + standardButtons: DialogButtonBox.Yes | DialogButtonBox.No + } + + Overlay.modal: Rectangle { + color: Fusion.darkShade + } + } + /* We use attached properties because we want to handle logic in C++, and: - We can't assume the footer only contains a DialogButtonBox (which would allow us @@ -45,6 +68,7 @@ FileDialogImpl { FileDialogImpl.breadcrumbBar: breadcrumbBar FileDialogImpl.fileNameLabel: fileNameLabel FileDialogImpl.fileNameTextField: fileNameTextField + FileDialogImpl.overwriteConfirmationDialog: overwriteConfirmationDialog background: Rectangle { implicitWidth: 600 @@ -124,7 +148,7 @@ FileDialogImpl { fileDetailRowWidth: nameFiltersComboBox.width KeyNavigation.backtab: breadcrumbBar - KeyNavigation.tab: nameFiltersComboBox + KeyNavigation.tab: fileNameTextField.visible ? fileNameTextField : nameFiltersComboBox } } } @@ -143,7 +167,6 @@ FileDialogImpl { TextField { id: fileNameTextField objectName: "fileNameTextField" - text: control.fileName visible: false Layout.fillWidth: true diff --git a/src/quickdialogs/quickdialogsquickimpl/qml/+Fusion/FileDialogDelegate.qml b/src/quickdialogs/quickdialogsquickimpl/qml/+Fusion/FileDialogDelegate.qml index 475528d2e..46cdb06f0 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qml/+Fusion/FileDialogDelegate.qml +++ b/src/quickdialogs/quickdialogsquickimpl/qml/+Fusion/FileDialogDelegate.qml @@ -34,7 +34,7 @@ DialogsQuickImpl.FileDialogDelegate { required property int index required property string fileName required property url fileUrl - required property int fileSize + required property string fileSize required property date fileModified required property bool fileIsDir diff --git a/src/quickdialogs/quickdialogsquickimpl/qml/+Imagine/FileDialog.qml b/src/quickdialogs/quickdialogsquickimpl/qml/+Imagine/FileDialog.qml index 664965e57..8568be710 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qml/+Imagine/FileDialog.qml +++ b/src/quickdialogs/quickdialogsquickimpl/qml/+Imagine/FileDialog.qml @@ -39,12 +39,34 @@ FileDialogImpl { standardButtons: T.Dialog.Open | T.Dialog.Cancel + Dialog { + id: overwriteConfirmationDialog + objectName: "confirmationDialog" + anchors.centerIn: parent + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + dim: true + modal: true + spacing: 12 + title: qsTr("“%1” already exists. Do you want to replace it?").arg(control.fileName) + + Label { + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("A file with the same name already exists in %1.\nReplacing it will overwrite its current contents.").arg(control.currentFolderName) + horizontalAlignment: Text.AlignHCenter + } + + footer: DialogButtonBox { + standardButtons: DialogButtonBox.Yes | DialogButtonBox.No + } + } + FileDialogImpl.buttonBox: buttonBox FileDialogImpl.nameFiltersComboBox: nameFiltersComboBox FileDialogImpl.fileDialogListView: fileDialogListView FileDialogImpl.breadcrumbBar: breadcrumbBar FileDialogImpl.fileNameLabel: fileNameLabel FileDialogImpl.fileNameTextField: fileNameTextField + FileDialogImpl.overwriteConfirmationDialog: overwriteConfirmationDialog background: NinePatchImage { source: Imagine.url + "dialog-background" @@ -115,6 +137,9 @@ FileDialogImpl { highlighted: ListView.isCurrentItem dialog: control fileDetailRowWidth: nameFiltersComboBox.width + + KeyNavigation.backtab: breadcrumbBar + KeyNavigation.tab: fileNameTextField.visible ? fileNameTextField : nameFiltersComboBox } } @@ -133,7 +158,6 @@ FileDialogImpl { TextField { id: fileNameTextField objectName: "fileNameTextField" - text: control.fileName visible: false Layout.fillWidth: true diff --git a/src/quickdialogs/quickdialogsquickimpl/qml/+Imagine/FileDialogDelegate.qml b/src/quickdialogs/quickdialogsquickimpl/qml/+Imagine/FileDialogDelegate.qml index 30094a7d9..88c6f99d1 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qml/+Imagine/FileDialogDelegate.qml +++ b/src/quickdialogs/quickdialogsquickimpl/qml/+Imagine/FileDialogDelegate.qml @@ -39,7 +39,7 @@ DialogsQuickImpl.FileDialogDelegate { required property int index required property string fileName required property url fileUrl - required property int fileSize + required property string fileSize required property date fileModified required property bool fileIsDir diff --git a/src/quickdialogs/quickdialogsquickimpl/qml/+Material/FileDialog.qml b/src/quickdialogs/quickdialogsquickimpl/qml/+Material/FileDialog.qml index cd2c513c2..9700aeba7 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qml/+Material/FileDialog.qml +++ b/src/quickdialogs/quickdialogsquickimpl/qml/+Material/FileDialog.qml @@ -32,12 +32,32 @@ FileDialogImpl { Material.elevation: 24 + Dialog { + id: overwriteConfirmationDialog + objectName: "confirmationDialog" + anchors.centerIn: parent + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + dim: true + modal: true + title: qsTr("“%1” already exists. Do you want to replace it?").arg(control.fileName) + + Label { + text: qsTr("A file with the same name already exists in %1.\nReplacing it will overwrite its current contents.").arg(control.currentFolderName) + } + + footer: DialogButtonBox { + alignment: Qt.AlignHCenter + standardButtons: DialogButtonBox.Yes | DialogButtonBox.No + } + } + FileDialogImpl.buttonBox: buttonBox FileDialogImpl.nameFiltersComboBox: nameFiltersComboBox FileDialogImpl.fileDialogListView: fileDialogListView FileDialogImpl.breadcrumbBar: breadcrumbBar FileDialogImpl.fileNameLabel: fileNameLabel FileDialogImpl.fileNameTextField: fileNameTextField + FileDialogImpl.overwriteConfirmationDialog: overwriteConfirmationDialog background: Rectangle { implicitWidth: 600 @@ -97,6 +117,9 @@ FileDialogImpl { highlighted: ListView.isCurrentItem dialog: control fileDetailRowWidth: nameFiltersComboBox.width + + KeyNavigation.backtab: breadcrumbBar + KeyNavigation.tab: fileNameTextField.visible ? fileNameTextField : nameFiltersComboBox } } @@ -116,7 +139,6 @@ FileDialogImpl { TextField { id: fileNameTextField objectName: "fileNameTextField" - text: control.fileName visible: false Layout.topMargin: 12 diff --git a/src/quickdialogs/quickdialogsquickimpl/qml/+Material/FileDialogDelegate.qml b/src/quickdialogs/quickdialogsquickimpl/qml/+Material/FileDialogDelegate.qml index c96231345..ff06ea8d4 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qml/+Material/FileDialogDelegate.qml +++ b/src/quickdialogs/quickdialogsquickimpl/qml/+Material/FileDialogDelegate.qml @@ -31,7 +31,7 @@ DialogsQuickImpl.FileDialogDelegate { required property int index required property string fileName required property url fileUrl - required property int fileSize + required property string fileSize required property date fileModified required property bool fileIsDir diff --git a/src/quickdialogs/quickdialogsquickimpl/qml/+Universal/FileDialog.qml b/src/quickdialogs/quickdialogsquickimpl/qml/+Universal/FileDialog.qml index c029b0629..0d2db8b42 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qml/+Universal/FileDialog.qml +++ b/src/quickdialogs/quickdialogsquickimpl/qml/+Universal/FileDialog.qml @@ -30,12 +30,35 @@ FileDialogImpl { standardButtons: T.Dialog.Open | T.Dialog.Cancel + Dialog { + id: overwriteConfirmationDialog + objectName: "confirmationDialog" + anchors.centerIn: parent + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + dim: true + modal: true + title: qsTr("“%1” already exists. Do you want to replace it?").arg(control.fileName) + + Label { + text: qsTr("A file with the same name already exists in %1.\nReplacing it will overwrite its current contents.").arg(control.currentFolderName) + } + + footer: DialogButtonBox { + standardButtons: DialogButtonBox.Yes | DialogButtonBox.No + } + + Overlay.modal: Rectangle { + color: overwriteConfirmationDialog.Universal.baseMediumColor + } + } + FileDialogImpl.buttonBox: buttonBox FileDialogImpl.nameFiltersComboBox: nameFiltersComboBox FileDialogImpl.fileDialogListView: fileDialogListView FileDialogImpl.breadcrumbBar: breadcrumbBar FileDialogImpl.fileNameLabel: fileNameLabel FileDialogImpl.fileNameTextField: fileNameTextField + FileDialogImpl.overwriteConfirmationDialog: overwriteConfirmationDialog background: Rectangle { implicitWidth: 600 @@ -99,6 +122,9 @@ FileDialogImpl { highlighted: ListView.isCurrentItem dialog: control fileDetailRowWidth: nameFiltersComboBox.width + + KeyNavigation.backtab: breadcrumbBar + KeyNavigation.tab: fileNameTextField.visible ? fileNameTextField : nameFiltersComboBox } } @@ -117,7 +143,6 @@ FileDialogImpl { TextField { id: fileNameTextField objectName: "fileNameTextField" - text: control.fileName visible: false Layout.fillWidth: true diff --git a/src/quickdialogs/quickdialogsquickimpl/qml/+Universal/FileDialogDelegate.qml b/src/quickdialogs/quickdialogsquickimpl/qml/+Universal/FileDialogDelegate.qml index 7650ec7a3..92c16f406 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qml/+Universal/FileDialogDelegate.qml +++ b/src/quickdialogs/quickdialogsquickimpl/qml/+Universal/FileDialogDelegate.qml @@ -32,7 +32,7 @@ DialogsQuickImpl.FileDialogDelegate { required property int index required property string fileName required property url fileUrl - required property int fileSize + required property string fileSize required property date fileModified required property bool fileIsDir diff --git a/src/quickdialogs/quickdialogsquickimpl/qml/FileDialog.qml b/src/quickdialogs/quickdialogsquickimpl/qml/FileDialog.qml index 0f25dee35..defb7dd4e 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qml/FileDialog.qml +++ b/src/quickdialogs/quickdialogsquickimpl/qml/FileDialog.qml @@ -34,6 +34,25 @@ FileDialogImpl { standardButtons: T.Dialog.Open | T.Dialog.Cancel + Dialog { + id: overwriteConfirmationDialog + objectName: "confirmationDialog" + anchors.centerIn: parent + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + dim: true + modal: true + title: qsTr("“%1” already exists. Do you want to replace it?").arg(control.fileName) + + Label { + text: qsTr("A file with the same name already exists in %1.\nReplacing it will overwrite its current contents.").arg(control.currentFolderName) + } + + footer: DialogButtonBox { + alignment: Qt.AlignHCenter + standardButtons: DialogButtonBox.Yes | DialogButtonBox.No + } + } + /* We use attached properties because we want to handle logic in C++, and: - We can't assume the footer only contains a DialogButtonBox (which would allow us @@ -48,6 +67,7 @@ FileDialogImpl { FileDialogImpl.breadcrumbBar: breadcrumbBar FileDialogImpl.fileNameLabel: fileNameLabel FileDialogImpl.fileNameTextField: fileNameTextField + FileDialogImpl.overwriteConfirmationDialog: overwriteConfirmationDialog background: Rectangle { implicitWidth: 600 @@ -106,7 +126,7 @@ FileDialogImpl { fileDetailRowWidth: nameFiltersComboBox.width KeyNavigation.backtab: breadcrumbBar - KeyNavigation.tab: nameFiltersComboBox + KeyNavigation.tab: fileNameTextField.visible ? fileNameTextField : nameFiltersComboBox } } @@ -135,7 +155,6 @@ FileDialogImpl { TextField { id: fileNameTextField objectName: "fileNameTextField" - text: control.fileName visible: false Layout.fillWidth: true diff --git a/src/quickdialogs/quickdialogsquickimpl/qml/FileDialogDelegate.qml b/src/quickdialogs/quickdialogsquickimpl/qml/FileDialogDelegate.qml index 3abe35f43..6f62375a8 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qml/FileDialogDelegate.qml +++ b/src/quickdialogs/quickdialogsquickimpl/qml/FileDialogDelegate.qml @@ -34,7 +34,7 @@ DialogsQuickImpl.FileDialogDelegate { required property int index required property string fileName required property url fileUrl - required property int fileSize + required property string fileSize required property date fileModified required property bool fileIsDir diff --git a/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogdelegate.cpp b/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogdelegate.cpp index 71b1fccbc..369176f84 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogdelegate.cpp +++ b/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogdelegate.cpp @@ -11,6 +11,7 @@ #include #include "qquickfiledialogimpl_p.h" +#include "qquickfiledialogimpl_p_p.h" #include "qquickfolderdialogimpl_p.h" QT_BEGIN_NAMESPACE @@ -67,6 +68,16 @@ void QQuickFileDialogDelegatePrivate::chooseFile() Q_ASSERT(fileDialog); // Otherwise it's a file, so select it and close the dialog. fileDialog->setSelectedFile(file); + + // Prioritize closing the dialog with QQuickDialogPrivate::handleClick() over QQuickDialog::accept() + const QQuickFileDialogImplAttached *attached = QQuickFileDialogImplPrivate::get(fileDialog)->attachedOrWarn(); + if (Q_LIKELY(attached)) { + auto *openButton = attached->buttonBox()->standardButton(QPlatformDialogHelper::Open); + if (Q_LIKELY(openButton)) { + emit openButton->clicked(); + return; + } + } fileDialog->accept(); } } diff --git a/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogimpl.cpp b/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogimpl.cpp index bcde63e7f..d16afe8ad 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogimpl.cpp +++ b/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogimpl.cpp @@ -137,12 +137,24 @@ void QQuickFileDialogImplPrivate::updateSelectedFile(const QString &oldFolderPat qCDebug(lcUpdateSelectedFile).nospace() << "updateSelectedFile is setting selectedFile to " << newSelectedFileUrl << ", newSelectedFileIndex is " << newSelectedFileIndex; q->setSelectedFile(newSelectedFileUrl); + updateFileNameTextEdit(); // If the index is -1, there are no files in the directory, and so fileDialogListView's // currentIndex will already be -1. if (newSelectedFileIndex != -1) tryUpdateFileDialogListViewCurrentIndex(newSelectedFileIndex); } +void QQuickFileDialogImplPrivate::updateFileNameTextEdit() +{ + QQuickFileDialogImplAttached *attached = attachedOrWarn(); + if (Q_UNLIKELY(!attached)) + return; + + const QFileInfo fileInfo(selectedFile.toLocalFile()); + if (fileInfo.isFile()) + attached->fileNameTextField()->setText(fileInfo.fileName()); +} + QDir::SortFlags QQuickFileDialogImplPrivate::fileListSortFlags() { QDir::SortFlags sortFlags = QDir::IgnoreCase; @@ -238,14 +250,35 @@ void QQuickFileDialogImplPrivate::handleClick(QQuickAbstractButton *button) // Don't call accept(), because selecting a folder != accepting the dialog. } else { // Otherwise it's a file, so select it and close the dialog. - q->setSelectedFile(selectedFile); - q->accept(); - QQuickDialogPrivate::handleClick(button); - emit q->fileSelected(selectedFile); + + lastButtonClicked = button; + + // Unless it already exists... + const bool dontConfirmOverride = q->options()->testOption(QFileDialogOptions::DontConfirmOverwrite); + const bool isSaveMode = q->options()->fileMode() == QFileDialogOptions::AnyFile; + if (QQuickFileDialogImplAttached *attached = attachedOrWarn(); + attached && fileInfo.exists() && isSaveMode && !dontConfirmOverride) { + QQuickDialog *confirmationDialog = attached->overwriteConfirmationDialog(); + confirmationDialog->open(); + static_cast(confirmationDialog->footer())->standardButton(QPlatformDialogHelper::Yes) + ->forceActiveFocus(Qt::PopupFocusReason); + } else { + selectFile(); + } } } } +void QQuickFileDialogImplPrivate::selectFile() +{ + Q_Q(QQuickFileDialogImpl); + Q_ASSERT(lastButtonClicked); + q->setSelectedFile(selectedFile); + q->accept(); + QQuickDialogPrivate::handleClick(lastButtonClicked); + emit q->fileSelected(selectedFile); +} + QQuickFileDialogImpl::QQuickFileDialogImpl(QObject *parent) : QQuickDialog(*(new QQuickFileDialogImplPrivate), parent) { @@ -332,6 +365,7 @@ void QQuickFileDialogImpl::setInitialCurrentFolderAndSelectedFile(const QUrl &fi qCDebug(lcSelectedFile) << "setting initial currentFolder to" << fileDirUrl << "and selectedFile to" << file; setCurrentFolder(fileDirUrl, QQuickFileDialogImpl::SetReason::Internal); setSelectedFile(file); + d->updateFileNameTextEdit(); d->setCurrentIndexToInitiallySelectedFile = true; // If the currentFolder didn't change, the FolderListModel won't change and @@ -426,8 +460,9 @@ void QQuickFileDialogImpl::setAcceptLabel(const QString &label) return; } - auto buttonType = d->options->acceptMode() == QFileDialogOptions::AcceptSave - ? QPlatformDialogHelper::Save : QPlatformDialogHelper::Open; + auto buttonType = (d->options && d->options->acceptMode() == QFileDialogOptions::AcceptSave) + ? QPlatformDialogHelper::Save + : QPlatformDialogHelper::Open; acceptButton->setText(!label.isEmpty() ? label : QQuickDialogButtonBoxPrivate::buttonText(buttonType)); } @@ -472,6 +507,11 @@ void QQuickFileDialogImpl::setFileName(const QString &fileName) setSelectedFile(QUrl(currentFolder().path() + u'/' + fileName)); } +QString QQuickFileDialogImpl::currentFolderName() const +{ + return QDir(currentFolder().toLocalFile()).dirName(); +} + void QQuickFileDialogImpl::componentComplete() { Q_D(QQuickFileDialogImpl); @@ -563,6 +603,7 @@ void QQuickFileDialogImplAttachedPrivate::fileDialogListViewCurrentIndexChanged( auto fileDialogImplPrivate = QQuickFileDialogImplPrivate::get(fileDialogImpl); if (moveReason != QQuickItemViewPrivate::Other) { fileDialogImpl->setSelectedFile(fileDialogDelegate->file()); + fileDialogImplPrivate->updateFileNameTextEdit(); } else if (fileDialogImplPrivate->setCurrentIndexToInitiallySelectedFile) { // When setting selectedFile before opening the FileDialog, // we need to ensure that the currentIndex is correct, because the initial change @@ -770,6 +811,32 @@ void QQuickFileDialogImplAttached::setFileNameTextField(QQuickTextField *fileNam emit fileNameTextFieldChanged(); } +QQuickDialog *QQuickFileDialogImplAttached::overwriteConfirmationDialog() const +{ + Q_D(const QQuickFileDialogImplAttached); + return d->overwriteConfirmationDialog; +} + +void QQuickFileDialogImplAttached::setOverwriteConfirmationDialog(QQuickDialog *dialog) +{ + Q_D(QQuickFileDialogImplAttached); + if (dialog == d->overwriteConfirmationDialog) + return; + + QQuickFileDialogImpl *fileDialogImpl = qobject_cast(parent()); + if (d->overwriteConfirmationDialog && fileDialogImpl) + QObjectPrivate::disconnect(d->overwriteConfirmationDialog, &QQuickDialog::accepted, + QQuickFileDialogImplPrivate::get(fileDialogImpl), &QQuickFileDialogImplPrivate::selectFile); + + d->overwriteConfirmationDialog = dialog; + + if (d->overwriteConfirmationDialog && fileDialogImpl) + QObjectPrivate::connect(d->overwriteConfirmationDialog, &QQuickDialog::accepted, + QQuickFileDialogImplPrivate::get(fileDialogImpl), &QQuickFileDialogImplPrivate::selectFile, Qt::QueuedConnection); + + emit overwriteConfirmationDialogChanged(); +} + QT_END_NAMESPACE #include "moc_qquickfiledialogimpl_p.cpp" diff --git a/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogimpl_p.h b/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogimpl_p.h index 4c64c5e4d..1861d7d7e 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogimpl_p.h +++ b/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogimpl_p.h @@ -41,6 +41,7 @@ class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFileDialogImpl : public QQui Q_PROPERTY(QStringList nameFilters READ nameFilters NOTIFY nameFiltersChanged FINAL) Q_PROPERTY(QQuickFileNameFilter *selectedNameFilter READ selectedNameFilter CONSTANT) Q_PROPERTY(QString fileName READ fileName WRITE setFileName NOTIFY selectedFileChanged FINAL) + Q_PROPERTY(QString currentFolderName READ currentFolderName NOTIFY selectedFileChanged FINAL) QML_NAMED_ELEMENT(FileDialogImpl) QML_ATTACHED(QQuickFileDialogImplAttached) QML_ADDED_IN_VERSION(6, 2) @@ -80,6 +81,8 @@ class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFileDialogImpl : public QQui QString fileName() const; void setFileName(const QString &fileName); + QString currentFolderName() const; + public Q_SLOTS: void selectNameFilter(const QString &filter); @@ -107,6 +110,7 @@ class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFileDialogImplAttached : pub Q_PROPERTY(QQuickFolderBreadcrumbBar *breadcrumbBar READ breadcrumbBar WRITE setBreadcrumbBar NOTIFY breadcrumbBarChanged) Q_PROPERTY(QQuickLabel *fileNameLabel READ fileNameLabel WRITE setFileNameLabel NOTIFY fileNameLabelChanged FINAL) Q_PROPERTY(QQuickTextField *fileNameTextField READ fileNameTextField WRITE setFileNameTextField NOTIFY fileNameTextFieldChanged FINAL) + Q_PROPERTY(QQuickDialog *overwriteConfirmationDialog READ overwriteConfirmationDialog WRITE setOverwriteConfirmationDialog NOTIFY overwriteConfirmationDialogChanged FINAL) Q_MOC_INCLUDE() Q_MOC_INCLUDE() Q_MOC_INCLUDE() @@ -136,6 +140,9 @@ class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFileDialogImplAttached : pub QQuickTextField *fileNameTextField() const; void setFileNameTextField(QQuickTextField *fileNameTextField); + QQuickDialog *overwriteConfirmationDialog() const; + void setOverwriteConfirmationDialog(QQuickDialog *dialog); + Q_SIGNALS: void buttonBoxChanged(); void nameFiltersComboBoxChanged(); @@ -143,6 +150,7 @@ class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFileDialogImplAttached : pub void breadcrumbBarChanged(); void fileNameLabelChanged(); void fileNameTextFieldChanged(); + void overwriteConfirmationDialogChanged(); private: Q_DISABLE_COPY(QQuickFileDialogImplAttached) diff --git a/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogimpl_p_p.h b/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogimpl_p_p.h index a0d893543..5e0b23959 100644 --- a/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogimpl_p_p.h +++ b/src/quickdialogs/quickdialogsquickimpl/qquickfiledialogimpl_p_p.h @@ -45,6 +45,7 @@ class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFileDialogImplPrivate : publ void updateEnabled(); void updateSelectedFile(const QString &oldFolderPath); + void updateFileNameTextEdit(); static QDir::SortFlags fileListSortFlags(); static QFileInfoList fileList(const QDir &dir); void setFileDialogListViewCurrentIndex(int newCurrentIndex); @@ -53,10 +54,12 @@ class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFileDialogImplPrivate : publ void handleAccept() override; void handleClick(QQuickAbstractButton *button) override; + void selectFile(); QSharedPointer options; QUrl currentFolder; QUrl selectedFile; + QQuickAbstractButton *lastButtonClicked = nullptr; QStringList nameFilters; mutable QQuickFileNameFilter *selectedNameFilter = nullptr; QString acceptLabel; @@ -82,6 +85,7 @@ class QQuickFileDialogImplAttachedPrivate : public QObjectPrivate QPointer breadcrumbBar; QPointer fileNameLabel; QPointer fileNameTextField; + QPointer overwriteConfirmationDialog; }; QT_END_NAMESPACE diff --git a/src/quicknativestyle/controls/DefaultTextArea.qml b/src/quicknativestyle/controls/DefaultTextArea.qml index 4ed9427ba..faab250fa 100644 --- a/src/quicknativestyle/controls/DefaultTextArea.qml +++ b/src/quicknativestyle/controls/DefaultTextArea.qml @@ -34,8 +34,8 @@ T.TextArea { id: placeholder x: control.leftPadding y: control.topPadding - width: control.availableWidth - height: control.availableHeight + width: control.width - (control.leftPadding + control.rightPadding) + height: control.height - (control.topPadding + control.bottomPadding) text: control.placeholderText font: control.font color: control.placeholderTextColor diff --git a/src/quickshapes/qquickshape.cpp b/src/quickshapes/qquickshape.cpp index 396f78660..e6f883bb2 100644 --- a/src/quickshapes/qquickshape.cpp +++ b/src/quickshapes/qquickshape.cpp @@ -664,6 +664,7 @@ QQuickShape::~QQuickShape() /*! \qmlproperty enumeration QtQuick.Shapes::Shape::rendererType + \readonly This property determines which path rendering backend is active. @@ -845,6 +846,7 @@ void QQuickShape::setVendorExtensionsEnabled(bool enable) /*! \qmlproperty enumeration QtQuick.Shapes::Shape::status + \readonly This property determines the status of the Shape and is relevant when Shape.asynchronous is set to \c true. diff --git a/src/quicktemplates/qquickabstractbutton.cpp b/src/quicktemplates/qquickabstractbutton.cpp index 86a28e966..e41c065b3 100644 --- a/src/quicktemplates/qquickabstractbutton.cpp +++ b/src/quicktemplates/qquickabstractbutton.cpp @@ -822,7 +822,7 @@ void QQuickAbstractButton::setIcon(const QQuickIcon &icon) \header \li Display \li Result \row \li \c AbstractButton.IconOnly \li \image qtquickcontrols-button-icononly.png \row \li \c AbstractButton.TextOnly \li \image qtquickcontrols-button-textonly.png - \row \li \c AbstractButton.TextBesideIcon \li \image qtquickcontrols-button-textbesideicon.png + \row \li \c AbstractButton.TextBesideIcon (default) \li \image qtquickcontrols-button-textbesideicon.png \row \li \c AbstractButton.TextUnderIcon \li \image qtquickcontrols-button-textundericon.png \endtable diff --git a/src/quicktemplates/qquickapplicationwindow.cpp b/src/quicktemplates/qquickapplicationwindow.cpp index 29f6e6350..ac9786472 100644 --- a/src/quicktemplates/qquickapplicationwindow.cpp +++ b/src/quicktemplates/qquickapplicationwindow.cpp @@ -332,7 +332,12 @@ QQuickApplicationWindowAttached *QQuickApplicationWindow::qmlAttachedProperties( \note If the background item has no explicit size specified, it automatically follows the control's size. In most cases, there is no need to specify - width or height for a background item. + width or height for a background item. However, when using Image as + the background, for example, a change in \l {Image::}{source} without + a change in size can cause the image to be incorrectly sized (at its + natural size, rather than the size of the window). This is because the + resizing done by ApplicationWindow is not considered "explicit". This is one + instance where it is necessary to set the size manually. \sa {Customizing ApplicationWindow}, contentItem, header, footer */ diff --git a/src/quicktemplates/qquickdrawer.cpp b/src/quicktemplates/qquickdrawer.cpp index ffe201891..9eb8f830a 100644 --- a/src/quicktemplates/qquickdrawer.cpp +++ b/src/quicktemplates/qquickdrawer.cpp @@ -12,6 +12,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -164,15 +165,25 @@ qreal QQuickDrawerPrivate::positionAt(const QPointF &point) const if (!window) return 0; - switch (edge) { + auto size = QSizeF(q->width(), q->height()); + + switch (effectiveEdge()) { case Qt::TopEdge: - return point.y() / q->height(); + if (edge == Qt::LeftEdge || edge == Qt::RightEdge) + size.transpose(); + return point.y() / size.height(); case Qt::LeftEdge: - return point.x() / q->width(); + if (edge == Qt::TopEdge || edge == Qt::BottomEdge) + size.transpose(); + return point.x() / size.width(); case Qt::RightEdge: - return (window->width() - point.x()) / q->width(); + if (edge == Qt::TopEdge || edge == Qt::BottomEdge) + size.transpose(); + return (window->width() - point.x()) / size.width(); case Qt::BottomEdge: - return (window->height() - point.y()) / q->height(); + if (edge == Qt::LeftEdge || edge == Qt::RightEdge) + size.transpose(); + return (window->height() - point.y()) / size.height(); default: return 0; } @@ -216,22 +227,24 @@ void QQuickDrawerPositioner::reposition() QQuickPopupPositioner::reposition(); } -void QQuickDrawerPrivate::showOverlay() +void QQuickDrawerPrivate::showDimmer() { // managed in setPosition() } -void QQuickDrawerPrivate::hideOverlay() +void QQuickDrawerPrivate::hideDimmer() { // managed in setPosition() } -void QQuickDrawerPrivate::resizeOverlay() +void QQuickDrawerPrivate::resizeDimmer() { if (!dimmer || !window) return; - QRectF geometry(0, 0, window->width(), window->height()); + const QQuickOverlay *overlay = QQuickOverlay::overlay(window); + + QRectF geometry(0, 0, overlay ? overlay->width() : 0, overlay ? overlay->height() : 0); if (edge == Qt::LeftEdge || edge == Qt::RightEdge) { geometry.setY(popupItem->y()); @@ -245,17 +258,18 @@ void QQuickDrawerPrivate::resizeOverlay() dimmer->setSize(geometry.size()); } -static bool isWithinDragMargin(const QQuickDrawer *drawer, const QPointF &pos) +bool QQuickDrawerPrivate::isWithinDragMargin(const QPointF &pos) const { - switch (drawer->edge()) { + Q_Q(const QQuickDrawer); + switch (effectiveEdge()) { case Qt::LeftEdge: - return pos.x() <= drawer->dragMargin(); + return pos.x() <= q->dragMargin(); case Qt::RightEdge: - return pos.x() >= drawer->window()->width() - drawer->dragMargin(); + return pos.x() >= q->window()->width() - q->dragMargin(); case Qt::TopEdge: - return pos.y() <= drawer->dragMargin(); + return pos.y() <= q->dragMargin(); case Qt::BottomEdge: - return pos.y() >= drawer->window()->height() - drawer->dragMargin(); + return pos.y() >= q->window()->height() - q->dragMargin(); default: Q_UNREACHABLE(); break; @@ -265,14 +279,13 @@ static bool isWithinDragMargin(const QQuickDrawer *drawer, const QPointF &pos) bool QQuickDrawerPrivate::startDrag(QEvent *event) { - Q_Q(QQuickDrawer); delayedEnterTransition = false; if (!window || !interactive || dragMargin < 0.0 || qFuzzyIsNull(dragMargin)) return false; switch (event->type()) { case QEvent::MouseButtonPress: - if (QMouseEvent *mouseEvent = static_cast(event); isWithinDragMargin(q, mouseEvent->scenePosition())) { + if (QMouseEvent *mouseEvent = static_cast(event); isWithinDragMargin(mouseEvent->scenePosition())) { // watch future events and grab the mouse once it has moved // sufficiently fast or far (in grabMouse). delayedEnterTransition = true; @@ -287,7 +300,7 @@ bool QQuickDrawerPrivate::startDrag(QEvent *event) case QEvent::TouchUpdate: { auto *touchEvent = static_cast(event); for (const QTouchEvent::TouchPoint &point : touchEvent->points()) { - if (point.state() == QEventPoint::Pressed && isWithinDragMargin(q, point.scenePosition())) { + if (point.state() == QEventPoint::Pressed && isWithinDragMargin(point.scenePosition())) { delayedEnterTransition = true; touchEvent->addPassiveGrabber(point, popupItem); handleTouchEvent(window->contentItem(), touchEvent); @@ -325,10 +338,11 @@ bool QQuickDrawerPrivate::grabMouse(QQuickItem *item, QMouseEvent *event) // larger threshold to avoid being too eager to steal touch (QTBUG-50045) const int threshold = qMax(20, QGuiApplication::styleHints()->startDragDistance() + 5); bool overThreshold = false; + Qt::Edge effEdge = effectiveEdge(); if (position > 0 || dragMargin > 0) { const bool xOverThreshold = QQuickWindowPrivate::dragOverThreshold(movePoint.x() - pressPoint.x(), Qt::XAxis, event, threshold); const bool yOverThreshold = QQuickWindowPrivate::dragOverThreshold(movePoint.y() - pressPoint.y(), Qt::YAxis, event, threshold); - if (edge == Qt::LeftEdge || edge == Qt::RightEdge) + if (effEdge == Qt::LeftEdge || effEdge == Qt::RightEdge) overThreshold = xOverThreshold && !yOverThreshold; else overThreshold = yOverThreshold && !xOverThreshold; @@ -336,7 +350,7 @@ bool QQuickDrawerPrivate::grabMouse(QQuickItem *item, QMouseEvent *event) // Don't be too eager to steal presses outside the drawer (QTBUG-53929) if (overThreshold && qFuzzyCompare(position, qreal(1.0)) && !contains(movePoint)) { - if (edge == Qt::LeftEdge || edge == Qt::RightEdge) + if (effEdge == Qt::LeftEdge || effEdge == Qt::RightEdge) overThreshold = qAbs(movePoint.x() - q->width()) < dragMargin; else overThreshold = qAbs(movePoint.y() - q->height()) < dragMargin; @@ -421,8 +435,6 @@ static const qreal openCloseVelocityThreshold = 300; // interactive control. bool QQuickDrawerPrivate::blockInput(QQuickItem *item, const QPointF &point) const { - Q_Q(const QQuickDrawer); - // We want all events, if mouse/touch is already grabbed. if (popupItem->keepMouseGrab() || popupItem->keepTouchGrab()) return true; @@ -436,7 +448,7 @@ bool QQuickDrawerPrivate::blockInput(QQuickItem *item, const QPointF &point) con return false; // Accept all events within drag area. - if (isWithinDragMargin(q, point)) + if (isWithinDragMargin(point)) return true; // Accept all other events if drawer is modal. @@ -487,9 +499,9 @@ bool QQuickDrawerPrivate::handleRelease(QQuickItem *item, const QPointF &point, } velocityCalculator.stopMeasuring(point, timestamp); - + Qt::Edge effEdge = effectiveEdge(); qreal velocity = 0; - if (edge == Qt::LeftEdge || edge == Qt::RightEdge) + if (effEdge == Qt::LeftEdge || effEdge == Qt::RightEdge) velocity = velocityCalculator.velocity().x(); else velocity = velocityCalculator.velocity().y(); @@ -502,7 +514,7 @@ bool QQuickDrawerPrivate::handleRelease(QQuickItem *item, const QPointF &point, // - bottom/right edge: negative velocity opens, positive velocity closes // // => invert the velocity for bottom and right edges, for the threshold comparison below - if (edge == Qt::RightEdge || edge == Qt::BottomEdge) + if (effEdge == Qt::RightEdge || effEdge == Qt::BottomEdge) velocity = -velocity; if (position > 0.7 || velocity > openCloseVelocityThreshold) { @@ -510,7 +522,7 @@ bool QQuickDrawerPrivate::handleRelease(QQuickItem *item, const QPointF &point, } else if (position < 0.3 || velocity < -openCloseVelocityThreshold) { transitionManager.transitionExit(); } else { - switch (edge) { + switch (effEdge) { case Qt::LeftEdge: if (point.x() - pressPoint.x() > 0) transitionManager.transitionEnter(); @@ -641,6 +653,31 @@ Qt::Edge QQuickDrawer::edge() const return d->edge; } +Qt::Edge QQuickDrawerPrivate::effectiveEdge() const +{ + auto realEdge = edge; + qreal rotation = window->contentItem()->rotation(); + const bool clockwise = rotation > 0; + while (qAbs(rotation) >= 90) { + rotation -= clockwise ? 90 : -90; + switch (realEdge) { + case Qt::LeftEdge: + realEdge = clockwise ? Qt::TopEdge : Qt::BottomEdge; + break; + case Qt::TopEdge: + realEdge = clockwise ? Qt::RightEdge : Qt::LeftEdge; + break; + case Qt::RightEdge: + realEdge = clockwise ? Qt::BottomEdge : Qt::TopEdge; + break; + case Qt::BottomEdge: + realEdge = clockwise ? Qt::LeftEdge : Qt::RightEdge; + break; + } + } + return realEdge; +} + void QQuickDrawer::setEdge(Qt::Edge edge) { Q_D(QQuickDrawer); @@ -799,7 +836,7 @@ void QQuickDrawer::geometryChange(const QRectF &newGeometry, const QRectF &oldGe { Q_D(QQuickDrawer); QQuickPopup::geometryChange(newGeometry, oldGeometry); - d->resizeOverlay(); + d->resizeDimmer(); } QT_END_NAMESPACE diff --git a/src/quicktemplates/qquickdrawer_p_p.h b/src/quicktemplates/qquickdrawer_p_p.h index 224e55783..7eae26b0c 100644 --- a/src/quicktemplates/qquickdrawer_p_p.h +++ b/src/quicktemplates/qquickdrawer_p_p.h @@ -35,9 +35,9 @@ class QQuickDrawerPrivate : public QQuickPopupPrivate qreal positionAt(const QPointF &point) const; QQuickPopupPositioner *getPositioner() override; - void showOverlay() override; - void hideOverlay() override; - void resizeOverlay() override; + void showDimmer() override; + void hideDimmer() override; + void resizeDimmer() override; bool startDrag(QEvent *event); bool grabMouse(QQuickItem *item, QMouseEvent *event); @@ -55,6 +55,8 @@ class QQuickDrawerPrivate : public QQuickPopupPrivate bool prepareExitTransition() override; bool setEdge(Qt::Edge edge); + Qt::Edge effectiveEdge() const; + bool isWithinDragMargin(const QPointF &point) const; Qt::Edge edge = Qt::LeftEdge; qreal offset = 0; diff --git a/src/quicktemplates/qquickoverlay.cpp b/src/quicktemplates/qquickoverlay.cpp index dde26c8a8..0e58cf988 100644 --- a/src/quicktemplates/qquickoverlay.cpp +++ b/src/quicktemplates/qquickoverlay.cpp @@ -394,7 +394,7 @@ void QQuickOverlay::geometryChange(const QRectF &newGeometry, const QRectF &oldG Q_D(QQuickOverlay); QQuickItem::geometryChange(newGeometry, oldGeometry); for (QQuickPopup *popup : std::as_const(d->allPopups)) - QQuickPopupPrivate::get(popup)->resizeOverlay(); + QQuickPopupPrivate::get(popup)->resizeDimmer(); } void QQuickOverlay::mousePressEvent(QMouseEvent *event) diff --git a/src/quicktemplates/qquickpane.cpp b/src/quicktemplates/qquickpane.cpp index 2def00b77..3c941548a 100644 --- a/src/quicktemplates/qquickpane.cpp +++ b/src/quicktemplates/qquickpane.cpp @@ -156,12 +156,7 @@ void QQuickPanePrivate::contentChildrenChange() { Q_Q(QQuickPane); - // The first child varies depending on how the content item is declared. - // If it's declared as a child of the Pane, it will be parented to the - // default QQuickContentItem. If it's assigned to the contentItem property - // directly, QQuickControl::contentItem will be used." - QQuickItem *newFirstChild = ((qobject_cast(contentItem)) - ? contentChildItems().value(0) : *contentItem); + QQuickItem *newFirstChild = getFirstChild(); if (newFirstChild != firstChild) { if (firstChild) @@ -191,6 +186,16 @@ qreal QQuickPanePrivate::getContentWidth() const return 0; } +QQuickItem* QQuickPanePrivate::getFirstChild() const +{ + // The first child varies depending on how the content item is declared. + // If it's declared as a child of the Pane, it will be parented to the + // default QQuickContentItem. If it's assigned to the contentItem property + // directly, QQuickControl::contentItem will be used. + return (qobject_cast(contentItem) + ? contentChildItems().value(0) : contentItem.data()); +} + qreal QQuickPanePrivate::getContentHeight() const { if (!contentItem) diff --git a/src/quicktemplates/qquickpane_p_p.h b/src/quicktemplates/qquickpane_p_p.h index fc77d52d0..e9964c70a 100644 --- a/src/quicktemplates/qquickpane_p_p.h +++ b/src/quicktemplates/qquickpane_p_p.h @@ -31,6 +31,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPanePrivate : public QQuickControlP virtual QQmlListProperty contentData(); virtual QQmlListProperty contentChildren(); virtual QList contentChildItems() const; + virtual QQuickItem *getFirstChild() const; QQuickItem *getContentItem() override; diff --git a/src/quicktemplates/qquickpopup.cpp b/src/quicktemplates/qquickpopup.cpp index ca7f89c95..14f1cfbb2 100644 --- a/src/quicktemplates/qquickpopup.cpp +++ b/src/quicktemplates/qquickpopup.cpp @@ -556,7 +556,7 @@ bool QQuickPopupPrivate::prepareEnterTransition() } if (dim) createOverlay(); - showOverlay(); + showDimmer(); emit q->aboutToShow(); visible = true; transitionState = EnterTransition; @@ -593,7 +593,7 @@ bool QQuickPopupPrivate::prepareExitTransition() if (focus) popupItem->setFocus(false, Qt::PopupFocusReason); transitionState = ExitTransition; - hideOverlay(); + hideDimmer(); emit q->aboutToHide(); emit q->openedChanged(); } @@ -880,17 +880,19 @@ void QQuickPopupPrivate::createOverlay() if (!dimmer) { dimmer = createDimmer(component, q, overlay); + if (!dimmer) + return; // We cannot update explicitDimmerOpacity when dimmer's opacity changes, // as it is expected to do so when we fade the dimmer in and out in - // show/hideOverlay, and any binding of the dimmer's opacity will be + // show/hideDimmer, and any binding of the dimmer's opacity will be // implicitly broken anyway. explicitDimmerOpacity = dimmer->opacity(); - // initially fully transparent, showOverlay fades the dimmer in. + // initially fully transparent, showDimmer fades the dimmer in. dimmer->setOpacity(0); if (q->isVisible()) - showOverlay(); + showDimmer(); } - resizeOverlay(); + resizeDimmer(); } void QQuickPopupPrivate::destroyDimmer() @@ -923,27 +925,29 @@ void QQuickPopupPrivate::updateContentPalettes(const QPalette& parentPalette) QQuickItemPrivate::get(popupItem)->updateChildrenPalettes(parentPalette); } -void QQuickPopupPrivate::showOverlay() +void QQuickPopupPrivate::showDimmer() { // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors if (dim && dimmer) QQmlProperty::write(dimmer, QStringLiteral("opacity"), explicitDimmerOpacity); } -void QQuickPopupPrivate::hideOverlay() +void QQuickPopupPrivate::hideDimmer() { // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors if (dim && dimmer) QQmlProperty::write(dimmer, QStringLiteral("opacity"), 0.0); } -void QQuickPopupPrivate::resizeOverlay() +void QQuickPopupPrivate::resizeDimmer() { if (!dimmer) return; - qreal w = window ? window->width() : 0; - qreal h = window ? window->height() : 0; + const QQuickOverlay *overlay = QQuickOverlay::overlay(window); + + qreal w = overlay ? overlay->width() : 0; + qreal h = overlay ? overlay->height() : 0; dimmer->setSize(QSizeF(w, h)); } @@ -2090,7 +2094,7 @@ void QQuickPopup::setVisible(bool visible) if (d->visible == visible && d->transitionState != QQuickPopupPrivate::ExitTransition) return; - if (d->complete) { + if (d->complete && d->window) { if (visible) d->transitionManager.transitionEnter(); else diff --git a/src/quicktemplates/qquickpopup_p_p.h b/src/quicktemplates/qquickpopup_p_p.h index ddff2b19e..defb5e2ea 100644 --- a/src/quicktemplates/qquickpopup_p_p.h +++ b/src/quicktemplates/qquickpopup_p_p.h @@ -96,9 +96,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickPopupPrivate void destroyDimmer(); void toggleOverlay(); void updateContentPalettes(const QPalette& parentPalette); - virtual void showOverlay(); - virtual void hideOverlay(); - virtual void resizeOverlay(); + virtual void showDimmer(); + virtual void hideDimmer(); + virtual void resizeDimmer(); virtual bool prepareEnterTransition(); virtual bool prepareExitTransition(); diff --git a/src/quicktemplates/qquickscrollview.cpp b/src/quicktemplates/qquickscrollview.cpp index e14e8e89d..5f7c7bf2f 100644 --- a/src/quicktemplates/qquickscrollview.cpp +++ b/src/quicktemplates/qquickscrollview.cpp @@ -98,6 +98,7 @@ class QQuickScrollViewPrivate : public QQuickPanePrivate QQmlListProperty contentData() override; QQmlListProperty contentChildren() override; QList contentChildItems() const override; + QQuickItem* getFirstChild() const override; QQuickItem *getContentItem() override; @@ -162,6 +163,11 @@ QQuickItem *QQuickScrollViewPrivate::getContentItem() return ensureFlickable(ContentItemFlag::DoNotSet); } +QQuickItem* QQuickScrollViewPrivate::getFirstChild() const +{ + return contentChildItems().value(0); +} + QQuickFlickable *QQuickScrollViewPrivate::ensureFlickable(ContentItemFlag contentItemFlag) { Q_Q(QQuickScrollView); diff --git a/src/quicktemplates/qquickselectionrectangle.cpp b/src/quicktemplates/qquickselectionrectangle.cpp index 29df45978..80f4ab1b4 100644 --- a/src/quicktemplates/qquickselectionrectangle.cpp +++ b/src/quicktemplates/qquickselectionrectangle.cpp @@ -196,9 +196,14 @@ QQuickSelectionRectanglePrivate::QQuickSelectionRectanglePrivate() return; if (modifiers & Qt::ShiftModifier) { - // Extend the existing selection towards the pressed cell - if (!m_active) - return; + // Extend the selection towards the pressed cell. If there is no + // existing selection, start a new selection from the current item + // to the pressed item. + if (!m_active) { + if (!m_selectable->startSelection(pos)) + return; + m_selectable->setSelectionStartPos(QPoint{-1, -1}); + } m_selectable->setSelectionEndPos(pos); updateHandles(); updateActiveState(true); @@ -237,9 +242,14 @@ QQuickSelectionRectanglePrivate::QQuickSelectionRectanglePrivate() } if (modifiers == Qt::ShiftModifier) { - // Extend the existing selection towards the pressed cell - if (!m_active) - return; + // Extend the selection towards the pressed cell. If there is no + // existing selection, start a new selection from the current item + // to the pressed item. + if (!m_active) { + if (!m_selectable->startSelection(pos)) + return; + m_selectable->setSelectionStartPos(QPoint{-1, -1}); + } m_selectable->setSelectionEndPos(pos); updateHandles(); updateActiveState(true); diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index fb3c8554b..c2c0f6f8d 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -655,6 +655,9 @@ QQuickWidget::~QQuickWidget() delete d->root; d->root = nullptr; + if (d->rhi) + d->rhi->removeCleanupCallback(this); + // NB! resetting graphics resources must be done from this destructor, // *not* from the private class' destructor. This is due to how destruction // works and due to the QWidget dtor (for toplevels) destroying the repaint @@ -1021,8 +1024,19 @@ void QQuickWidgetPrivate::initializeWithRhi() if (rhi) return; - if (QWidgetRepaintManager *repaintManager = tlwd->maybeRepaintManager()) + if (QWidgetRepaintManager *repaintManager = tlwd->maybeRepaintManager()) { rhi = repaintManager->rhi(); + if (rhi) { + // We don't own the RHI, so make sure we clean up if it goes away + rhi->addCleanupCallback(q, [this](QRhi *rhi) { + if (this->rhi == rhi) { + invalidateRenderControl(); + deviceLost = true; + this->rhi = nullptr; + } + }); + } + } if (!rhi) { // The widget (and its parent chain, if any) may not be shown at @@ -1651,7 +1665,7 @@ bool QQuickWidget::event(QEvent *e) QPointerEvent *pointerEvent = static_cast(e); auto deliveredPoints = pointerEvent->points(); for (auto &point : deliveredPoints) { - if (pointerEvent->exclusiveGrabber(point)) + if (pointerEvent->exclusiveGrabber(point) || !pointerEvent->passiveGrabbers(point).isEmpty()) point.setAccepted(true); } } @@ -1675,6 +1689,8 @@ bool QQuickWidget::event(QEvent *e) } case QEvent::WindowAboutToChangeInternal: + if (d->rhi) + d->rhi->removeCleanupCallback(this); d->invalidateRenderControl(); d->deviceLost = true; d->rhi = nullptr; diff --git a/tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp b/tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp index 4ad9699cb..13fd2e5bd 100644 --- a/tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp +++ b/tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp @@ -105,9 +105,7 @@ private slots: if (newCurrentOutputLine > m_currentOutputLine) { // lets wait a little bit more to not cut anything int triggeredCount = 0; - int debugCounter = 0; do { - debugCounter++; triggeredCount = m_process->output().size(); QTest::qWait(updateTimeOut); newCurrentOutputLine = m_process->output().size(); diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp index 516abed9e..e65c1a325 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp @@ -1124,6 +1124,25 @@ void tst_QJSValue::toVariant() QCOMPARE(func.toVariant().metaType(), QMetaType::fromType()); } + + // object with custom prototype + { + QJSValue object = eng.evaluate(R"js( + (function(){ + function Person(firstName, lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + return new Person("John", "Doe"); + })(); + )js"); + QVERIFY(object.isObject()); + auto asVariant = object.toVariant(); + QCOMPARE(asVariant.metaType(), QMetaType::fromType()); + auto variantMap = asVariant.value(); + QVERIFY(variantMap.contains("firstName")); + QCOMPARE(variantMap["firstName"].toString(), "John"); + } } void tst_QJSValue::toPrimitive_data() diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index 00c04bf4e..f16117df0 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -55,6 +55,7 @@ set(qml_files SelectionRectangle.qml ShadowedObjectName.qml ShadowedObjectNameDerived.qml + StoreMetaEnum.qml Test.qml TestCase.qml WindowDerived.qml @@ -193,10 +194,13 @@ set(qml_files popContextAfterRet.qml prefixedMetaType.qml pressAndHoldButton.qml + reduceWithNullThis.qml readEnumFromInstance.qml registerPropagation.qml registerelimination.qml + renameAdjust.qml revisions.qml + scopeIdLookup.qml scopeVsObject.qml script.js script.mjs diff --git a/tests/auto/qml/qmlcppcodegen/data/StoreMetaEnum.qml b/tests/auto/qml/qmlcppcodegen/data/StoreMetaEnum.qml new file mode 100644 index 000000000..eb3da15a3 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/StoreMetaEnum.qml @@ -0,0 +1,12 @@ +import QtQml + +QtObject { + enum Foo { + Bar, + Baz + } + + property var eF: StoreMetaEnum.Foo + property int bar: eF.Bar + property int baz: eF.Baz +} diff --git a/tests/auto/qml/qmlcppcodegen/data/asCast.qml b/tests/auto/qml/qmlcppcodegen/data/asCast.qml index 1befc08d0..cb8155ca6 100644 --- a/tests/auto/qml/qmlcppcodegen/data/asCast.qml +++ b/tests/auto/qml/qmlcppcodegen/data/asCast.qml @@ -28,4 +28,14 @@ Item { property QtObject dummyAsItem: dummy as Item property QtObject dummyAsRectangle: dummy as Rectangle property QtObject dummyAsDummy: dummy as Dummy + + property QtObject nullAsObject: null as QtObject + property QtObject nullAsItem: null as Item + property QtObject nullAsRectangle: null as Rectangle + property QtObject nullAsDummy: null as Dummy + + property QtObject undefinedAsObject: undefined as QtObject + property QtObject undefinedAsItem: undefined as Item + property QtObject undefinedAsRectangle: undefined as Rectangle + property QtObject undefinedAsDummy: undefined as Dummy } diff --git a/tests/auto/qml/qmlcppcodegen/data/enumConversion.qml b/tests/auto/qml/qmlcppcodegen/data/enumConversion.qml index fee2c50e1..61ddd2162 100644 --- a/tests/auto/qml/qmlcppcodegen/data/enumConversion.qml +++ b/tests/auto/qml/qmlcppcodegen/data/enumConversion.qml @@ -1,7 +1,12 @@ +pragma Strict import TestTypes MyType { id: root + + property alias status: root.a + property int test: myEnumType.type property bool test_1: myEnumType.type + objectName: root.status + "m" } diff --git a/tests/auto/qml/qmlcppcodegen/data/failures.qml b/tests/auto/qml/qmlcppcodegen/data/failures.qml index 80c62bdc8..6109d5cea 100644 --- a/tests/auto/qml/qmlcppcodegen/data/failures.qml +++ b/tests/auto/qml/qmlcppcodegen/data/failures.qml @@ -103,4 +103,6 @@ QtObject { readonly property int someNumber: 10 function writeToReadonly() { someNumber = 20 } + + property var silly: [,0] } diff --git a/tests/auto/qml/qmlcppcodegen/data/reduceWithNullThis.qml b/tests/auto/qml/qmlcppcodegen/data/reduceWithNullThis.qml new file mode 100644 index 000000000..c6fda8c73 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/reduceWithNullThis.qml @@ -0,0 +1,18 @@ +import QtQml + +QtObject { + id: mainItem + property int topPadding: 12 + property int bottomPadding: 12 + + property int preferredHeight: mainItem.children.reduce(maximumImplicitHeightReducer, 0) + topPadding + bottomPadding + function maximumImplicitHeightReducer(accumulator: real, item: Binding): real { + return Math.max(accumulator, (item.objectName + "b").length); + } + + property int preferredHeight2: mainItem.children.reduce((accumulator, item) => { + return Math.max(accumulator, (item.objectName + "b").length); + }, 0) + topPadding + bottomPadding + + property list children: [ Binding { objectName: "aaa" } ] +} diff --git a/tests/auto/qml/qmlcppcodegen/data/renameAdjust.qml b/tests/auto/qml/qmlcppcodegen/data/renameAdjust.qml new file mode 100644 index 000000000..9352163ba --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/renameAdjust.qml @@ -0,0 +1,19 @@ +pragma Strict +import QtQml + +QtObject { + id: last + property int value: 10 + + function verify(i: int) { + if (last.value !== i) + console.error("failed", last.value, i); + else + console.log("success") + } + + Component.onCompleted: { + verify(10) + verify(11) + } +} diff --git a/tests/auto/qml/qmlcppcodegen/data/scopeIdLookup.qml b/tests/auto/qml/qmlcppcodegen/data/scopeIdLookup.qml new file mode 100644 index 000000000..e23f18059 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/scopeIdLookup.qml @@ -0,0 +1,20 @@ +pragma ComponentBehavior: Bound + +import QtQml + +QtObject { + id: root + + property QtObject b: QtObject { + id: bar + objectName: "outer" + } + + property Instantiator i: Instantiator { + model: 1 + delegate: QtObject { + property QtObject bar: QtObject { objectName: "inner" } + Component.onCompleted: root.objectName = bar.objectName + } + } +} diff --git a/tests/auto/qml/qmlcppcodegen/data/urlString.qml b/tests/auto/qml/qmlcppcodegen/data/urlString.qml index 511c54532..a83855ebd 100644 --- a/tests/auto/qml/qmlcppcodegen/data/urlString.qml +++ b/tests/auto/qml/qmlcppcodegen/data/urlString.qml @@ -9,5 +9,12 @@ QtObject { Component.onCompleted: { c = "http://dddddd.com"; self.d = "http://aaaaaa.com"; + myUrlChanged(c) + } + + signal myUrlChanged(urlParam: url) + + onMyUrlChanged: (urlParam) => { + objectName = urlParam; } } diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 0b3dd8dd6..157e35de1 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -159,10 +159,13 @@ private slots: void popContextAfterRet(); void prefixedType(); void propertyOfParent(); + void reduceWithNullThis(); void readEnumFromInstance(); void registerElimination(); void registerPropagation(); + void renameAdjust(); void revisions(); + void scopeIdLookup(); void scopeObjectDestruction(); void scopeVsObject(); void sequenceToIterable(); @@ -176,6 +179,7 @@ private slots: void signatureIgnored(); void simpleBinding(); void storeElementSideEffects(); + void storeMetaEnum(); void stringArg(); void stringLength(); void stringToByteArray(); @@ -616,6 +620,16 @@ void tst_QmlCppCodegen::asCast() QCOMPARE(qvariant_cast(root->property("dummyAsItem")), dummy); QCOMPARE(qvariant_cast(root->property("dummyAsRectangle")), nullptr); QCOMPARE(qvariant_cast(root->property("dummyAsDummy")), dummy); + + QCOMPARE(qvariant_cast(root->property("nullAsObject")), nullptr); + QCOMPARE(qvariant_cast(root->property("nullAsItem")), nullptr); + QCOMPARE(qvariant_cast(root->property("nullAsRectangle")), nullptr); + QCOMPARE(qvariant_cast(root->property("nullAsDummy")), nullptr); + + QCOMPARE(qvariant_cast(root->property("undefinedAsObject")), nullptr); + QCOMPARE(qvariant_cast(root->property("undefinedAsItem")), nullptr); + QCOMPARE(qvariant_cast(root->property("undefinedAsRectangle")), nullptr); + QCOMPARE(qvariant_cast(root->property("undefinedAsDummy")), nullptr); } void tst_QmlCppCodegen::attachedBaseEnum() @@ -1320,6 +1334,7 @@ void tst_QmlCppCodegen::enumConversion() QVERIFY(o); QCOMPARE(o->property("test").toInt(), 0x04); QCOMPARE(o->property("test_1").toBool(), true); + QCOMPARE(o->objectName(), u"0m"_s); } void tst_QmlCppCodegen::enumFromBadSingleton() @@ -3357,6 +3372,18 @@ void tst_QmlCppCodegen::propertyOfParent() } } +void tst_QmlCppCodegen::reduceWithNullThis() +{ + QQmlEngine engine; + QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/reduceWithNullThis.qml"_s)); + QVERIFY2(component.isReady(), component.errorString().toUtf8()); + QScopedPointer object(component.create()); + QVERIFY(!object.isNull()); + + QCOMPARE(object->property("preferredHeight").toDouble(), 28.0); + QCOMPARE(object->property("preferredHeight2").toDouble(), 28.0); +} + void tst_QmlCppCodegen::readEnumFromInstance() { QQmlEngine engine; @@ -3422,6 +3449,19 @@ void tst_QmlCppCodegen::registerPropagation() QCOMPARE(undefined, u"undefined"_s); } +void tst_QmlCppCodegen::renameAdjust() +{ + QQmlEngine engine; + QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/renameAdjust.qml"_s)); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + + QTest::ignoreMessage(QtDebugMsg, "success"); + QTest::ignoreMessage(QtCriticalMsg, "failed 10 11"); + + QScopedPointer o(c.create()); + QVERIFY(o); +} + void tst_QmlCppCodegen::revisions() { QQmlEngine engine; @@ -3434,6 +3474,16 @@ void tst_QmlCppCodegen::revisions() QCOMPARE(o->property("gotten").toInt(), 5); } +void tst_QmlCppCodegen::scopeIdLookup() +{ + QQmlEngine engine; + QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/scopeIdLookup.qml"_s)); + QVERIFY2(!component.isError(), component.errorString().toUtf8()); + QScopedPointer object(component.create()); + QVERIFY(!object.isNull()); + QCOMPARE(object->property("objectName").toString(), u"outer"_s); +} + void tst_QmlCppCodegen::scopeObjectDestruction() { QQmlEngine engine; @@ -3657,6 +3707,20 @@ void tst_QmlCppCodegen::storeElementSideEffects() QCOMPARE(prop.property(0).toInt(), 10); } +void tst_QmlCppCodegen::storeMetaEnum() +{ + QQmlEngine engine; + + QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/StoreMetaEnum.qml"_s)); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + + QScopedPointer o(c.create()); + QVERIFY(o); + + QCOMPARE(o->property("bar").toInt(), 0); + QCOMPARE(o->property("baz").toInt(), 1); +} + void tst_QmlCppCodegen::stringArg() { QQmlEngine engine; @@ -3985,6 +4049,7 @@ void tst_QmlCppCodegen::urlString() QCOMPARE(qvariant_cast(rootObject->property("c")), QUrl(u"http://dddddd.com"_s)); QCOMPARE(qvariant_cast(rootObject->property("d")), QUrl(u"http://aaaaaa.com"_s)); QCOMPARE(qvariant_cast(rootObject->property("e")), QUrl(u"http://a112233.de"_s)); + QCOMPARE(rootObject->objectName(), QLatin1String("http://dddddd.com")); } void tst_QmlCppCodegen::valueTypeBehavior() diff --git a/tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml b/tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml new file mode 100644 index 000000000..8ae4dd7c8 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml @@ -0,0 +1,4 @@ +Item { + // should keep its comma + property var some_array_literal: [30, 20, 0.3,] +} diff --git a/tests/auto/qml/qmlformat/data/arrayEndComma.qml b/tests/auto/qml/qmlformat/data/arrayEndComma.qml new file mode 100644 index 000000000..1aec09515 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/arrayEndComma.qml @@ -0,0 +1,8 @@ +Item { + // should keep its comma + property var some_array_literal: [ + 30, + 20, + 0.3, + ] +} diff --git a/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml b/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml index 0c7a2829c..8eaac7117 100644 --- a/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml +++ b/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml @@ -1,13 +1,15 @@ Item { - property var test: [{ + property var test: [ + { // Testing "foo": "bar" - }] + } + ] onTestChanged: { fooBar(test, { - // Testing - "foo": "bar" - }); + // Testing + "foo": "bar" + }); } } diff --git a/tests/auto/qml/qmlformat/data/dontRemoveComments.qml b/tests/auto/qml/qmlformat/data/dontRemoveComments.qml index 179783487..2d2b4b670 100644 --- a/tests/auto/qml/qmlformat/data/dontRemoveComments.qml +++ b/tests/auto/qml/qmlformat/data/dontRemoveComments.qml @@ -1,8 +1,10 @@ Item { - property var test: [{ -// Testing + property var test: [ + { + // Testing "foo": "bar" - }] + } + ] onTestChanged: { fooBar(test, { diff --git a/tests/auto/qml/qmlformat/data/escapeChars.formatted.qml b/tests/auto/qml/qmlformat/data/escapeChars.formatted.qml new file mode 100644 index 000000000..3cb99b704 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/escapeChars.formatted.qml @@ -0,0 +1,15 @@ +import QtQuick + +Item { + x: { + const s = "\""; + let a = { + "\"": "\\" + }; + let patron = { + "\\\"\n\n": "\?\?\\\"", + "": "", + "\'\"\n": 1 + }; + } +} diff --git a/tests/auto/qml/qmlformat/data/escapeChars.qml b/tests/auto/qml/qmlformat/data/escapeChars.qml new file mode 100644 index 000000000..c82ff3119 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/escapeChars.qml @@ -0,0 +1,16 @@ +import QtQuick + +Item { + x: { + const s = "\"" + let a = { + "\"": "\\" + }; + + let patron = { + "\\\"\n\n" : "\?\?\\\"","": "", "\'\"\n":1 + }; + + + } +} diff --git a/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml b/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml index dfd9bcf7e..3feac7368 100644 --- a/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml +++ b/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml @@ -107,25 +107,25 @@ QtObject { myLambda(myObject); }; myFunction(({ - a, - b: { - c, - d: [firstD] - }, - e: { - f, - g: { - h, - i: [, secondI] - } + a, + b: { + c, + d: [firstD] + }, + e: { + f, + g: { + h, + i: [, secondI] } - }) => { - console.log(a); // 1 - console.log(c); // 2 - console.log(firstD); // 3 - console.log(f); // 6 - console.log(h); // 7 - console.log(secondI); // 9 - }); + } + }) => { + console.log(a); // 1 + console.log(c); // 2 + console.log(firstD); // 3 + console.log(f); // 6 + console.log(h); // 7 + console.log(secondI); // 9 + }); } } diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp index 11c31d8fe..eff3d518f 100644 --- a/tests/auto/qml/qmlformat/tst_qmlformat.cpp +++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp @@ -343,6 +343,9 @@ void TestQmlformat::testFormat_data() QTest::newRow("ellipsisFunctionArgument") << "ellipsisFunctionArgument.qml" << "ellipsisFunctionArgument.formatted.qml" << QStringList{} << RunOption::OnCopy; + QTest::newRow("arrayEndComma") + << "arrayEndComma.qml" + << "arrayEndComma.formatted.qml" << QStringList{} << RunOption::OnCopy; } void TestQmlformat::testFormat() diff --git a/tests/auto/qml/qmlsplitlib/CMakeLists.txt b/tests/auto/qml/qmlsplitlib/CMakeLists.txt index f9783941c..a0ae9dfde 100644 --- a/tests/auto/qml/qmlsplitlib/CMakeLists.txt +++ b/tests/auto/qml/qmlsplitlib/CMakeLists.txt @@ -13,6 +13,17 @@ generate_export_header(tst_qmlsplitlib_library) target_link_libraries(tst_qmlsplitlib_library Qt::Core Qt::QmlIntegration) +qt_add_library(tst-qmlsplitlib-library-2 + lib2.h + lib2.cpp +) +qt_autogen_tools_initial_setup(tst-qmlsplitlib-library-2) +target_include_directories(tst-qmlsplitlib-library-2 PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # find autogenerated header +generate_export_header(tst-qmlsplitlib-library-2) + +target_link_libraries(tst-qmlsplitlib-library-2 Qt::Core Qt::QmlIntegration) + + qt_internal_add_test(tst_qmlsplitlib SOURCES tst_qmlsplitlib.cpp @@ -23,6 +34,7 @@ qt_internal_add_test(tst_qmlsplitlib qt_autogen_tools_initial_setup(tst_qmlsplitlib) qt6_generate_foreign_qml_types(tst_qmlsplitlib_library tst_qmlsplitlib) +qt6_generate_foreign_qml_types(tst-qmlsplitlib-library-2 tst_qmlsplitlib) qt_policy(SET QTP0001 NEW) @@ -30,6 +42,7 @@ qt6_add_qml_module(tst_qmlsplitlib URI "SplitLib" QML_FILES main.qml + main2.qml ) -target_link_libraries(tst_qmlsplitlib PRIVATE tst_qmlsplitlib_library) +target_link_libraries(tst_qmlsplitlib PRIVATE tst_qmlsplitlib_library tst-qmlsplitlib-library-2) diff --git a/tests/auto/qml/qmlsplitlib/lib2.cpp b/tests/auto/qml/qmlsplitlib/lib2.cpp new file mode 100644 index 000000000..d4489f5c7 --- /dev/null +++ b/tests/auto/qml/qmlsplitlib/lib2.cpp @@ -0,0 +1,5 @@ +#include "lib2.h" + +bool SplitLib2::transmogrify() { return true; } + +#include "moc_lib2.cpp" diff --git a/tests/auto/qml/qmlsplitlib/lib2.h b/tests/auto/qml/qmlsplitlib/lib2.h new file mode 100644 index 000000000..480ec7709 --- /dev/null +++ b/tests/auto/qml/qmlsplitlib/lib2.h @@ -0,0 +1,30 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef SPLITLIB_LIB2_H +#define SPLITLIB_LIB2_H +#include "tst-qmlsplitlib-library-2_export.h" + +#include +#include +#include + +class TST_QMLSPLITLIB_LIBRARY_2_EXPORT SplitLib2 : public QObject +{ +public: + Q_OBJECT + QML_ELEMENT + + Q_INVOKABLE bool transmogrify(); +}; + + +class TST_QMLSPLITLIB_LIBRARY_2_EXPORT Foo2 : public QObject +{ +public: + Q_OBJECT + QML_NAMED_ELEMENT(Bar2) + QML_SINGLETON +}; + +#endif diff --git a/tests/auto/qml/qmlsplitlib/main2.qml b/tests/auto/qml/qmlsplitlib/main2.qml new file mode 100644 index 000000000..9b42b70fd --- /dev/null +++ b/tests/auto/qml/qmlsplitlib/main2.qml @@ -0,0 +1,8 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import SplitLib + +SplitLib2 { + property string s: Bar2.objectName +} diff --git a/tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp b/tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp index 893ed77ff..92a9e07c4 100644 --- a/tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp +++ b/tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp @@ -6,12 +6,14 @@ #include #include #include "lib.h" +#include "lib2.h" class tst_splitlib : public QObject { Q_OBJECT private slots: void verifyComponent(); + void verifyComponent2(); }; void tst_splitlib::verifyComponent() @@ -25,5 +27,16 @@ void tst_splitlib::verifyComponent() QVERIFY(lib); } +void tst_splitlib::verifyComponent2() +{ + QQmlEngine engine; + QQmlComponent c(&engine, QStringLiteral("qrc:/qt/qml/SplitLib/main2.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer o(c.create()); + QVERIFY(!o.isNull()); + auto lib = qobject_cast(o.get()); + QVERIFY(lib); +} + QTEST_MAIN(tst_splitlib) #include "tst_qmlsplitlib.moc" diff --git a/tests/auto/qml/qmltc/CMakeLists.txt b/tests/auto/qml/qmltc/CMakeLists.txt index 3aee154ae..8c397405e 100644 --- a/tests/auto/qml/qmltc/CMakeLists.txt +++ b/tests/auto/qml/qmltc/CMakeLists.txt @@ -4,6 +4,7 @@ add_subdirectory(QmltcTests) add_subdirectory(NamespaceTest/Subfolder) add_subdirectory(QmltcExportedTests) +add_subdirectory(QmltcExportedNoFileNameTest) set(test_sources nameconflict.h nameconflict.cpp @@ -22,6 +23,8 @@ set(qmltc_module_libs qmltc_namespace_test_moduleplugin qmltc_exported_tests_module qmltc_exported_tests_moduleplugin + qmltc_exported_no_file_name_test_module + qmltc_exported_no_file_name_test_moduleplugin ) qt_internal_add_test(tst_qmltc_diskcache SOURCES ${test_sources} diff --git a/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/CMakeLists.txt new file mode 100644 index 000000000..47f920129 --- /dev/null +++ b/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_add_library(qmltc_exported_no_file_name_test_module STATIC) +qt_autogen_tools_initial_setup(qmltc_exported_no_file_name_test_module) + +set(common_libraries + Qt::QuickPrivate +) + +target_link_libraries(qmltc_exported_no_file_name_test_module PUBLIC ${common_libraries}) + +qt_policy(SET QTP0001 NEW) + +qt6_add_qml_module(qmltc_exported_no_file_name_test_module + URI QmltcExportedNoFileNameTest + QML_FILES + HelloExportedWorldNoFileName.qml + DEPENDENCIES + Qt::Quick + ENABLE_TYPE_COMPILER + QMLTC_EXPORT_DIRECTIVE "Q_DECL_EXPORT" + # explicitly omitting QMLTC_EXPORT_FILE_NAME +) + +target_include_directories(qmltc_exported_no_file_name_test_module PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + +qt_autogen_tools_initial_setup(qmltc_exported_no_file_name_test_moduleplugin) diff --git a/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/HelloExportedWorldNoFileName.qml b/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/HelloExportedWorldNoFileName.qml new file mode 100644 index 000000000..89986df5a --- /dev/null +++ b/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/HelloExportedWorldNoFileName.qml @@ -0,0 +1,5 @@ +import QtQml + +QtObject { + property string myString: "Hello! I should be exported by qmltc" +} diff --git a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt index bb6d8c88f..11216ae13 100644 --- a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt +++ b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt @@ -110,6 +110,7 @@ set(qml_sources singletons.qml mySignals.qml myCheckBox.qml + signalConnections.qml # support types: DefaultPropertySingleChild.qml diff --git a/tests/auto/qml/qmltc/QmltcTests/signalConnections.qml b/tests/auto/qml/qmltc/QmltcTests/signalConnections.qml new file mode 100644 index 000000000..abcf6fdd6 --- /dev/null +++ b/tests/auto/qml/qmltc/QmltcTests/signalConnections.qml @@ -0,0 +1,46 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQml + +QtObject { + id: root + + property bool cycleEnabled: false + property bool cycleFirst: false + property bool cycleSecond: false + + property Timer enableTimer: Timer { + running: root.cycleEnabled + interval: 1 + onTriggered: { + conn.enabled = !conn.enabled; + root.cycleEnabled = false; + } + } + + property Timer firstTimer: Timer { + id: firstTimer + objectName: "first" + running: root.cycleFirst + interval: 1 + onTriggered: root.cycleFirst = false + } + + property Timer secondTimer: Timer { + objectName: "second" + running: root.cycleSecond + interval: 1 + onTriggered: conn.target = this; + repeat: true + } + + property Connections conn: Connections { + id: conn + target: firstTimer + function onTriggered(m) { + root.objectName = target.objectName + root.cycleSecond = false; + } + } +} diff --git a/tests/auto/qml/qmltc/tst_qmltc.cpp b/tests/auto/qml/qmltc/tst_qmltc.cpp index a95c187fe..c157d7e87 100644 --- a/tests/auto/qml/qmltc/tst_qmltc.cpp +++ b/tests/auto/qml/qmltc/tst_qmltc.cpp @@ -79,12 +79,14 @@ #include "aliases.h" #include "inlinecomponentsfromdifferentfiles.h" #include "helloexportedworld.h" +#include "helloexportedworldnofilename.h" #include "testprivateproperty.h" #include "singletons.h" #include "mysignals.h" #include "namespacedtypes.h" #include "type.h" +#include "signalconnections.h" // Qt: #include @@ -3225,4 +3227,37 @@ void tst_qmltc::checkExportsAreCompiling() QCOMPARE(w.myString(), u"Hello! I should be exported by qmltc"_s); } +void tst_qmltc::checkExportsNoFileName() +{ + QQmlEngine e; + QmltcExportedNoFileNameTest::HelloExportedWorldNoFileName w(&e); + QCOMPARE(w.myString(), u"Hello! I should be exported by qmltc"_s); +} + +void tst_qmltc::signalConnections() +{ + QQmlEngine e; + PREPEND_NAMESPACE(signalConnections) createdByQmltc(&e); + + QVERIFY(createdByQmltc.objectName().isEmpty()); + createdByQmltc.setCycleFirst(true); + QTRY_VERIFY(!createdByQmltc.cycleFirst()); + QCOMPARE(createdByQmltc.objectName(), QLatin1String("first")); + + createdByQmltc.setObjectName(QLatin1String("none")); + createdByQmltc.setCycleEnabled(true); + QTRY_VERIFY(!createdByQmltc.cycleEnabled()); + + createdByQmltc.setCycleFirst(true); + QTRY_VERIFY(!createdByQmltc.cycleFirst()); + QCOMPARE(createdByQmltc.objectName(), QLatin1String("none")); + + createdByQmltc.setCycleEnabled(true); + QTRY_VERIFY(!createdByQmltc.cycleEnabled()); + + createdByQmltc.setCycleSecond(true); + QTRY_VERIFY(!createdByQmltc.cycleSecond()); + QCOMPARE(createdByQmltc.objectName(), QLatin1String("second")); +} + QTEST_MAIN(tst_qmltc) diff --git a/tests/auto/qml/qmltc/tst_qmltc.h b/tests/auto/qml/qmltc/tst_qmltc.h index 8874200ad..767718d80 100644 --- a/tests/auto/qml/qmltc/tst_qmltc.h +++ b/tests/auto/qml/qmltc/tst_qmltc.h @@ -95,4 +95,6 @@ private slots: void cppNamespaces(); void namespacedName(); void checkExportsAreCompiling(); + void checkExportsNoFileName(); + void signalConnections(); }; diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp index e484589da..48d34c654 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp @@ -566,7 +566,7 @@ void tst_qmltyperegistrar::uncreatable() qmlRegisterTypesAndRevisions("A", 1); } -void tst_qmltyperegistrar::singletonVesions() +void tst_qmltyperegistrar::singletonVersions() { QQmlEngine engine; qmlRegisterTypesAndRevisions("A", 0); @@ -581,7 +581,7 @@ void tst_qmltyperegistrar::singletonVesions() " property QtObject v1: SingletonVesion1\n" "}", QUrl()); QVERIFY2(c.isReady(), qPrintable(c.errorString())); - auto obj = c.create(); + QScopedPointer obj(c.create()); QVERIFY2(!obj->property("v0").isNull(), "Singleton version 0 is not registered"); QVERIFY2(!obj->property("v1").isNull(), "Singleton version 1 is not registered"); } diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h index 53607359f..ac4630c56 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h @@ -704,7 +704,7 @@ private slots: void methodReturnType(); void hasIsConstantInParameters(); void uncreatable(); - void singletonVesions(); + void singletonVersions(); #ifdef QT_QUICK_LIB void foreignRevisionedProperty(); diff --git a/tests/auto/qml/qqmldelegatemodel/data/clearCacheDuringInsertion.qml b/tests/auto/qml/qqmldelegatemodel/data/clearCacheDuringInsertion.qml new file mode 100644 index 000000000..da69e55a1 --- /dev/null +++ b/tests/auto/qml/qqmldelegatemodel/data/clearCacheDuringInsertion.qml @@ -0,0 +1,138 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtQuick.Window +import QtQuick.Controls +import QtQuick.Layouts +import QtQml.Models + +Window { + id: root + width: 640 + height: 480 + visible: true + color: "#111111" + + Column { + spacing: 1 + Repeater { + model: 1000 + + Rectangle { + width: 100 + height: 100 + color: "grey" + DelegateModel { + id: delegateModel + delegate: Rectangle { + width: 100 + height: 20 + color: "black" + Text { + anchors.centerIn: parent + text: "Name: " + model.name + color: "white" + } + } + + property int length: 0 + property var filterAcceptsItem: function(item) { return true; } + + model: ListModel { + id: myModel + + ListElement { + name: "tomato" + classifications: [ + ListElement { classification: "fruit" }, + ListElement { classification: "veg" } + ] + nutritionFacts: [ + ListElement { + calories: "45" + } + ] + } + + ListElement { + name: "apple" + classifications: [ + ListElement { classification: "fruit" } + ] + nutritionFacts: [ + ListElement { + calories: "87" + } + ] + } + + ListElement { + name: "broccoli" + classifications: [ + ListElement { classification: "veg" } + ] + nutritionFacts: [ + ListElement { + calories: "12" + } + ] + } + + ListElement { + name: "squash" + classifications: [ + ListElement { classification: "veg" } + ] + nutritionFacts: [ + ListElement { + calories: "112" + } + ] + } + } + + groups: [ + DelegateModelGroup { id: visibleItems; name: "visible" }, + DelegateModelGroup { name: "veg" }, + DelegateModelGroup { name: "fruit"; includeByDefault: true } + ] + + function update() { + + // Step 1: Filter items + var visible = []; + for (var i = 0; i < items.count; ++i) { + var item = items.get(i); + if (filterAcceptsItem(item.model)) { + visible.push(item); + } + } + + // Step 2: Add all items to the visible group: + for (i = 0; i < visible.length; ++i) { + items.insert(visible[i], delegateModel.filterOnGroup) + } + delegateModel.length = visible.length + } + + items.onChanged: update() + onFilterAcceptsItemChanged: update() + + filterOnGroup: "visible" + Component.onCompleted: { + for(var i = 0; i < myModel.count; i++) { + var temp = 0; + var entry = myModel.get(i); + + for (var j = 0; j < entry.classifications.count; j++) { + temp = entry.classifications.get(j) + items.insert(entry, temp.classification) + } + } + } + } + } + } + } +} diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp index c8f6c39b1..ea049b718 100644 --- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp +++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp @@ -34,6 +34,7 @@ private slots: void deleteRace(); void persistedItemsStayInCache(); void doNotUnrefObjectUnderConstruction(); + void clearCacheDuringInsertion(); }; class AbstractItemModel : public QAbstractItemModel @@ -485,6 +486,16 @@ void tst_QQmlDelegateModel::doNotUnrefObjectUnderConstruction() QTRY_COMPARE(object->property("testModel").toInt(), 0); } +void tst_QQmlDelegateModel::clearCacheDuringInsertion() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("clearCacheDuringInsertion.qml")); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + std::unique_ptr object(component.create()); + QVERIFY(object); + QTRY_COMPARE(object->property("testModel").toInt(), 0); +} + QTEST_MAIN(tst_QQmlDelegateModel) #include "tst_qqmldelegatemodel.moc" diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.8.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.8.qml new file mode 100644 index 000000000..7d43aa6c0 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.8.qml @@ -0,0 +1,21 @@ +import Qt.test +import QtQuick + +Item { + id: root + property int count: 0 + signal someSignal + + property Item item: Item { + id: contextItem + function test() { + count++; + } + } + + function itemDestroy() { + contextItem.destroy() + } + + Component.onCompleted: root.someSignal.connect(contextItem, contextItem.test); +} diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.9.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.9.qml new file mode 100644 index 000000000..1123edf3f --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.9.qml @@ -0,0 +1,30 @@ +import Qt.test +import QtQuick + +MyQmlObject { + id: root + property int a: 0 + + signal someSignal + + function disconnectSignal() { + root.someSignal.disconnect(other.MyQmlObject, root.test) + } + + function destroyObj() { + other.destroy() + } + + function test() { + other.MyQmlObject.value2++ + root.a = other.MyQmlObject.value2 + } + + property MyQmlObject obj + obj: MyQmlObject { + id: other + MyQmlObject.value2: 0 + } + + Component.onCompleted: root.someSignal.connect(other.MyQmlObject, root.test) +} diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.deletion.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.deletion.qml new file mode 100644 index 000000000..efbbc9fed --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.deletion.qml @@ -0,0 +1,36 @@ +import Qt.test +import QtQml + +QtObject { + id: root + + property int a: 0 + property int b: 0 + + signal someSignal + + function destroyObj() { + obj.destroy() + } + + function test() { + ++a + } + + component DestructionReceiver: QtObject { + // Has its own context and therefore can receive Component.onDestruction + } + + property QtObject obj: QtObject { + property QtObject inner: DestructionReceiver { + Component.onDestruction: { + // The outer obj is already queued for deletion. + // We don't want to see this signal delivered. + root.someSignal(); + ++root.b + } + } + } + + Component.onCompleted: someSignal.connect(obj, test) +} diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnectSingleton.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnectSingleton.qml new file mode 100644 index 000000000..f666945b3 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/scriptConnectSingleton.qml @@ -0,0 +1,21 @@ +import QtQuick +import Test + +Item { + id: root + + property int a: 0 + signal mySignal + + function test() { + MyInheritedQmlObjectSingleton.value++ + root.a = MyInheritedQmlObjectSingleton.value + } + + function disconnectSingleton() { + root.mySignal.disconnect(MyInheritedQmlObjectSingleton, root.test) + } + + Component.onCompleted: root.mySignal.connect(MyInheritedQmlObjectSingleton, + root.test) +} diff --git a/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.5.qml b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.5.qml new file mode 100644 index 000000000..9d24fa85a --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.5.qml @@ -0,0 +1,19 @@ +import Qt.test +import QtQuick + +Item { + id: root + property int count: 0 + signal someSignal + signal disconnectSignal + + property Item item: Item { + id: contextItem + function test() { + count++; + } + } + + Component.onCompleted: root.someSignal.connect(contextItem, contextItem.test); + onDisconnectSignal: { root.someSignal.disconnect(contextItem, contextItem.test); } +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 4023824f7..02b93bdec 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -3858,6 +3858,82 @@ void tst_qqmlecmascript::scriptConnect() QScopedPointer root { component.create() }; QVERIFY2(root, qPrintable(component.errorString())); } + + { + QQmlComponent component(&engine, testFileUrl("scriptConnect.8.qml")); + + QScopedPointer obj(component.create()); + QVERIFY2(obj, qPrintable(component.errorString())); + QVERIFY(obj.data() != nullptr); + + QCOMPARE(obj.data()->property("count"), 0); + + QMetaObject::invokeMethod(obj.data(), "someSignal"); + QCOMPARE(obj.data()->property("count"), 1); + + QMetaObject::invokeMethod(obj.data(), "itemDestroy"); + QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); + QCoreApplication::processEvents(); + + QMetaObject::invokeMethod(obj.data(), "someSignal"); + QCOMPARE(obj.data()->property("count"), 1); + } + + { + QQmlComponent component(&engine, testFileUrl("scriptConnect.9.qml")); + + QScopedPointer obj(component.create()); + QVERIFY2(obj, qPrintable(component.errorString())); + QVERIFY(obj.data() != nullptr); + + MyQmlObject *object = qobject_cast(obj.data()); + + QCOMPARE(object->property("a"), 0); + + QMetaObject::invokeMethod(object, "someSignal"); + QCOMPARE(object->property("a"), 1); + + QMetaObject::invokeMethod(object, "destroyObj", Qt::DirectConnection); + QApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); + QApplication::processEvents(); + + QMetaObject::invokeMethod(object, "someSignal"); + + QCOMPARE(object->property("a"), 1); + } + + { + QQmlComponent component(&engine, testFileUrl("scriptConnectSingleton.qml")); + + QScopedPointer obj(component.create()); + QVERIFY2(obj, qPrintable(component.errorString())); + QVERIFY(obj.data() != nullptr); + + QMetaObject::invokeMethod(obj.data(), "mySignal", Qt::DirectConnection); + QCOMPARE(obj.data()->property("a").toInt(), 1); + engine.clearSingletons(); + QMetaObject::invokeMethod(obj.data(), "mySignal", Qt::DirectConnection); + QCOMPARE(obj.data()->property("a").toInt(), 1); + } + + { + QQmlComponent component(&engine, testFileUrl("scriptConnect.deletion.qml")); + + QScopedPointer obj(component.create()); + QVERIFY2(obj, qPrintable(component.errorString())); + QVERIFY(!obj.isNull()); + + QCOMPARE(obj->property("a"), 0); + + QMetaObject::invokeMethod(obj.data(), "someSignal"); + QCOMPARE(obj->property("a"), 1); + + QCOMPARE(obj->property("b"), 0); + QMetaObject::invokeMethod(obj.data(), "destroyObj", Qt::DirectConnection); + + QTRY_COMPARE(obj->property("b"), 1); + QCOMPARE(obj->property("a"), 1); + } } void tst_qqmlecmascript::scriptDisconnect() @@ -3938,6 +4014,60 @@ void tst_qqmlecmascript::scriptDisconnect() emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 3); } + + { + QQmlComponent component(&engine, testFileUrl("scriptDisconnect.5.qml")); + + QScopedPointer obj(component.create()); + QVERIFY2(obj, qPrintable(component.errorString())); + QVERIFY(obj.data() != nullptr); + + QCOMPARE(obj.data()->property("count"), 0); + + QMetaObject::invokeMethod(obj.data(), "someSignal"); + QCOMPARE(obj.data()->property("count"), 1); + + QMetaObject::invokeMethod(obj.data(), "disconnectSignal"); + + QMetaObject::invokeMethod(obj.data(), "someSignal"); + QCOMPARE(obj.data()->property("count"), 1); + } + + { + QQmlComponent component(&engine, testFileUrl("scriptConnect.9.qml")); + + QScopedPointer obj(component.create()); + QVERIFY2(obj, qPrintable(component.errorString())); + QVERIFY(obj.data() != nullptr); + + MyQmlObject *object = qobject_cast(obj.data()); + + QCOMPARE(object->property("a"), 0); + + QMetaObject::invokeMethod(object, "someSignal"); + QCOMPARE(object->property("a"), 1); + + QMetaObject::invokeMethod(object, "disconnectSignal", Qt::DirectConnection); + + QMetaObject::invokeMethod(object, "someSignal"); + + QCOMPARE(object->property("a"), 1); + } + + { + QQmlComponent component(&engine, testFileUrl("scriptConnectSingleton.qml")); + + QScopedPointer obj(component.create()); + QVERIFY2(obj, qPrintable(component.errorString())); + QVERIFY(obj.data() != nullptr); + + QMetaObject::invokeMethod(obj.data(), "mySignal", Qt::DirectConnection); + QCOMPARE(obj.data()->property("a").toInt(), 1); + + QMetaObject::invokeMethod(obj.data(), "disconnectSingleton", Qt::DirectConnection); + QMetaObject::invokeMethod(obj.data(), "mySignal", Qt::DirectConnection); + QCOMPARE(obj.data()->property("a").toInt(), 1); + } } class OwnershipObject : public QObject diff --git a/tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml b/tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml index cb8416830..747328360 100644 --- a/tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml +++ b/tests/auto/qmldom/domdata/reformatter/requiredReformatted2.qml @@ -8,7 +8,7 @@ Item { function foo() { theItem.foo("The issue is exacerbated if the object literal is wrapped onto the next line like so:", { - "foo": theFoo - }); + "foo": theFoo + }); } } diff --git a/tests/auto/qmltest/selftests/tst_signalspy.qml b/tests/auto/qmltest/selftests/tst_signalspy.qml new file mode 100644 index 000000000..dbc607e02 --- /dev/null +++ b/tests/auto/qmltest/selftests/tst_signalspy.qml @@ -0,0 +1,53 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtTest + +TestCase { + id: testCase + name: "SignalSpy" + + Component { + id: itemWithAmbigiousSignalNameOnChild + Item { + property Item child: Item { + property bool opened: true + signal opened() + } + } + } + + Component { + id: signalSpy + SignalSpy {} + } + + function init() { + failOnWarning(/.?/) + } + + function test_ambigiousSignalName() { + let control = createTemporaryObject(itemWithAmbigiousSignalNameOnChild, testCase) + verify(control) + + let openedSpy = signalSpy.createObject(control, {target: control.child, signalName: "opened"}) + verify(openedSpy) + compare(openedSpy.target, control.child) + compare(openedSpy.signalName, "opened") + verify(openedSpy.valid) + + // reset the target, i.e. disconnect the spy + openedSpy.target = null + compare(openedSpy.target, null) + compare(openedSpy.signalName, "opened") + verify(!openedSpy.valid) + + // connect again to check that it will be disconnected + // on SignalSpy destruction with no issues/warnings/etc. + openedSpy.target = control.child + compare(openedSpy.target, control.child) + compare(openedSpy.signalName, "opened") + verify(openedSpy.valid) + } +} diff --git a/tests/auto/quick/CMakeLists.txt b/tests/auto/quick/CMakeLists.txt index 15ae6c6a9..070613fcd 100644 --- a/tests/auto/quick/CMakeLists.txt +++ b/tests/auto/quick/CMakeLists.txt @@ -79,7 +79,9 @@ if(QT_FEATURE_private_tests) add_subdirectory(qquickview) add_subdirectory(qquickview_extra) add_subdirectory(qquickcanvasitem) - add_subdirectory(qquickdesignersupport) + if(QT_FEATURE_quick_designer) + add_subdirectory(qquickdesignersupport) + endif() add_subdirectory(qquickscreen) add_subdirectory(touchmouse) add_subdirectory(scenegraph) diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/changingCursor.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/changingCursor.qml new file mode 100644 index 000000000..75bfbf5c3 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/changingCursor.qml @@ -0,0 +1,37 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick 2.15 + + +Rectangle { + id: brownRect + objectName: "brownRect" + + width: 400 + height: 400 + + HoverHandler { + id: hh + cursorShape: parent.colorIndex == 0 ? + Qt.CrossCursor : + Qt.OpenHandCursor + } + + property list colors: ["beige", "brown"] + property int colorIndex: 0 + + color: colors[colorIndex] + + Timer { + id: colorTimer + interval: 200 + running: true + repeat: true + + onTriggered: { + parent.colorIndex = (parent.colorIndex + 1) % parent.colors.length; + parent.color = parent.colors[parent.colorIndex]; + } + } +} diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverHandler.qml b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverHandler.qml new file mode 100644 index 000000000..60dfc53c4 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/data/hoverHandler.qml @@ -0,0 +1,17 @@ +import QtQuick + +Item { + width: 320 + height: 240 + + Rectangle { + width: 100 + height: 100 + anchors.centerIn: parent + color: hh.hovered ? "lightsteelblue" : "beige" + + HoverHandler { + id: hh + } + } +} diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp index e488c0486..ace99daa6 100644 --- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp @@ -48,9 +48,13 @@ private slots: void deviceCursor(); void addHandlerFromCpp(); void ensureHoverHandlerWorksWhenItemHasHoverDisabled(); + void changeCursor(); + void touchDrag(); private: void createView(QScopedPointer &window, const char *fileName); + + QScopedPointer touchscreen = QScopedPointer(QTest::createTouchDevice()); }; void tst_HoverHandler::createView(QScopedPointer &window, const char *fileName) @@ -671,6 +675,74 @@ void tst_HoverHandler::ensureHoverHandlerWorksWhenItemHasHoverDisabled() QCOMPARE(spy.size(), 2); } +void tst_HoverHandler::changeCursor() +{ + QScopedPointer windowPtr; + createView(windowPtr, "changingCursor.qml"); + QQuickView * window = windowPtr.data(); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QQuickItem *item = window->findChild("brownRect"); + QVERIFY(item); + QQuickHoverHandler *hh = item->findChild(); + QVERIFY(hh); + + QPoint itemCenter(item->mapToScene(QPointF(item->width() / 2, item->height() / 2)).toPoint()); + QSignalSpy hoveredSpy(hh, SIGNAL(hoveredChanged())); + + QTest::mouseMove(window, itemCenter); + + QTRY_COMPARE(hoveredSpy.size(), 1); + +#if QT_CONFIG(cursor) + QTRY_COMPARE(window->cursor().shape(), Qt::CrossCursor); + QTRY_COMPARE(window->cursor().shape(), Qt::OpenHandCursor); + QTRY_COMPARE(window->cursor().shape(), Qt::CrossCursor); + QTRY_COMPARE(window->cursor().shape(), Qt::OpenHandCursor); +#endif +} + +void tst_HoverHandler::touchDrag() +{ + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl("hoverHandler.qml"))); + const QQuickItem *root = window.rootObject(); + QQuickHoverHandler *handler = root->findChild(); + QVERIFY(handler); + + // polishAndSync() calls flushFrameSynchronousEvents() before emitting afterAnimating() + QSignalSpy frameSyncSpy(&window, &QQuickWindow::afterAnimating); + + const QPoint out(root->width() - 1, root->height() / 2); + QPoint in(root->width() / 2, root->height() / 2); + + QTest::touchEvent(&window, touchscreen.get()).press(0, out, &window); + QQuickTouchUtils::flush(&window); + QCOMPARE(handler->isHovered(), false); + + frameSyncSpy.clear(); + QTest::touchEvent(&window, touchscreen.get()).move(0, in, &window); + QQuickTouchUtils::flush(&window); + QTRY_COMPARE(handler->isHovered(), true); + QCOMPARE(handler->point().scenePosition(), in); + + in += {10, 10}; + QTest::touchEvent(&window, touchscreen.get()).move(0, in, &window); + QQuickTouchUtils::flush(&window); + // ensure that the color change is visible + QTRY_COMPARE_GE(frameSyncSpy.size(), 1); + QCOMPARE(handler->isHovered(), true); + QCOMPARE(handler->point().scenePosition(), in); + + QTest::touchEvent(&window, touchscreen.get()).move(0, out, &window); + QQuickTouchUtils::flush(&window); + QTRY_COMPARE_GE(frameSyncSpy.size(), 2); + QCOMPARE(handler->isHovered(), false); + + QTest::touchEvent(&window, touchscreen.get()).release(0, out, &window); +} + QTEST_MAIN(tst_HoverHandler) #include "tst_qquickhoverhandler.moc" diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml index fa58d76e4..99672c555 100644 --- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml +++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml @@ -10,13 +10,20 @@ Rectangle { property alias pressed: tap.pressed property bool checked: false property alias gesturePolicy: tap.gesturePolicy + property alias longPressThreshold: tap.longPressThreshold property point tappedPosition: Qt.point(0, 0) + property real timeHeldWhenTapped: 0 + property real timeHeldWhenLongPressed: 0 signal tapped signal canceled width: label.implicitWidth * 1.5; height: label.implicitHeight * 2.0 border.color: "#9f9d9a"; border.width: 1; radius: height / 4; antialiasing: true + function assignUndefinedLongPressThreshold() { + tap.longPressThreshold = undefined + } + gradient: Gradient { GradientStop { position: 0.0; color: tap.pressed ? "#b8b5b2" : "#efebe7" } GradientStop { position: 1.0; color: "#b8b5b2" } @@ -25,14 +32,17 @@ Rectangle { TapHandler { id: tap objectName: label.text - longPressThreshold: 100 // CI can be insanely slow, so don't demand a timely release to generate onTapped onSingleTapped: console.log("Single tap") onDoubleTapped: console.log("Double tap") - onTapped: { - console.log("Tapped") + onTapped: (eventPoint, button) => { + console.log("Tapped", button, eventPoint) tapFlash.start() root.tappedPosition = point.scenePosition root.tapped() + root.timeHeldWhenTapped = tap.timeHeld // eventPoint.timeHeld is already 0 + } + onLongPressed: { + root.timeHeldWhenLongPressed = tap.timeHeld } onCanceled: root.canceled() } diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml index 5731f51f3..4a3264d54 100644 --- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml +++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml @@ -9,19 +9,25 @@ Item { Button { objectName: "DragThreshold" label: "DragThreshold" - x: 10; y: 10; width: parent.width - 20; height: 40 + x: 10; y: 10; width: 300; height: 40 gesturePolicy: TapHandler.DragThreshold } Button { objectName: "WithinBounds" label: "WithinBounds" - x: 10; y: 60; width: parent.width - 20; height: 40 + x: 10; y: 60; width: 300; height: 40 gesturePolicy: TapHandler.WithinBounds } Button { objectName: "ReleaseWithinBounds" label: "ReleaseWithinBounds" - x: 10; y: 110; width: parent.width - 20; height: 40 + x: 10; y: 110; width: 300; height: 40 gesturePolicy: TapHandler.ReleaseWithinBounds } + Button { + objectName: "DragWithinBounds" + label: "DragWithinBounds" + x: 10; y: 160; width: 300; height: 40 + gesturePolicy: TapHandler.DragWithinBounds + } } diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml new file mode 100644 index 000000000..7732c4208 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/nestedAndSibling.qml @@ -0,0 +1,39 @@ +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 + +Item { + width: 360 + height: 280 + + Rectangle { + width: 200; height: 200; x: 100; y: 10 + color: th1.pressed ? "blue" : "lightblue" + + TapHandler { + id: th1 + objectName: "th1" + } + + Rectangle { + width: 200; height: 200; x: 50; y: 50 + color: th2.pressed ? "steelblue" : "lightsteelblue" + + TapHandler { + id: th2 + objectName: "th2" + } + } + } + + Rectangle { + width: 200; height: 200; x: 10; y: 50 + color: th3.pressed ? "goldenrod" : "beige" + + TapHandler { + id: th3 + objectName: "th3" + } + } +} + diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp index a2ea404d6..1df323d37 100644 --- a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp @@ -48,8 +48,8 @@ private slots: void mouseMultiTapLeftRight(); void singleTapDoubleTap_data(); void singleTapDoubleTap(); - void touchLongPress(); - void mouseLongPress(); + void longPress_data(); + void longPress(); void buttonsMultiTouch(); void componentUserBehavioralOverride(); void rightLongPressIgnoreWheel(); @@ -57,6 +57,8 @@ private slots: void nonTopLevelParentWindow(); void nestedDoubleTap_data(); void nestedDoubleTap(); + void nestedAndSiblingPropagation_data(); + void nestedAndSiblingPropagation(); private: void createView(QScopedPointer &window, const char *fileName, @@ -778,76 +780,192 @@ void tst_TapHandler::singleTapDoubleTap() QCOMPARE(singleTapSpy.size(), expectedEndingSingleTapCount); } -void tst_TapHandler::touchLongPress() +void tst_TapHandler::longPress_data() { - QScopedPointer windowPtr; - createView(windowPtr, "buttons.qml"); - QQuickView * window = windowPtr.data(); - - QQuickItem *button = window->rootObject()->findChild("DragThreshold"); - QVERIFY(button); - QQuickTapHandler *tapHandler = button->findChild("DragThreshold"); - QVERIFY(tapHandler); - QSignalSpy tappedSpy(button, SIGNAL(tapped())); - QSignalSpy longPressThresholdChangedSpy(tapHandler, SIGNAL(longPressThresholdChanged())); - QSignalSpy timeHeldSpy(tapHandler, SIGNAL(timeHeldChanged())); - QSignalSpy longPressedSpy(tapHandler, SIGNAL(longPressed())); - - // Reduce the threshold so that we can get a long press quickly - tapHandler->setLongPressThreshold(0.5); - QCOMPARE(longPressThresholdChangedSpy.size(), 1); + QTest::addColumn("device"); + QTest::addColumn("buttonName"); + QTest::addColumn("longPressThreshold"); + QTest::addColumn("releaseOffset"); + QTest::addColumn("expectLongPress"); + QTest::addColumn("expectTapped"); - // Press and hold - QPoint p1 = button->mapToScene(button->clipRect().center()).toPoint(); - QTest::touchEvent(window, touchDevice).press(1, p1, window); - QQuickTouchUtils::flush(window); - QTRY_VERIFY(button->property("pressed").toBool()); - QTRY_COMPARE(longPressedSpy.size(), 1); - timeHeldSpy.wait(); // the longer we hold it, the more this will occur - qDebug() << "held" << tapHandler->timeHeld() << "secs; timeHeld updated" << timeHeldSpy.size() << "times"; - QVERIFY(timeHeldSpy.size() > 0); - QVERIFY(tapHandler->timeHeld() > 0.4); // Should be > 0.5 but slow CI and timer granularity can interfere + const QPointingDevice *constTouchDevice = touchDevice; - // Release and verify that tapped was not emitted - QTest::touchEvent(window, touchDevice).release(1, p1, window); - QQuickTouchUtils::flush(window); - QTRY_VERIFY(!button->property("pressed").toBool()); - QCOMPARE(tappedSpy.size(), 0); + // Reduce the threshold so that we can get a long press quickly (faster in CI) + const qreal longPressThreshold = 0.3; + QTest::newRow("mouse, lpt longPressThreshold: DragThreshold") + << QPointingDevice::primaryPointingDevice() << "DragThreshold" + << longPressThreshold << QPoint(0, 0) << true << false; + QTest::newRow("touch, lpt longPressThreshold: DragThreshold") + << constTouchDevice << "DragThreshold" << longPressThreshold + << QPoint(0, 0) << true << false; + QTest::newRow("mouse, lpt longPressThreshold: DragThreshold, drag") + << QPointingDevice::primaryPointingDevice() << "DragThreshold" + << longPressThreshold << QPoint(50, 0) << false << false; + QTest::newRow("touch, lpt longPressThreshold: DragThreshold, drag") + << constTouchDevice << "DragThreshold" + << longPressThreshold << QPoint(50, 0) << false << false; + + QTest::newRow("mouse, lpt longPressThreshold: WithinBounds") + << QPointingDevice::primaryPointingDevice() << "WithinBounds" + << longPressThreshold << QPoint(0, 0) << true << false; + QTest::newRow("touch, lpt longPressThreshold: WithinBounds") + << constTouchDevice << "WithinBounds" + << longPressThreshold << QPoint(0, 0) << true << false; + QTest::newRow("mouse, lpt longPressThreshold: WithinBounds, drag") + << QPointingDevice::primaryPointingDevice() << "WithinBounds" + << longPressThreshold << QPoint(50, 0) << true << false; + QTest::newRow("touch, lpt longPressThreshold: WithinBounds, drag") + << constTouchDevice << "WithinBounds" + << longPressThreshold << QPoint(50, 0) << true << false; + QTest::newRow("mouse, lpt longPressThreshold: WithinBounds, drag out") + << QPointingDevice::primaryPointingDevice() << "WithinBounds" + << longPressThreshold << QPoint(155, 0) << false << false; + QTest::newRow("touch, lpt longPressThreshold: WithinBounds, drag out") + << constTouchDevice << "WithinBounds" + << longPressThreshold << QPoint(155, 0) << false << false; + + QTest::newRow("mouse, lpt longPressThreshold: ReleaseWithinBounds") + << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds" + << longPressThreshold << QPoint(0, 0) << true << false; + QTest::newRow("touch, lpt longPressThreshold: ReleaseWithinBounds") + << constTouchDevice << "ReleaseWithinBounds" + << longPressThreshold << QPoint(0, 0) << true << false; + QTest::newRow("mouse, lpt longPressThreshold: ReleaseWithinBounds, drag") + << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds" + << longPressThreshold << QPoint(50, 0) << true << false; + QTest::newRow("touch, lpt longPressThreshold: ReleaseWithinBounds, drag") + << constTouchDevice << "ReleaseWithinBounds" + << longPressThreshold << QPoint(50, 0) << true << false; + QTest::newRow("mouse, lpt longPressThreshold: ReleaseWithinBounds, drag out") + << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds" + << longPressThreshold << QPoint(155, 0) << false << false; + QTest::newRow("touch, lpt longPressThreshold: ReleaseWithinBounds, drag out") + << constTouchDevice << "ReleaseWithinBounds" + << longPressThreshold << QPoint(155, 0) << false << false; + + QTest::newRow("mouse, lpt longPressThreshold: DragWithinBounds") + << QPointingDevice::primaryPointingDevice() << "DragWithinBounds" + << longPressThreshold << QPoint(0, 0) << true << false; + QTest::newRow("touch, lpt longPressThreshold: DragWithinBounds") + << constTouchDevice << "DragWithinBounds" + << longPressThreshold << QPoint(0, 0) << true << false; + QTest::newRow("mouse, lpt longPressThreshold: DragWithinBounds, drag") + << QPointingDevice::primaryPointingDevice() << "DragWithinBounds" + << longPressThreshold << QPoint(50, 0) << true << false; + QTest::newRow("touch, lpt longPressThreshold: DragWithinBounds, drag") + << constTouchDevice << "DragWithinBounds" + << longPressThreshold << QPoint(50, 0) << true << false; + QTest::newRow("mouse, lpt longPressThreshold: DragWithinBounds, drag out") + << QPointingDevice::primaryPointingDevice() << "DragWithinBounds" + << longPressThreshold << QPoint(155, 0) << false << false; + QTest::newRow("touch, lpt longPressThreshold: DragWithinBounds, drag out") + << constTouchDevice << "DragWithinBounds" + << longPressThreshold << QPoint(155, 0) << false << false; + + // Zero or negative threshold means long press is disabled + QTest::newRow("mouse, lpt 0: DragThreshold") + << QPointingDevice::primaryPointingDevice() << "DragThreshold" + << qreal(0) << QPoint(0, 0) << false << true; + QTest::newRow("mouse, lpt -1: DragThreshold") + << QPointingDevice::primaryPointingDevice() << "DragThreshold" + << qreal(-1) << QPoint(0, 0) << true << false; + QTest::newRow("touch, lpt 0: DragThreshold") + << constTouchDevice << "DragThreshold" + << qreal(0) << QPoint(0, 0) << false << true; + + QTest::newRow("mouse, lpt 0: WithinBounds") + << QPointingDevice::primaryPointingDevice() << "WithinBounds" + << qreal(0) << QPoint(0, 0) << false << true; + QTest::newRow("mouse, lpt -1: WithinBounds") + << QPointingDevice::primaryPointingDevice() << "WithinBounds" + << qreal(-1) << QPoint(0, 0) << true << false; + QTest::newRow("touch, lpt 0: WithinBounds") + << constTouchDevice << "WithinBounds" + << qreal(0) << QPoint(0, 0) << false << true; + + QTest::newRow("mouse, lpt 0: ReleaseWithinBounds") + << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds" + << qreal(0) << QPoint(0, 0) << false << true; + QTest::newRow("mouse, lpt -1: ReleaseWithinBounds") + << QPointingDevice::primaryPointingDevice() << "ReleaseWithinBounds" + << qreal(-1) << QPoint(0, 0) << true << false; + QTest::newRow("touch, lpt 0: ReleaseWithinBounds") + << constTouchDevice << "ReleaseWithinBounds" + << qreal(0) << QPoint(0, 0) << false << true; + + QTest::newRow("mouse, lpt 0: DragWithinBounds") + << QPointingDevice::primaryPointingDevice() << "DragWithinBounds" + << qreal(0) << QPoint(0, 0) << false << true; + QTest::newRow("mouse, lpt -1: DragWithinBounds") + << QPointingDevice::primaryPointingDevice() << "DragWithinBounds" + << qreal(-1) << QPoint(0, 0) << true << false; + QTest::newRow("touch, lpt 0: DragWithinBounds") + << constTouchDevice << "DragWithinBounds" + << qreal(0) << QPoint(0, 0) << false << true; } -void tst_TapHandler::mouseLongPress() +void tst_TapHandler::longPress() { - QScopedPointer windowPtr; - createView(windowPtr, "buttons.qml"); - QQuickView * window = windowPtr.data(); + QFETCH(const QPointingDevice *, device); + QFETCH(QString, buttonName); + QFETCH(qreal, longPressThreshold); + QFETCH(QPoint, releaseOffset); + QFETCH(bool, expectLongPress); + QFETCH(bool, expectTapped); - QQuickItem *button = window->rootObject()->findChild("DragThreshold"); + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl("buttons.qml"))); + + QQuickItem *button = window.rootObject()->findChild(buttonName); QVERIFY(button); - QQuickTapHandler *tapHandler = button->findChild("DragThreshold"); + QQuickTapHandler *tapHandler = button->findChild(buttonName); QVERIFY(tapHandler); QSignalSpy tappedSpy(button, SIGNAL(tapped())); QSignalSpy longPressThresholdChangedSpy(tapHandler, SIGNAL(longPressThresholdChanged())); QSignalSpy timeHeldSpy(tapHandler, SIGNAL(timeHeldChanged())); QSignalSpy longPressedSpy(tapHandler, SIGNAL(longPressed())); - // Reduce the threshold so that we can get a long press quickly - tapHandler->setLongPressThreshold(0.5); - QCOMPARE(longPressThresholdChangedSpy.size(), 1); + const qreal defaultThreshold = tapHandler->longPressThreshold(); + qsizetype changedCount = 0; + QCOMPARE_GT(defaultThreshold, 0); + tapHandler->setLongPressThreshold(longPressThreshold); + if (longPressThreshold > 0) + QCOMPARE(longPressThresholdChangedSpy.size(), ++changedCount); + QVERIFY(QMetaObject::invokeMethod(button, "assignUndefinedLongPressThreshold")); + if (longPressThreshold > 0) + QCOMPARE(longPressThresholdChangedSpy.size(), ++changedCount); + QCOMPARE(tapHandler->longPressThreshold(), defaultThreshold); + tapHandler->setLongPressThreshold(longPressThreshold); // Press and hold QPoint p1 = button->mapToScene(button->clipRect().center()).toPoint(); - QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); + QQuickTest::pointerPress(device, &window, 1, p1); QTRY_VERIFY(button->property("pressed").toBool()); - QTRY_COMPARE(longPressedSpy.size(), 1); + QTRY_COMPARE(longPressedSpy.size(), expectLongPress ? 1 : 0); timeHeldSpy.wait(); // the longer we hold it, the more this will occur qDebug() << "held" << tapHandler->timeHeld() << "secs; timeHeld updated" << timeHeldSpy.size() << "times"; - QVERIFY(timeHeldSpy.size() > 0); - QVERIFY(tapHandler->timeHeld() > 0.4); // Should be > 0.5 but slow CI and timer granularity can interfere + QCOMPARE_GT(timeHeldSpy.size(), 0); + if (expectLongPress) { + // Should be > longPressThreshold but slow CI and timer granularity can interfere + QCOMPARE_GT(tapHandler->timeHeld(), longPressThreshold - 0.1); + } else { + // Should be quite small, but event delivery is not instantaneous + QCOMPARE_LT(tapHandler->timeHeld(), 0.3); + } + + // If we have an offset, we need a move between press and release for realistic simulation + if (!releaseOffset.isNull()) + QQuickTest::pointerMove(device, &window, 1, p1 + releaseOffset); - // Release and verify that tapped was not emitted - QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1, 500); + // Release (optionally at an offset) and check whether tapped was emitted + QQuickTest::pointerRelease(device, &window, 1, p1 + releaseOffset); QTRY_VERIFY(!button->property("pressed").toBool()); - QCOMPARE(tappedSpy.size(), 0); + if (expectLongPress) + QCOMPARE_GT(button->property("timeHeldWhenLongPressed").toReal(), longPressThreshold - 0.1); + QCOMPARE(tapHandler->timeHeld(), -1); + QCOMPARE(tappedSpy.size(), expectTapped ? 1 : 0); + QCOMPARE(longPressedSpy.size(), expectLongPress ? 1 : 0); } void tst_TapHandler::buttonsMultiTouch() @@ -1116,6 +1234,61 @@ void tst_TapHandler::nestedDoubleTap() // QTBUG-102625 childGesturePolicy == QQuickTapHandler::GesturePolicy::DragThreshold ? 4 : 2); } +void tst_TapHandler::nestedAndSiblingPropagation_data() +{ + QTest::addColumn("device"); + QTest::addColumn("gesturePolicy"); + QTest::addColumn("expectPropagation"); + + const QPointingDevice *constTouchDevice = touchDevice; + + QTest::newRow("primary, DragThreshold") << QPointingDevice::primaryPointingDevice() + << QQuickTapHandler::GesturePolicy::DragThreshold << true; + QTest::newRow("primary, WithinBounds") << QPointingDevice::primaryPointingDevice() + << QQuickTapHandler::GesturePolicy::WithinBounds << false; + QTest::newRow("primary, ReleaseWithinBounds") << QPointingDevice::primaryPointingDevice() + << QQuickTapHandler::GesturePolicy::ReleaseWithinBounds << false; + QTest::newRow("primary, DragWithinBounds") << QPointingDevice::primaryPointingDevice() + << QQuickTapHandler::GesturePolicy::DragWithinBounds << false; + + QTest::newRow("touch, DragThreshold") << constTouchDevice + << QQuickTapHandler::GesturePolicy::DragThreshold << true; + QTest::newRow("touch, WithinBounds") << constTouchDevice + << QQuickTapHandler::GesturePolicy::WithinBounds << false; + QTest::newRow("touch, ReleaseWithinBounds") << constTouchDevice + << QQuickTapHandler::GesturePolicy::ReleaseWithinBounds << false; + QTest::newRow("touch, DragWithinBounds") << constTouchDevice + << QQuickTapHandler::GesturePolicy::DragWithinBounds << false; +} + +void tst_TapHandler::nestedAndSiblingPropagation() // QTBUG-117387 +{ + QFETCH(const QPointingDevice *, device); + QFETCH(QQuickTapHandler::GesturePolicy, gesturePolicy); + QFETCH(bool, expectPropagation); + + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl("nestedAndSibling.qml"))); + QQuickItem *root = window.rootObject(); + QQuickTapHandler *th1 = root->findChild("th1"); + QVERIFY(th1); + th1->setGesturePolicy(gesturePolicy); + QQuickTapHandler *th2 = root->findChild("th2"); + QVERIFY(th2); + th2->setGesturePolicy(gesturePolicy); + QQuickTapHandler *th3 = root->findChild("th3"); + QVERIFY(th3); + th3->setGesturePolicy(gesturePolicy); + + QPoint middle(180, 140); + QQuickTest::pointerPress(device, &window, 0, middle); + QVERIFY(th3->isPressed()); // it's on top + QCOMPARE(th2->isPressed(), expectPropagation); + QCOMPARE(th1->isPressed(), expectPropagation); + + QQuickTest::pointerRelease(device, &window, 0, middle); +} + QTEST_MAIN(tst_TapHandler) #include "tst_qquicktaphandler.moc" diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp index cb81ec8a0..92dc81050 100644 --- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp +++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp @@ -62,6 +62,7 @@ private slots: void noCaching(); void sourceChangesOnFrameChanged(); void currentFrame(); + void qtbug_120555(); }; void tst_qquickanimatedimage::cleanup() @@ -646,6 +647,36 @@ void tst_qquickanimatedimage::currentFrame() QCOMPARE(anim->property("frameChangeCount"), 2); } +void tst_qquickanimatedimage::qtbug_120555() +{ + TestHTTPServer server; + QVERIFY2(server.listen(), qPrintable(server.errorString())); + server.serveDirectory(dataDirectory()); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\nAnimatedImage {}", {}); + + QQuickAnimatedImage *anim = qobject_cast(component.create()); + QVERIFY(anim); + + anim->setSource(server.url("/stickman.gif")); + QTRY_COMPARE(anim->status(), QQuickImage::Loading); + + anim->setFillMode(QQuickImage::PreserveAspectFit); + QCOMPARE(anim->fillMode(), QQuickImage::PreserveAspectFit); + anim->setMipmap(true); + QCOMPARE(anim->mipmap(), true); + anim->setCache(false); + QCOMPARE(anim->cache(), false); + anim->setSourceSize(QSize(200, 200)); + QCOMPARE(anim->sourceSize(), QSize(200, 200)); + + QTRY_COMPARE(anim->status(), QQuickImage::Ready); + + delete anim; +} + QTEST_MAIN(tst_qquickanimatedimage) #include "tst_qquickanimatedimage.moc" diff --git a/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp b/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp index a0a1c6621..8a31536be 100644 --- a/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp +++ b/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp @@ -177,7 +177,8 @@ void tst_qquickdeliveryagent::passiveGrabberOrder() QPoint pos(75, 75); QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, pos); - QTest::qWait(1000); + QTRY_VERIFY(rootTap->isPressed()); + QTRY_VERIFY(subsceneTap->isPressed()); auto devPriv = QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice()); const auto &persistentPoint = devPriv->activePoints.values().first(); qCDebug(lcTests) << "passive grabbers" << persistentPoint.passiveGrabbers << "contexts" << persistentPoint.passiveGrabbersContext; @@ -187,7 +188,8 @@ void tst_qquickdeliveryagent::passiveGrabberOrder() QCOMPARE(persistentPoint.passiveGrabbers.last(), rootTap); QTest::mouseRelease(&view, Qt::LeftButton); - QTest::qWait(100); + QTRY_COMPARE(rootTap->isPressed(), false); + QTRY_COMPARE(subsceneTap->isPressed(), false); // QQuickWindow::event() has failsafe: clear all grabbers after release QCOMPARE(persistentPoint.passiveGrabbers.size(), 0); diff --git a/tests/auto/quick/qquickdragattached/tst_qquickdragattached.cpp b/tests/auto/quick/qquickdragattached/tst_qquickdragattached.cpp index 19e35703f..5ce72a747 100644 --- a/tests/auto/quick/qquickdragattached/tst_qquickdragattached.cpp +++ b/tests/auto/quick/qquickdragattached/tst_qquickdragattached.cpp @@ -53,9 +53,9 @@ void tst_QQuickDragAttached::setMimeData_data() QTest::addRow("text/uri-list, variant") << makeMap("text/uri-list", QVariantList{QVariant("file://foo")}) << QStringList{"text/uri-list"}; - QTest::addRow("mismatch image") - << makeMap("image/png", "not an image") - << QStringList{}; + QTest::addRow("application/json") + << makeMap("application/json", "{}") + << QStringList{"application/json"}; QTest::addRow("missing charset") << makeMap("text/plain;charset=", QString("foo")) << QStringList{}; @@ -116,7 +116,11 @@ void tst_QQuickDragAttached::startDrag() std::unique_ptr data(d->createMimeData()); QVERIFY(data); + auto debugHelper = qScopeGuard([&data]{ + qWarning() << data->formats(); + }); QCOMPARE(data->formats(), formats); + debugHelper.dismiss(); #else QSKIP("This test relies on private APIs that are only exported in developer-builds"); #endif diff --git a/tests/auto/quick/qquickimage/data/statusChanged.qml b/tests/auto/quick/qquickimage/data/statusChanged.qml new file mode 100644 index 000000000..ce4b4c4be --- /dev/null +++ b/tests/auto/quick/qquickimage/data/statusChanged.qml @@ -0,0 +1,25 @@ +import QtQuick + +Image { + id: root + property var changeSignals: [] + property var statusChanges: [] + property size statusChangedFirstImplicitSize: Qt.size(-1,-1) + + source: "heart.png" + + onFrameCountChanged: root.changeSignals.push("frameCount") + onCurrentFrameChanged: root.changeSignals.push("currentFrame") + onSourceSizeChanged: root.changeSignals.push("sourceSize") + onImplicitWidthChanged: root.changeSignals.push("implicitWidth") + onImplicitHeightChanged: root.changeSignals.push("implicitHeight") + onPaintedWidthChanged: root.changeSignals.push("paintedWidth") + onPaintedHeightChanged: root.changeSignals.push("paintedHeight") + onProgressChanged: root.changeSignals.push("progress") + onStatusChanged: (status) => { + root.changeSignals.push("status") + root.statusChanges.push(status) + if (root.statusChangedFirstImplicitSize.width < 0) + root.statusChangedFirstImplicitSize = Qt.size(root.implicitWidth, root.implicitHeight) + } +} diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp index 343bde5f5..e3a9554f6 100644 --- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp +++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp @@ -24,10 +24,13 @@ #include #include +#include #include // #define DEBUG_WRITE_OUTPUT +Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests") + using namespace QQuickVisualTestUtils; Q_DECLARE_METATYPE(QQuickImageBase::Status) @@ -68,6 +71,7 @@ private slots: void sourceClipRect_data(); void sourceClipRect(); void progressAndStatusChanges(); + void progressAndChangeSignalOrder(); void sourceSizeChanges(); void correctStatus(); void highdpi(); @@ -978,6 +982,28 @@ void tst_qquickimage::progressAndStatusChanges() delete obj; } +void tst_qquickimage::progressAndChangeSignalOrder() +{ + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl("statusChanged.qml"))); + QQuickImage *image = qmlobject_cast(window.rootObject()); + QVERIFY(image); + + QTRY_COMPARE(image->status(), QQuickImageBase::Ready); + // QTBUG-120205: implicitSize should be correct when status changes to Ready + QCOMPARE(image->property("statusChangedFirstImplicitSize").toSize(), QSize(300, 300)); + QCOMPARE(image->property("statusChanges").toList().size(), 1); // just Ready + const QStringList signalOrder = image->property("changeSignals").toStringList(); + const QStringList expectedOrder = {"progress", "paintedHeight", "paintedWidth", + "implicitWidth", "implicitHeight", + "paintedHeight", "paintedWidth", + "status", "sourceSize", "frameCount"}; + qCDebug(lcTests) << "signal order" << signalOrder; + // exact order may not be critical, and repeated signals may be silly; + // but this way we'll find out when it changes + QCOMPARE(signalOrder, expectedOrder); +} + class TestQImageProvider : public QQuickImageProvider { public: diff --git a/tests/auto/quick/qquicklistview2/data/changingOrientationWithListModel.qml b/tests/auto/quick/qquicklistview2/data/changingOrientationWithListModel.qml new file mode 100644 index 000000000..366b20b02 --- /dev/null +++ b/tests/auto/quick/qquicklistview2/data/changingOrientationWithListModel.qml @@ -0,0 +1,47 @@ +import QtQuick + +ListView { + id: root + + function allDelegates(valueSelector) { + let sum = 0; + for (let i = 0; i < root.count; i++) + sum += valueSelector(root.itemAtIndex(i)); + return sum; + } + + readonly property bool isXReset: allDelegates(function(item) { return item?.x ?? 0; }) === 0 + readonly property bool isYReset: allDelegates(function(item) { return item?.y ?? 0; }) === 0 + + width: 500 + height: 500 + delegate: Rectangle { + width: root.width + height: root.height + color: c + } + model: ListModel { + ListElement { + c: "red" + } + ListElement { + c: "green" + } + ListElement { + c: "blue" + } + ListElement { + c: "cyan" + } + ListElement { + c: "magenta" + } + ListElement { + c: "teal" + } + } + clip: true + orientation: ListView.Vertical + snapMode: ListView.SnapOneItem + highlightRangeMode: ListView.StrictlyEnforceRange +} \ No newline at end of file diff --git a/tests/auto/quick/qquicklistview2/data/changingOrientationWithObjectModel.qml b/tests/auto/quick/qquicklistview2/data/changingOrientationWithObjectModel.qml new file mode 100644 index 000000000..1d165a496 --- /dev/null +++ b/tests/auto/quick/qquicklistview2/data/changingOrientationWithObjectModel.qml @@ -0,0 +1,54 @@ +import QtQuick + +ListView { + id: root + + readonly property bool isXReset: red.x === 0 && green.x === 0 && blue.x === 0 && cyan.x === 0 && magenta.x === 0 && teal.x === 0 + + readonly property bool isYReset: red.y === 0 && green.y === 0 && blue.y === 0 && cyan.y === 0 && magenta.y === 0 && teal.y === 0 + + width: 500 + height: 500 + model: ObjectModel { + Rectangle { + id: red + width: root.width + height: root.height + color: "red" + } + Rectangle { + id: green + width: root.width + height: root.height + color: "green" + } + Rectangle { + id: blue + width: root.width + height: root.height + color: "blue" + } + Rectangle { + id: cyan + width: root.width + height: root.height + color: "cyan" + } + Rectangle { + id: magenta + width: root.width + height: root.height + color: "magenta" + } + Rectangle { + id: teal + width: root.width + height: root.height + color: "teal" + } + } + clip: true + orientation: ListView.Vertical + snapMode: ListView.SnapOneItem + highlightRangeMode: ListView.StrictlyEnforceRange +} \ No newline at end of file diff --git a/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp b/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp index b298f5f38..257b35707 100644 --- a/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp +++ b/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp @@ -60,6 +60,9 @@ private slots: void fetchMore_data(); void fetchMore(); + void changingOrientationResetsPreviousAxisValues_data(); + void changingOrientationResetsPreviousAxisValues(); + private: void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to); QScopedPointer touchDevice = QScopedPointer(QTest::createTouchDevice()); @@ -1116,6 +1119,40 @@ void tst_QQuickListView2::fetchMore() // QTBUG-95107 QCOMPARE_GE(model.m_lines, listView->count()); // fetchMore() was called } } + +void tst_QQuickListView2::changingOrientationResetsPreviousAxisValues_data() +{ + QTest::addColumn("sourceFile"); + QTest::newRow("ObjectModel") << QByteArray("changingOrientationWithObjectModel.qml"); + QTest::newRow("ListModel") << QByteArray("changingOrientationWithListModel.qml"); +} + +void tst_QQuickListView2::changingOrientationResetsPreviousAxisValues() // QTBUG-115696 +{ + QFETCH(QByteArray, sourceFile); + + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl(QString::fromLatin1(sourceFile)))); + auto *listView = qobject_cast(window.rootObject()); + QVERIFY(listView); + + // Starts of with vertical orientation. X should be 0 for all delegates, but not Y. + QVERIFY(listView->property("isXReset").toBool()); + QVERIFY(!listView->property("isYReset").toBool()); + + listView->setOrientation(QQuickListView::Orientation::Horizontal); + + // Y should be 0 for all delegates, but not X. + QVERIFY(!listView->property("isXReset").toBool()); + QVERIFY(listView->property("isYReset").toBool()); + + listView->setOrientation(QQuickListView::Orientation::Vertical); + + // X should be 0 for all delegates, but not Y. + QVERIFY(listView->property("isXReset").toBool()); + QVERIFY(!listView->property("isYReset").toBool()); +} + QTEST_MAIN(tst_QQuickListView2) #include "tst_qquicklistview2.moc" diff --git a/tests/auto/quick/qquickmousearea/data/cursorUpdating.qml b/tests/auto/quick/qquickmousearea/data/cursorUpdating.qml new file mode 100644 index 000000000..2d06543c7 --- /dev/null +++ b/tests/auto/quick/qquickmousearea/data/cursorUpdating.qml @@ -0,0 +1,71 @@ +import QtQuick + +Item { + width: 600 + height: 600 + + ListModel { + id: cursorsModel + ListElement { cursorShape: Qt.ArrowCursor; text: "Arrow" } + ListElement { cursorShape: Qt.UpArrowCursor; text: "UpArrow" } + ListElement { cursorShape: Qt.CrossCursor; text: "Cross" } + ListElement { cursorShape: Qt.WaitCursor; text: "Wait" } + ListElement { cursorShape: Qt.IBeamCursor; text: "IBeam" } + ListElement { cursorShape: Qt.SizeVerCursor; text: "SizeVer" } + ListElement { cursorShape: Qt.SizeHorCursor; text: "SizeHor" } + ListElement { cursorShape: Qt.SizeBDiagCursor; text: "SizeBDiag" } + ListElement { cursorShape: Qt.SizeFDiagCursor; text: "SizeFDiag" } + ListElement { cursorShape: Qt.SizeAllCursor; text: "SizeAll" } + ListElement { cursorShape: Qt.BlankCursor; text: "Blank" } + ListElement { cursorShape: Qt.SplitVCursor; text: "SplitV" } + ListElement { cursorShape: Qt.SplitHCursor; text: "SplitH" } + ListElement { cursorShape: Qt.PointingHandCursor; text: "PointingHand" } + ListElement { cursorShape: Qt.ForbiddenCursor; text: "Forbidden" } + ListElement { cursorShape: Qt.WhatsThisCursor; text: "WhatsThis" } + ListElement { cursorShape: Qt.BusyCursor; text: "Busy" } + ListElement { cursorShape: Qt.OpenHandCursor; text: "OpenHand" } + ListElement { cursorShape: Qt.ClosedHandCursor; text: "ClosedHand" } + ListElement { cursorShape: Qt.DragCopyCursor; text: "DragCopy" } + ListElement { cursorShape: Qt.DragMoveCursor; text: "DragMove" } + ListElement { cursorShape: Qt.DragLinkCursor; text: "DragLink" } + } + + Flickable { + anchors.fill: parent + contentHeight: flow.height + Flow { + id: flow + width: parent.width + Repeater { + model: cursorsModel + Rectangle { + id: root + color: "white" + border.width: 5 + border.color: "black" + + width: 200 + height: 200 + + Text { + id: textItem + anchors.fill: parent + anchors.margins: parent.width * 0.1 + text: model.text + fontSizeMode: Text.Fit + minimumPixelSize: 10; font.pixelSize: height + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: model.cursorShape + } + } + } + } + } +} diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index ec2b9695d..8d4c76b24 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -23,6 +23,11 @@ Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests") +static bool isPlatformWayland() +{ + return !QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive); +} + class CircleMask : public QObject { Q_OBJECT @@ -121,6 +126,7 @@ private slots: void changeAxis(); #if QT_CONFIG(cursor) void cursorShape(); + void cursorUpdating(); #endif void moveAndReleaseWithoutPress(); void nestedStopAtBounds(); @@ -1901,6 +1907,38 @@ void tst_QQuickMouseArea::cursorShape() QCOMPARE(mouseArea->cursor().shape(), Qt::WaitCursor); QCOMPARE(spy.size(), 2); } + +void tst_QQuickMouseArea::cursorUpdating() +{ + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl("cursorUpdating.qml"))); + QQuickItem *root = window.rootObject(); + QVERIFY(root); + QQuickFlickable *flickable = root->findChild(); + QVERIFY(flickable); + QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(root); + QVERIFY(rootPrivate->subtreeCursorEnabled); + + QTest::mouseMove(&window, QPoint(40, 40)); + QCOMPARE(window.cursor().shape(), Qt::ArrowCursor); + + QTest::mouseMove(&window, QPoint(240, 40)); + QCOMPARE(window.cursor().shape(), Qt::UpArrowCursor); + + if (isPlatformWayland()) + QSKIP("Wayland: QCursor::setPos() doesn't work."); + + // QTBUG-53987: with the cursor physically hovering, use wheel to + // position a different item that requests a different cursor + const QPoint p(240, 40); + const QPoint pg = window.mapToGlobal(p); + QCursor::setPos(pg); + QWheelEvent wheelEvent(p, pg, QPoint(60, -400), QPoint(0, -600), + Qt::NoButton, Qt::ControlModifier, Qt::NoScrollPhase, false); + QGuiApplication::sendEvent(&window, &wheelEvent); + QTRY_VERIFY(flickable->contentY() > 300); + QCOMPARE(window.cursor().shape(), Qt::IBeamCursor); +} #endif void tst_QQuickMouseArea::moveAndReleaseWithoutPress() diff --git a/tests/auto/quick/qquickpathview/data/mousePressAfterFlick.qml b/tests/auto/quick/qquickpathview/data/mousePressAfterFlick.qml new file mode 100644 index 000000000..a30234127 --- /dev/null +++ b/tests/auto/quick/qquickpathview/data/mousePressAfterFlick.qml @@ -0,0 +1,61 @@ +import QtQuick + +Item { + id: root + width: 360 + height: 900 + + MouseArea { + id: rootMouseArea + objectName: "rootMouseArea" + anchors.fill: parent + } + + PathView { + id: pathView + objectName: "pathView" + anchors.centerIn: parent + width: 150 + height: parent.height + dragMargin: Number.POSITIVE_INFINITY + + preferredHighlightBegin: 0.5 + preferredHighlightEnd: 0.5 + pathItemCount: 9 + + Item { + anchors.fill: parent + } + + model: 10 + + delegate: Rectangle { + id: delegate + width: parent.width + height: 120 + color: "red" + Text { + anchors.fill: parent + horizontalAlignment: Qt.AlignHCenter + text: "Path element " + modelData + } + } + + path: Path { + id: path + property int width: pathView.width + startX: path.width / 2 + startY: 0 + + PathCurve { + x: path.width / 2 + relativeY: 32 + } + PathCurve { + x: path.width / 2 + relativeY: pathView.height - 32 + } + } + } +} + diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp index 98085002e..68daaafa7 100644 --- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp +++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -130,6 +131,7 @@ private slots: void requiredPropertiesInDelegate(); void requiredPropertiesInDelegatePreventUnrelated(); void touchMove(); + void mousePressAfterFlick(); private: QScopedPointer touchDevice = QScopedPointer(QTest::createTouchDevice()); @@ -2851,6 +2853,47 @@ void tst_QQuickPathView::touchMove() } +void tst_QQuickPathView::mousePressAfterFlick() // QTBUG-115121 +{ + QScopedPointer window(createView()); + QQuickVisualTestUtils::moveMouseAway(window.data()); + window->setSource(testFileUrl("mousePressAfterFlick.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QQuickPathView *pathview = window->rootObject()->findChild("pathView"); + QVERIFY(pathview != nullptr); + + QQuickMouseArea *mouseArea = window->rootObject()->findChild("rootMouseArea"); + QVERIFY(mouseArea != nullptr); + + QSignalSpy flickingSpy(pathview, SIGNAL(flickingChanged())); + QSignalSpy flickStartedSpy(pathview, SIGNAL(flickStarted())); + QSignalSpy flickEndedSpy(pathview, SIGNAL(flickEnded())); + + QSignalSpy pressedSpy(mouseArea, &QQuickMouseArea::pressed); + + flickingSpy.clear(); + flickStartedSpy.clear(); + flickEndedSpy.clear(); + + // Dragging the child mouse area should animate the PathView (MA has no drag target) + QPoint from = QPoint((window->width() / 2), (window->height() * 3 / 4)); + QPoint to = QPoint((window->width() / 2), (window->height() / 4)); + flick(window.data(), from, to, 100); + QVERIFY(pathview->isMoving()); + QCOMPARE(flickingSpy.size(), 1); + QCOMPARE(flickStartedSpy.size(), 1); + QCOMPARE(flickEndedSpy.size(), 0); + + // Now while it's still moving, click it. + // The PathView should stop at a position + QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() / 4)); + QTRY_VERIFY(!pathview->isMoving()); + QCOMPARE(flickEndedSpy.size(), 1); + QCOMPARE(pressedSpy.size(), 0); +} + QTEST_MAIN(tst_QQuickPathView) #include "tst_qquickpathview.moc" diff --git a/tests/auto/quick/qquicktextedit/BLACKLIST b/tests/auto/quick/qquicktextedit/BLACKLIST index 270a4f786..d1097331a 100644 --- a/tests/auto/quick/qquicktextedit/BLACKLIST +++ b/tests/auto/quick/qquicktextedit/BLACKLIST @@ -1,10 +1,3 @@ -# QTBUG-109488 temporary fix -[largeTextObservesViewport] -linux -windows -android -darwin - [mouseSelection] opensuse-leap diff --git a/tests/auto/quick/qquicktextedit/data/resizeTextEditPolish.qml b/tests/auto/quick/qquicktextedit/data/resizeTextEditPolish.qml new file mode 100644 index 000000000..44819a0de --- /dev/null +++ b/tests/auto/quick/qquicktextedit/data/resizeTextEditPolish.qml @@ -0,0 +1,42 @@ +import QtQuick +import QtQuick.Controls + +Item { + width: 400 + height: 150 + + TextEdit { + id: textEdit + anchors { + top: parent.top + left: parent.left + right: parent.right + } + readOnly: true + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + text: "Lorem ipsum dolor sit amet, consectetur adipisicing" + states: [ + State { + name: "multi-line" + when: textEdit.lineCount > 1 + AnchorChanges { + target: textEdit + anchors.bottom: undefined + } + PropertyChanges { + target: textEdit + height: undefined + } + }, + State { + name: "single-line" + when: true + AnchorChanges { + target: textEdit + anchors.bottom: { return textEdit.parent.bottom } + } + } + ] + } +} diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index 9819494d3..99f95cc5a 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -211,6 +212,7 @@ private slots: void rtlAlignmentInColumnLayout_QTBUG_112858(); + void resizeTextEditPolish(); private: void simulateKeys(QWindow *window, const QList &keys); #if QT_CONFIG(shortcut) @@ -3766,16 +3768,16 @@ void tst_qquicktextedit::largeTextObservesViewport_data() // by default, the root item acts as the viewport: // QQuickTextEdit doesn't populate lines of text beyond the bottom of the window // cursor position 1000 is on line 121 - QTest::newRow("default plain text") << text << QQuickTextEdit::PlainText << false << 1000 << 0 - << 1 << 118 << 142 << 2400 << 3000; + QTest::newRow("default plain text") << text << QQuickTextEdit::PlainText << false << 1000 << 2 + << 3 << 118 << 144 << 2150 << 3000; // make the rectangle into a viewport item, and move the text upwards: // QQuickTextEdit doesn't populate lines of text beyond the bottom of the viewport rectangle QTest::newRow("clipped plain text") << text << QQuickTextEdit::PlainText << true << 1000 << 0 - << 1 << 123 << 137 << 2550 << 3000; + << 3 << 123 << 137 << 2200 << 3000; // scroll backwards QTest::newRow("scroll backwards in plain text") << text << QQuickTextEdit::PlainText << true << 1000 << 600 - << 1 << 93 << 108 << 1475 << 2300; + << 3 << 91 << 108 << 1475 << 2300; { QStringList lines; @@ -3799,20 +3801,20 @@ void tst_qquicktextedit::largeTextObservesViewport_data() // by default, the root item acts as the viewport: // QQuickTextEdit doesn't populate blocks beyond the bottom of the window QTest::newRow("default styled text") << text << QQuickTextEdit::RichText << false << 1000 << 0 - << 1 << 124 << 139 << 3900 << 4500; + << 3 << 122 << 139 << 3600 << 4500; // make the rectangle into a viewport item, and move the text upwards: // QQuickTextEdit doesn't populate blocks that don't intersect the viewport rectangle QTest::newRow("clipped styled text") << text << QQuickTextEdit::RichText << true << 1000 << 0 - << 1 << 127 << 136 << 4000 << 4360; + << 3 << 127 << 136 << 3700 << 4360; // get the "chapter 2" heading into the viewport QTest::newRow("heading visible") << text << QQuickTextEdit::RichText << true << 800 << 0 - << 1 << 105 << 113 << 3300 << 3600; + << 3 << 105 << 113 << 3050 << 3600; // get the "chapter 2" heading into the viewport, and then scroll backwards QTest::newRow("scroll backwards") << text << QQuickTextEdit::RichText << true << 800 << 20 - << 1 << 104 << 113 << 3200 << 3600; + << 3 << 104 << 113 << 3000 << 3600; // get the "chapter 2" heading into the viewport, and then scroll forwards QTest::newRow("scroll forwards") << text << QQuickTextEdit::RichText << true << 800 << -50 - << 1 << 106 << 115 << 3300 << 3670; + << 3 << 106 << 115 << 3000 << 3670; } void tst_qquicktextedit::largeTextObservesViewport() @@ -6591,6 +6593,35 @@ void tst_qquicktextedit::rtlAlignmentInColumnLayout_QTBUG_112858() } } +void tst_qquicktextedit::resizeTextEditPolish() +{ + QQuickView window(testFileUrl("resizeTextEditPolish.qml")); + QVERIFY(window.rootObject() != nullptr); + + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + + auto *edit = window.rootObject()->findChild(); + QVERIFY(edit != nullptr); + QCOMPARE(edit->lineCount(), 1); + + QSignalSpy spy(edit, SIGNAL(lineCountChanged())); + + // Resize item and check for item polished + auto *item = edit->parentItem(); + item->setWidth(item->width() - (item->width() / 2)); + + QVERIFY(QQuickTest::qIsPolishScheduled(edit)); + QVERIFY(QQuickTest::qWaitForPolish(edit)); + + QTRY_COMPARE(spy.size(), 1); + QVERIFY(edit->lineCount() > 1); + QCOMPARE(edit->state(), QString("multi-line")); + auto *editPriv = QQuickTextEditPrivate::get(edit); + QCOMPARE(editPriv->xoff, 0); + QCOMPARE(editPriv->yoff, 0); +} + QTEST_MAIN(tst_qquicktextedit) #include "tst_qquicktextedit.moc" diff --git a/tests/auto/quickcontrols/CMakeLists.txt b/tests/auto/quickcontrols/CMakeLists.txt index c45d6f38e..f4f2e6b2c 100644 --- a/tests/auto/quickcontrols/CMakeLists.txt +++ b/tests/auto/quickcontrols/CMakeLists.txt @@ -10,7 +10,9 @@ endif() add_subdirectory(cursor) add_subdirectory(customization) add_subdirectory(deferred) -add_subdirectory(designer) +if(QT_FEATURE_quick_designer) + add_subdirectory(designer) +endif() if(NOT ANDROID) # QTBUG-100258 add_subdirectory(focus) endif() diff --git a/tests/auto/quickcontrols/controls/data/tst_abstractbutton.qml b/tests/auto/quickcontrols/controls/data/tst_abstractbutton.qml index 0141d09e7..4560c93de 100644 --- a/tests/auto/quickcontrols/controls/data/tst_abstractbutton.qml +++ b/tests/auto/quickcontrols/controls/data/tst_abstractbutton.qml @@ -42,15 +42,17 @@ TestCase { SignalSpy { } } - function test_defaults() { + function init() { failOnWarning(/.?/) + } + function test_defaults() { let control = createTemporaryObject(defaultComponent, testCase) verify(control) } function test_text() { - var control = createTemporaryObject(button, testCase); + let control = createTemporaryObject(button, testCase); verify(control); compare(control.text, ""); @@ -61,7 +63,7 @@ TestCase { } function test_baseline() { - var control = createTemporaryObject(button, testCase, {padding: 6}) + let control = createTemporaryObject(button, testCase, {padding: 6}) verify(control) compare(control.baselineOffset, 0) control.contentItem = item.createObject(control, {baselineOffset: 12}) @@ -69,7 +71,7 @@ TestCase { } function test_implicitSize() { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) compare(control.implicitWidth, 0) @@ -96,22 +98,22 @@ TestCase { } function test_pressPoint(data) { - var control = createTemporaryObject(button, testCase, {width: 100, height: 40}) + let control = createTemporaryObject(button, testCase, {width: 100, height: 40}) verify(control) - var pressXChanges = 0 - var pressYChanges = 0 + let pressXChanges = 0 + let pressYChanges = 0 - var pressXSpy = signalSpy.createObject(control, {target: control, signalName: "pressXChanged"}) + let pressXSpy = signalSpy.createObject(control, {target: control, signalName: "pressXChanged"}) verify(pressXSpy.valid) - var pressYSpy = signalSpy.createObject(control, {target: control, signalName: "pressYChanged"}) + let pressYSpy = signalSpy.createObject(control, {target: control, signalName: "pressYChanged"}) verify(pressYSpy.valid) compare(control.pressX, 0) compare(control.pressY, 0) - var touch = data.touch ? touchEvent(control) : null + let touch = data.touch ? touchEvent(control) : null if (data.touch) touch.press(0, control, control.width / 2, control.height / 2).commit() @@ -196,10 +198,10 @@ TestCase { } function test_pressAndHold() { - var control = createTemporaryObject(button, testCase, {checkable: true}) + let control = createTemporaryObject(button, testCase, {checkable: true}) verify(control) - var pressAndHoldSpy = signalSpy.createObject(control, {target: control, signalName: "pressAndHold"}) + let pressAndHoldSpy = signalSpy.createObject(control, {target: control, signalName: "pressAndHold"}) verify(pressAndHoldSpy.valid) mousePress(control) @@ -228,10 +230,10 @@ TestCase { } function test_keyEvents(data) { - var container = createTemporaryObject(keyCatcher, testCase) + let container = createTemporaryObject(keyCatcher, testCase) verify(container) - var control = button.createObject(container) + let control = button.createObject(container) verify(control) control.forceActiveFocus() @@ -245,7 +247,7 @@ TestCase { } function test_icon() { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) compare(control.icon.name, "") compare(control.icon.source, "") @@ -253,7 +255,7 @@ TestCase { compare(control.icon.height, 0) compare(control.icon.color, "#00000000") - var iconSpy = signalSpy.createObject(control, { target: control, signalName: "iconChanged"} ) + let iconSpy = signalSpy.createObject(control, { target: control, signalName: "iconChanged"} ) verify(iconSpy.valid) control.icon.name = "test-name" @@ -322,14 +324,14 @@ TestCase { } function test_action(data) { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) control[data.property] = data.initButton - var act = action.createObject(control) + let act = action.createObject(control) act[data.property] = data.initAction - var spy = signalSpy.createObject(control, {target: control, signalName: data.property + "Changed"}) + let spy = signalSpy.createObject(control, {target: control, signalName: data.property + "Changed"}) verify(spy.valid) // assign action @@ -362,23 +364,23 @@ TestCase { } function test_actionIcon_data() { - var data = [] + let data = [] // Save duplicating the rows by reusing them with different properties of the same type. // This means that the first loop will test icon.name and the second one will test icon.source. - var stringPropertyValueSuffixes = [ + let stringPropertyValueSuffixes = [ { propertyName: "name", valueSuffix: "IconName" }, { propertyName: "source", valueSuffix: "IconSource" } ] - for (var i = 0; i < stringPropertyValueSuffixes.length; ++i) { - var propertyName = stringPropertyValueSuffixes[i].propertyName - var valueSuffix = stringPropertyValueSuffixes[i].valueSuffix + for (let i = 0; i < stringPropertyValueSuffixes.length; ++i) { + let propertyName = stringPropertyValueSuffixes[i].propertyName + let valueSuffix = stringPropertyValueSuffixes[i].valueSuffix - var buttonPropertyValue = "Button" + valueSuffix - var buttonPropertyValue2 = "Button" + valueSuffix + "2" - var actionPropertyValue = "Action" + valueSuffix - var actionPropertyValue2 = "Action" + valueSuffix + "2" + let buttonPropertyValue = "Button" + valueSuffix + let buttonPropertyValue2 = "Button" + valueSuffix + "2" + let actionPropertyValue = "Action" + valueSuffix + let actionPropertyValue2 = "Action" + valueSuffix + "2" data.push({ tag: "implicit " + propertyName, property: propertyName, initButton: undefined, initAction: actionPropertyValue, @@ -420,19 +422,19 @@ TestCase { resetExpected: buttonPropertyValue, resetChanged: false }) } - var intPropertyNames = [ + let intPropertyNames = [ "width", "height", ] - for (i = 0; i < intPropertyNames.length; ++i) { - propertyName = intPropertyNames[i] + for (let i = 0; i < intPropertyNames.length; ++i) { + let propertyName = intPropertyNames[i] - buttonPropertyValue = 20 - buttonPropertyValue2 = 21 - actionPropertyValue = 40 - actionPropertyValue2 = 41 - var defaultValue = 0 + let buttonPropertyValue = 20 + let buttonPropertyValue2 = 21 + let actionPropertyValue = 40 + let actionPropertyValue2 = 41 + let defaultValue = 0 data.push({ tag: "implicit " + propertyName, property: propertyName, initButton: undefined, initAction: actionPropertyValue, @@ -474,12 +476,12 @@ TestCase { resetExpected: buttonPropertyValue, resetChanged: false }) } - propertyName = "color" - buttonPropertyValue = "#aa0000" - buttonPropertyValue2 = "#ff0000" - actionPropertyValue = "#0000aa" - actionPropertyValue2 = "#0000ff" - defaultValue = "#00000000" + let propertyName = "color" + let buttonPropertyValue = "#aa0000" + let buttonPropertyValue2 = "#ff0000" + let actionPropertyValue = "#0000aa" + let actionPropertyValue2 = "#0000ff" + let defaultValue = "#00000000" data.push({ tag: "implicit " + propertyName, property: propertyName, initButton: undefined, initAction: actionPropertyValue, @@ -524,14 +526,14 @@ TestCase { } function test_actionIcon(data) { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) control.icon[data.property] = data.initButton - var act = action.createObject(control) + let act = action.createObject(control) act.icon[data.property] = data.initAction - var spy = signalSpy.createObject(control, {target: control, signalName: "iconChanged"}) + let spy = signalSpy.createObject(control, {target: control, signalName: "iconChanged"}) verify(spy.valid) // assign action @@ -580,7 +582,7 @@ TestCase { } function test_actionButton() { - var control = createTemporaryObject(actionButton, testCase) + let control = createTemporaryObject(actionButton, testCase) verify(control) // initial values @@ -590,7 +592,7 @@ TestCase { compare(control.enabled, false) compare(control.icon.name, "checked") - var textSpy = signalSpy.createObject(control, { target: control, signalName: "textChanged" }) + let textSpy = signalSpy.createObject(control, { target: control, signalName: "textChanged" }) verify(textSpy.valid) // changes via action @@ -631,7 +633,7 @@ TestCase { // setting an action while button has a particular property set // shouldn't cause a change in the button's effective property value - var secondAction = createTemporaryObject(action, testCase) + let secondAction = createTemporaryObject(action, testCase) verify(secondAction) secondAction.text = "SecondAction" control.action = secondAction @@ -639,7 +641,7 @@ TestCase { compare(textSpy.count, 2) // test setting an action whose properties aren't set - var thirdAction = createTemporaryObject(action, testCase) + let thirdAction = createTemporaryObject(action, testCase) verify(thirdAction) control.action = thirdAction compare(control.text, "Button") @@ -657,7 +659,7 @@ TestCase { } function test_checkable_button() { - var control = createTemporaryObject(checkableButton, testCase) + let control = createTemporaryObject(checkableButton, testCase) verify(control) control.checked = false control.forceActiveFocus() @@ -681,9 +683,9 @@ TestCase { compare(control.action.checked, false) compare(control.checked, false) - var checkedSpy = signalSpy.createObject(control, {target: control.action, signalName: "checkedChanged"}) - var toggledSpy = signalSpy.createObject(control, {target: control, signalName: "toggled"}) - var actionToggledSpy = signalSpy.createObject(control, {target: control.action, signalName: "toggled"}) + let checkedSpy = signalSpy.createObject(control, {target: control.action, signalName: "checkedChanged"}) + let toggledSpy = signalSpy.createObject(control, {target: control, signalName: "toggled"}) + let actionToggledSpy = signalSpy.createObject(control, {target: control.action, signalName: "toggled"}) verify(checkedSpy.valid) verify(toggledSpy.valid) @@ -723,16 +725,16 @@ TestCase { } function test_trigger(data) { - var control = createTemporaryObject(actionButton, testCase, {"action.enabled": data.action, "enabled": data.button}) + let control = createTemporaryObject(actionButton, testCase, {"action.enabled": data.action, "enabled": data.button}) verify(control) compare(control.enabled, data.button) compare(control.action.enabled, data.action) - var buttonSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"}) + let buttonSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"}) verify(buttonSpy.valid) - var actionSpy = signalSpy.createObject(control, {target: control.action, signalName: "triggered"}) + let actionSpy = signalSpy.createObject(control, {target: control.action, signalName: "triggered"}) verify(actionSpy.valid) if (data.click) @@ -748,13 +750,13 @@ TestCase { if (Qt.platform.os === "osx" || Qt.platform.os === "macos") skip("Mnemonics are not used on macOS") - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) control.text = "&Hello" compare(control.text, "&Hello") - var clickSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"}) + let clickSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"}) verify(clickSpy.valid) keyClick(Qt.Key_H, Qt.AltModifier) @@ -789,7 +791,7 @@ TestCase { control.text = undefined control.action = action.createObject(control, {text: "&Action"}) - var actionSpy = signalSpy.createObject(control, {target: control.action, signalName: "triggered"}) + let actionSpy = signalSpy.createObject(control, {target: control.action, signalName: "triggered"}) verify(actionSpy.valid) keyClick(Qt.Key_A, Qt.AltModifier) @@ -814,12 +816,12 @@ TestCase { } function test_actionGroup() { - var group = createTemporaryObject(actionGroup, testCase) + let group = createTemporaryObject(actionGroup, testCase) verify(group) - var button1 = createTemporaryObject(button, testCase, {action: group.actions[0], width: 10, height: 10}) - var button2 = createTemporaryObject(button, testCase, {action: group.actions[1], width: 10, height: 10, y: 10}) - var button3 = createTemporaryObject(button, testCase, {action: group.actions[2], width: 10, height: 10, y: 20}) + let button1 = createTemporaryObject(button, testCase, {action: group.actions[0], width: 10, height: 10}) + let button2 = createTemporaryObject(button, testCase, {action: group.actions[1], width: 10, height: 10, y: 10}) + let button3 = createTemporaryObject(button, testCase, {action: group.actions[2], width: 10, height: 10, y: 20}) verify(button1) compare(button1.checked, true) @@ -846,10 +848,10 @@ TestCase { } function test_clickedAfterLongPress() { - var control = createTemporaryObject(button, testCase, { text: "Hello" }) + let control = createTemporaryObject(button, testCase, { text: "Hello" }) verify(control) - var clickedSpy = signalSpy.createObject(control, { target: control, signalName: "clicked" }) + let clickedSpy = signalSpy.createObject(control, { target: control, signalName: "clicked" }) verify(clickedSpy.valid) mousePress(control) @@ -970,7 +972,7 @@ TestCase { } function test_rightMouseButton() { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) let pressedSpy = signalSpy.createObject(control, { target: control, signalName: "pressed" }) @@ -992,7 +994,8 @@ TestCase { // QTBUG-116289 - adding a HoverHandler into the button should not affect the handling of the right mouse button let hoverHandler = createTemporaryQmlObject("import QtQuick; HoverHandler {}", control) - control.data.push(hoverHandler) + verify(hoverHandler) + compare(hoverHandler.target, control) mousePress(control, control.width / 2, control.height / 2, Qt.RightButton) mouseRelease(control, control.width / 2, control.height / 2, Qt.RightButton) diff --git a/tests/auto/quickcontrols/controls/data/tst_action.qml b/tests/auto/quickcontrols/controls/data/tst_action.qml index 40aa4810f..6ed17a0d2 100644 --- a/tests/auto/quickcontrols/controls/data/tst_action.qml +++ b/tests/auto/quickcontrols/controls/data/tst_action.qml @@ -24,18 +24,20 @@ TestCase { SignalSpy { } } - function test_empty() { + function init() { failOnWarning(/.?/) + } + function test_empty() { let control = createTemporaryObject(component, testCase) verify(control) } function test_enabled() { - var action = createTemporaryObject(component, testCase) + let action = createTemporaryObject(component, testCase) verify(action) - var spy = createTemporaryObject(signalSpy, testCase, {target: action, signalName: "triggered"}) + let spy = createTemporaryObject(signalSpy, testCase, {target: action, signalName: "triggered"}) verify(spy.valid) action.trigger() @@ -89,7 +91,7 @@ TestCase { } function test_shared() { - var container = createTemporaryObject(buttonAndMenu, testCase) + let container = createTemporaryObject(buttonAndMenu, testCase) verify(container) keyClick(Qt.Key_B, Qt.ControlModifier) @@ -126,10 +128,10 @@ TestCase { } function test_repeater() { - var container = createTemporaryObject(actionAndRepeater, testCase) + let container = createTemporaryObject(actionAndRepeater, testCase) verify(container) - var spy = signalSpy.createObject(container, {target: container.action, signalName: "triggered"}) + let spy = signalSpy.createObject(container, {target: container.action, signalName: "triggered"}) verify(spy.valid) keyClick(Qt.Key_A, Qt.ControlModifier) @@ -160,7 +162,7 @@ TestCase { } function test_shortcutBinding() { - var container = createTemporaryObject(shortcutBinding, testCase); + let container = createTemporaryObject(shortcutBinding, testCase); verify(container) compare(container.indirect.nativeText, container.direct.nativeText); } @@ -188,7 +190,7 @@ TestCase { function test_shortcutCleanup() { { - var container = createTemporaryObject(shortcutCleanup, testCase); + let container = createTemporaryObject(shortcutCleanup, testCase); verify(container) container.action.shortcut = "Delete" container.menu.open() diff --git a/tests/auto/quickcontrols/controls/data/tst_actiongroup.qml b/tests/auto/quickcontrols/controls/data/tst_actiongroup.qml index 9d44223be..c535d9ca7 100644 --- a/tests/auto/quickcontrols/controls/data/tst_actiongroup.qml +++ b/tests/auto/quickcontrols/controls/data/tst_actiongroup.qml @@ -37,8 +37,12 @@ TestCase { SignalSpy { } } + function init() { + failOnWarning(/.?/) + } + function test_null() { - var group = createTemporaryObject(actionGroup, testCase) + let group = createTemporaryObject(actionGroup, testCase) verify(group) group.addAction(null) @@ -51,9 +55,7 @@ TestCase { } function test_defaults() { - failOnWarning(/.?/) - - var group = createTemporaryObject(actionGroup, testCase) + let group = createTemporaryObject(actionGroup, testCase) verify(group) compare(group.actions.length, 0) compare(group.checkedAction, null) @@ -61,16 +63,16 @@ TestCase { } function test_current() { - var group = createTemporaryObject(actionGroup, testCase) + let group = createTemporaryObject(actionGroup, testCase) verify(group) - var checkedActionSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "checkedActionChanged"}) + let checkedActionSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "checkedActionChanged"}) verify(checkedActionSpy.valid) verify(!group.checkedAction) - var action1 = createTemporaryObject(action, testCase, {checked: true}) - var action2 = createTemporaryObject(action, testCase, {checked: false}) - var action3 = createTemporaryObject(action, testCase, {checked: true, objectName: "3"}) + let action1 = createTemporaryObject(action, testCase, {checked: true}) + let action2 = createTemporaryObject(action, testCase, {checked: false}) + let action3 = createTemporaryObject(action, testCase, {checked: true, objectName: "3"}) // add checked group.addAction(action1) @@ -130,17 +132,17 @@ TestCase { } function test_actions() { - var group = createTemporaryObject(actionGroup, testCase) + let group = createTemporaryObject(actionGroup, testCase) verify(group) - var actionsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "actionsChanged"}) + let actionsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "actionsChanged"}) verify(actionsSpy.valid) compare(group.actions.length, 0) compare(group.checkedAction, null) - var action1 = createTemporaryObject(action, testCase, {checked: true}) - var action2 = createTemporaryObject(action, testCase, {checked: false}) + let action1 = createTemporaryObject(action, testCase, {checked: true}) + let action2 = createTemporaryObject(action, testCase, {checked: false}) group.actions = [action1, action2] compare(group.actions.length, 2) @@ -149,7 +151,7 @@ TestCase { compare(group.checkedAction, action1) compare(actionsSpy.count, 2) - var action3 = createTemporaryObject(action, testCase, {checked: true}) + let action3 = createTemporaryObject(action, testCase, {checked: true}) group.addAction(action3) compare(group.actions.length, 3) @@ -173,7 +175,7 @@ TestCase { } function test_declarative() { - var group = createTemporaryObject(declarativeGroup, testCase) + let group = createTemporaryObject(declarativeGroup, testCase) verify(group) compare(group.actions.length, 3) @@ -190,14 +192,14 @@ TestCase { } function test_triggered(data) { - var group = createTemporaryObject(actionGroup, testCase, {exclusive: data.exclusive}) + let group = createTemporaryObject(actionGroup, testCase, {exclusive: data.exclusive}) verify(group) - var triggeredSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "triggered"}) + let triggeredSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "triggered"}) verify(triggeredSpy.valid) - var action1 = createTemporaryObject(action, testCase) - var action2 = createTemporaryObject(action, testCase) + let action1 = createTemporaryObject(action, testCase) + let action2 = createTemporaryObject(action, testCase) group.addAction(action1) group.addAction(action2) @@ -222,7 +224,7 @@ TestCase { } function test_attached() { - var container = createTemporaryObject(attachedGroup, testCase) + let container = createTemporaryObject(attachedGroup, testCase) verify(container) verify(!container.group.checkedAction) @@ -247,13 +249,13 @@ TestCase { } function test_actionDestroyed() { - var group = createTemporaryObject(actionGroup, testCase) + let group = createTemporaryObject(actionGroup, testCase) verify(group) - var actionsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "actionsChanged"}) + let actionsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "actionsChanged"}) verify(actionsSpy.valid) - var action1 = createTemporaryObject(action, testCase, {objectName: "action1", checked: true}) + let action1 = createTemporaryObject(action, testCase, {objectName: "action1", checked: true}) group.addAction(action1) compare(group.actions.length, 1) @@ -269,15 +271,15 @@ TestCase { } function test_nonExclusive() { - var group = createTemporaryObject(nonExclusiveGroup, testCase) + let group = createTemporaryObject(nonExclusiveGroup, testCase) verify(group) - var action1 = createTemporaryObject(action, testCase, {checked: true}) + let action1 = createTemporaryObject(action, testCase, {checked: true}) group.addAction(action1) compare(action1.checked, true) compare(group.checkedAction, null) - var action2 = createTemporaryObject(action, testCase, {checked: true}) + let action2 = createTemporaryObject(action, testCase, {checked: true}) group.addAction(action2) compare(action1.checked, true) compare(action2.checked, true) @@ -305,18 +307,18 @@ TestCase { } function test_enabled() { - var group = createTemporaryObject(actionGroup, testCase) + let group = createTemporaryObject(actionGroup, testCase) verify(group) compare(group.enabled, true) - var action1 = createTemporaryObject(action, testCase) - var action2 = createTemporaryObject(action, testCase) + let action1 = createTemporaryObject(action, testCase) + let action2 = createTemporaryObject(action, testCase) compare(action1.enabled, true) compare(action2.enabled, true) - var action1Spy = createTemporaryObject(signalSpy, testCase, {target: action1, signalName: "enabledChanged"}) - var action2Spy = createTemporaryObject(signalSpy, testCase, {target: action2, signalName: "enabledChanged"}) + let action1Spy = createTemporaryObject(signalSpy, testCase, {target: action1, signalName: "enabledChanged"}) + let action2Spy = createTemporaryObject(signalSpy, testCase, {target: action2, signalName: "enabledChanged"}) verify(action1Spy.valid && action2Spy.valid) group.addAction(action1) @@ -392,7 +394,7 @@ TestCase { } function test_controls(data) { - var container = createTemporaryObject(data.component, testCase) + let container = createTemporaryObject(data.component, testCase) verify(container) verify(!container.group.checkedAction) diff --git a/tests/auto/quickcontrols/controls/data/tst_busyindicator.qml b/tests/auto/quickcontrols/controls/data/tst_busyindicator.qml index a50fd1bfa..69b1cc1d1 100644 --- a/tests/auto/quickcontrols/controls/data/tst_busyindicator.qml +++ b/tests/auto/quickcontrols/controls/data/tst_busyindicator.qml @@ -22,17 +22,26 @@ TestCase { id: mouseArea MouseArea { } } - - function test_defaults() { + + Component { + id: busyIndicatorInItem + Item { + BusyIndicator { } + } + } + + function init() { failOnWarning(/.?/) + } + function test_defaults() { let control = createTemporaryObject(busyIndicator, testCase) verify(control) compare(control.running, true) } function test_running() { - var control = createTemporaryObject(busyIndicator, testCase) + let control = createTemporaryObject(busyIndicator, testCase) verify(control) compare(control.running, true) @@ -42,10 +51,10 @@ TestCase { // QTBUG-61785 function test_mouseArea() { - var ma = createTemporaryObject(mouseArea, testCase, {width: testCase.width, height: testCase.height}) + let ma = createTemporaryObject(mouseArea, testCase, {width: testCase.width, height: testCase.height}) verify(ma) - var control = busyIndicator.createObject(ma, {width: testCase.width, height: testCase.height}) + let control = busyIndicator.createObject(ma, {width: testCase.width, height: testCase.height}) verify(control) mousePress(control) @@ -54,11 +63,23 @@ TestCase { mouseRelease(control) verify(!ma.pressed) - var touch = touchEvent(control) + let touch = touchEvent(control) touch.press(0, control).commit() verify(ma.pressed) touch.release(0, control).commit() verify(!ma.pressed) } + + // QTBUG-108808 + function test_visibility() { + let control = createTemporaryObject(busyIndicatorInItem, testCase, {visible: false}) + verify(control) + + let invisibleImage = grabImage(control) + control.visible = true + let visibleImage = grabImage(control) + + verify(!invisibleImage.equals(visibleImage)) + } } diff --git a/tests/auto/quickcontrols/controls/data/tst_button.qml b/tests/auto/quickcontrols/controls/data/tst_button.qml index 9ddfa0885..8720b55ef 100644 --- a/tests/auto/quickcontrols/controls/data/tst_button.qml +++ b/tests/auto/quickcontrols/controls/data/tst_button.qml @@ -30,9 +30,11 @@ TestCase { SignalSpy { } } - function test_defaults() { + function init() { failOnWarning(/.?/) + } + function test_defaults() { let control = createTemporaryObject(button, testCase) verify(control) compare(control.highlighted, false) @@ -40,7 +42,7 @@ TestCase { } function test_text() { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) compare(control.text, "") @@ -51,10 +53,10 @@ TestCase { } function test_mouse() { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) // click sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], @@ -120,11 +122,11 @@ TestCase { } function test_touch() { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) - var touch = touchEvent(control) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let touch = touchEvent(control) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) // click sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], @@ -163,15 +165,15 @@ TestCase { } function test_multiTouch() { - var control1 = createTemporaryObject(button, testCase) + let control1 = createTemporaryObject(button, testCase) verify(control1) - var pressedCount1 = 0 + let pressedCount1 = 0 - var pressedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "pressedChanged"}) + let pressedSpy1 = signalSpy.createObject(control1, {target: control1, signalName: "pressedChanged"}) verify(pressedSpy1.valid) - var touch = touchEvent(control1) + let touch = touchEvent(control1) touch.press(0, control1, 0, 0).commit().move(0, control1, control1.width - 1, control1.height - 1).commit() compare(pressedSpy1.count, ++pressedCount1) @@ -185,12 +187,12 @@ TestCase { compare(pressedSpy1.count, pressedCount1) compare(control1.pressed, true) - var control2 = createTemporaryObject(button, testCase, {y: control1.height}) + let control2 = createTemporaryObject(button, testCase, {y: control1.height}) verify(control2) - var pressedCount2 = 0 + let pressedCount2 = 0 - var pressedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "pressedChanged"}) + let pressedSpy2 = signalSpy.createObject(control2, {target: control2, signalName: "pressedChanged"}) verify(pressedSpy2.valid) // press the second button @@ -213,13 +215,13 @@ TestCase { } function test_keys() { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) control.forceActiveFocus() verify(control.activeFocus) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) // click sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], @@ -236,8 +238,8 @@ TestCase { sequenceSpy.expectedSequence = [] // Not testing Key_Enter and Key_Return because QGnomeTheme uses them for // pressing buttons and the CI uses the QGnomeTheme platform theme. - var keys = [Qt.Key_Escape, Qt.Key_Tab] - for (var i = 0; i < keys.length; ++i) { + let keys = [Qt.Key_Escape, Qt.Key_Tab] + for (let i = 0; i < keys.length; ++i) { sequenceSpy.reset() keyClick(keys[i]) verify(sequenceSpy.success) @@ -249,7 +251,7 @@ TestCase { } function test_autoRepeat() { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) compare(control.autoRepeat, false) @@ -259,11 +261,11 @@ TestCase { control.forceActiveFocus() verify(control.activeFocus) - var clickSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"}) + let clickSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"}) verify(clickSpy.valid) - var pressSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"}) + let pressSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"}) verify(pressSpy.valid) - var releaseSpy = signalSpy.createObject(control, {target: control, signalName: "released"}) + let releaseSpy = signalSpy.createObject(control, {target: control, signalName: "released"}) verify(releaseSpy.valid) // auto-repeat mouse click @@ -333,18 +335,18 @@ TestCase { } function test_baseline() { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset) } function test_checkable() { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) verify(control.hasOwnProperty("checkable")) verify(!control.checkable) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], ["downChanged", { "down": true }], @@ -386,7 +388,7 @@ TestCase { } function test_highlighted() { - var control = createTemporaryObject(button, testCase) + let control = createTemporaryObject(button, testCase) verify(control) verify(!control.highlighted) @@ -395,11 +397,11 @@ TestCase { } function test_spacing() { - var control = createTemporaryObject(button, testCase, { text: "Some long, long, long text" }) + let control = createTemporaryObject(button, testCase, { text: "Some long, long, long text" }) verify(control) verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth) - var textLabel = findChild(control.contentItem, "label") + let textLabel = findChild(control.contentItem, "label") verify(textLabel) // The implicitWidth of the IconLabel that all buttons use as their contentItem @@ -428,7 +430,7 @@ TestCase { } function test_display(data) { - var control = createTemporaryObject(button, testCase, { + let control = createTemporaryObject(button, testCase, { text: "Button", display: data.display, "icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png", @@ -437,8 +439,8 @@ TestCase { verify(control) compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png") - var iconImage = findChild(control.contentItem, "image") - var textLabel = findChild(control.contentItem, "label") + let iconImage = findChild(control.contentItem, "image") + let textLabel = findChild(control.contentItem, "label") switch (control.display) { case Button.IconOnly: diff --git a/tests/auto/quickcontrols/controls/data/tst_buttongroup.qml b/tests/auto/quickcontrols/controls/data/tst_buttongroup.qml index c4e20355e..ef9740523 100644 --- a/tests/auto/quickcontrols/controls/data/tst_buttongroup.qml +++ b/tests/auto/quickcontrols/controls/data/tst_buttongroup.qml @@ -28,14 +28,6 @@ TestCase { SignalSpy { } } - function test_null() { - var group = createTemporaryObject(buttonGroup, testCase) - verify(group) - - group.addButton(null) - group.removeButton(null) - } - Component { id: button Button { } @@ -46,10 +38,12 @@ TestCase { QtObject { } } - function test_defaults() { + function init() { failOnWarning(/.?/) + } - var group = createTemporaryObject(buttonGroup, testCase) + function test_defaults() { + let group = createTemporaryObject(buttonGroup, testCase) verify(group) compare(group.buttons.length, 0) compare(group.checkedButton, null) @@ -57,17 +51,25 @@ TestCase { compare(group.checkState, Qt.Unchecked) } + function test_null() { + let group = createTemporaryObject(buttonGroup, testCase) + verify(group) + + group.addButton(null) + group.removeButton(null) + } + function test_current() { - var group = createTemporaryObject(buttonGroup, testCase) + let group = createTemporaryObject(buttonGroup, testCase) verify(group) - var checkedButtonSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "checkedButtonChanged"}) + let checkedButtonSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "checkedButtonChanged"}) verify(checkedButtonSpy.valid) verify(!group.checkedButton) - var button1 = createTemporaryObject(button, testCase, {checked: true}) - var button2 = createTemporaryObject(button, testCase, {checked: false}) - var button3 = createTemporaryObject(button, testCase, {checked: true, objectName: "3"}) + let button1 = createTemporaryObject(button, testCase, {checked: true}) + let button2 = createTemporaryObject(button, testCase, {checked: false}) + let button3 = createTemporaryObject(button, testCase, {checked: true, objectName: "3"}) // add checked group.addButton(button1) @@ -127,17 +129,17 @@ TestCase { } function test_buttons() { - var group = createTemporaryObject(buttonGroup, testCase) + let group = createTemporaryObject(buttonGroup, testCase) verify(group) - var buttonsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "buttonsChanged"}) + let buttonsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "buttonsChanged"}) verify(buttonsSpy.valid) compare(group.buttons.length, 0) compare(group.checkedButton, null) - var button1 = createTemporaryObject(button, testCase, {checked: true}) - var button2 = createTemporaryObject(button, testCase, {checked: false}) + let button1 = createTemporaryObject(button, testCase, {checked: true}) + let button2 = createTemporaryObject(button, testCase, {checked: false}) group.buttons = [button1, button2] compare(group.buttons.length, 2) @@ -146,7 +148,7 @@ TestCase { compare(group.checkedButton, button1) compare(buttonsSpy.count, 2) - var button3 = createTemporaryObject(button, testCase, {checked: true}) + let button3 = createTemporaryObject(button, testCase, {checked: true}) group.addButton(button3) compare(group.buttons.length, 3) @@ -177,14 +179,14 @@ TestCase { } function test_clicked(data) { - var group = createTemporaryObject(buttonGroup, testCase, {exclusive: data.exclusive}) + let group = createTemporaryObject(buttonGroup, testCase, {exclusive: data.exclusive}) verify(group) - var clickedSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "clicked"}) + let clickedSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "clicked"}) verify(clickedSpy.valid) - var button1 = createTemporaryObject(button, testCase) - var button2 = createTemporaryObject(button, testCase) + let button1 = createTemporaryObject(button, testCase) + let button2 = createTemporaryObject(button, testCase) group.addButton(button1) group.addButton(button2) @@ -252,7 +254,7 @@ TestCase { } function test_controls(data) { - var container = createTemporaryObject(data.component, testCase) + let container = createTemporaryObject(data.component, testCase) verify(container) verify(!container.group.checkedButton) @@ -277,13 +279,13 @@ TestCase { } function test_buttonDestroyed() { - var group = createTemporaryObject(buttonGroup, testCase) + let group = createTemporaryObject(buttonGroup, testCase) verify(group) - var buttonsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "buttonsChanged"}) + let buttonsSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "buttonsChanged"}) verify(buttonsSpy.valid) - var button1 = createTemporaryObject(button, testCase, {objectName: "button1", checked: true}) + let button1 = createTemporaryObject(button, testCase, {objectName: "button1", checked: true}) group.addButton(button1) compare(group.buttons.length, 1) @@ -316,7 +318,7 @@ TestCase { } function test_repeater() { - var container = createTemporaryObject(repeater, testCase) + let container = createTemporaryObject(repeater, testCase) verify(container) verify(container.group.checkedButton) @@ -324,25 +326,25 @@ TestCase { } function test_nonExclusive() { - var group = createTemporaryObject(nonExclusiveGroup, testCase) + let group = createTemporaryObject(nonExclusiveGroup, testCase) verify(group) compare(group.checkState, Qt.Unchecked) - var button1 = createTemporaryObject(button, testCase, {checked: true}) + let button1 = createTemporaryObject(button, testCase, {checked: true}) group.addButton(button1) compare(button1.checked, true) compare(group.checkedButton, null) compare(group.checkState, Qt.Checked) - var button2 = createTemporaryObject(button, testCase, {checked: true}) + let button2 = createTemporaryObject(button, testCase, {checked: true}) group.addButton(button2) compare(button1.checked, true) compare(button2.checked, true) compare(group.checkedButton, null) compare(group.checkState, Qt.Checked) - var button3 = createTemporaryObject(button, testCase, {checked: false}) + let button3 = createTemporaryObject(button, testCase, {checked: false}) group.addButton(button3) compare(button1.checked, true) compare(button2.checked, true) @@ -401,7 +403,7 @@ TestCase { model: ListModel { id: listModel Component.onCompleted: { - for (var i = 0; i < 10; ++i) + for (let i = 0; i < 10; ++i) append({text: i}) } } @@ -410,7 +412,7 @@ TestCase { } function test_checkedButtonDestroyed() { - var column = createTemporaryObject(checkedButtonColumn, testCase) + let column = createTemporaryObject(checkedButtonColumn, testCase) verify(column) waitForRendering(column) @@ -452,7 +454,7 @@ TestCase { } function test_resetButtonGroup() { - var container = createTemporaryObject(buttonGroupComp, testCase) + let container = createTemporaryObject(buttonGroupComp, testCase) verify(container) // Check for initial buttons assigned to button group diff --git a/tests/auto/quickcontrols/controls/data/tst_calendarmodel.qml b/tests/auto/quickcontrols/controls/data/tst_calendarmodel.qml index a2f843678..5ccc10af0 100644 --- a/tests/auto/quickcontrols/controls/data/tst_calendarmodel.qml +++ b/tests/auto/quickcontrols/controls/data/tst_calendarmodel.qml @@ -29,6 +29,10 @@ TestCase { } } + function init() { + failOnWarning(/.?/) + } + function test_indices_data() { return [ // "from" and "to" must currently be in the same year. @@ -63,7 +67,7 @@ TestCase { } function test_invalid() { - var model = calendarModel.createObject(testCase) + let model = calendarModel.createObject(testCase) verify(model) compare(model.indexOf(-1, -1), -1) @@ -73,11 +77,11 @@ TestCase { } function test_instantiator() { - var inst = instantiator.createObject(testCase) + let inst = instantiator.createObject(testCase) verify(inst) compare(inst.count, 12) - for (var m = 0; m < inst.count; ++m) { + for (let m = 0; m < inst.count; ++m) { compare(inst.objectAt(m).month, m) compare(inst.objectAt(m).year, 2016) } diff --git a/tests/auto/quickcontrols/controls/data/tst_checkbox.qml b/tests/auto/quickcontrols/controls/data/tst_checkbox.qml index 5991ae900..7d8048412 100644 --- a/tests/auto/quickcontrols/controls/data/tst_checkbox.qml +++ b/tests/auto/quickcontrols/controls/data/tst_checkbox.qml @@ -25,9 +25,11 @@ TestCase { } } - function test_defaults() { + function init() { failOnWarning(/.?/) + } + function test_defaults() { let control = createTemporaryObject(checkBox, testCase) verify(control) compare(control.tristate, false) @@ -35,7 +37,7 @@ TestCase { } function test_text() { - var control = createTemporaryObject(checkBox, testCase) + let control = createTemporaryObject(checkBox, testCase) verify(control) compare(control.text, "") @@ -46,10 +48,10 @@ TestCase { } function test_checked() { - var control = createTemporaryObject(checkBox, testCase) + let control = createTemporaryObject(checkBox, testCase) verify(control) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) sequenceSpy.expectedSequence = [] compare(control.checked, false) @@ -72,10 +74,10 @@ TestCase { } function test_checkState() { - var control = createTemporaryObject(checkBox, testCase) + let control = createTemporaryObject(checkBox, testCase) verify(control) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) sequenceSpy.expectedSequence = [] compare(control.checked, false) @@ -98,10 +100,10 @@ TestCase { } function test_mouse() { - var control = createTemporaryObject(checkBox, testCase) + let control = createTemporaryObject(checkBox, testCase) verify(control) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) // check sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }], @@ -169,12 +171,12 @@ TestCase { } function test_touch() { - var control = createTemporaryObject(checkBox, testCase) + let control = createTemporaryObject(checkBox, testCase) verify(control) - var touch = touchEvent(control) + let touch = touchEvent(control) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) // check sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }], @@ -235,10 +237,10 @@ TestCase { } function test_keys() { - var control = createTemporaryObject(checkBox, testCase) + let control = createTemporaryObject(checkBox, testCase) verify(control) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) sequenceSpy.expectedSequence = [] control.forceActiveFocus() @@ -277,8 +279,8 @@ TestCase { sequenceSpy.expectedSequence = [] // Not testing Key_Enter and Key_Return because QGnomeTheme uses them for // pressing buttons and the CI uses the QGnomeTheme platform theme. - var keys = [Qt.Key_Escape, Qt.Key_Tab] - for (var i = 0; i < keys.length; ++i) { + let keys = [Qt.Key_Escape, Qt.Key_Tab] + for (let i = 0; i < keys.length; ++i) { sequenceSpy.reset() keyClick(keys[i]) compare(control.checked, false) @@ -295,7 +297,7 @@ TestCase { } function test_checked_binding() { - var container = createTemporaryObject(checkedBoundBoxes, testCase) + let container = createTemporaryObject(checkedBoundBoxes, testCase) verify(container) compare(container.cb1.checked, false) @@ -325,7 +327,7 @@ TestCase { } function test_checkState_binding() { - var container = createTemporaryObject(checkStateBoundBoxes, testCase) + let container = createTemporaryObject(checkStateBoundBoxes, testCase) verify(container) compare(container.cb1.checked, false) @@ -361,9 +363,9 @@ TestCase { } function test_tristate() { - var control = createTemporaryObject(checkBox, testCase, {tristate: true}) + let control = createTemporaryObject(checkBox, testCase, {tristate: true}) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) sequenceSpy.expectedSequence = [] control.forceActiveFocus() @@ -457,7 +459,7 @@ TestCase { } function test_baseline() { - var control = createTemporaryObject(checkBox, testCase) + let control = createTemporaryObject(checkBox, testCase) verify(control) compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset) } @@ -484,7 +486,7 @@ TestCase { } function test_nextCheckState(data) { - var control = createTemporaryObject(nextCheckStateBox, testCase) + let control = createTemporaryObject(nextCheckStateBox, testCase) verify(control) // mouse @@ -496,7 +498,7 @@ TestCase { // touch control.checkState = data.checkState compare(control.checkState, data.checkState) - var touch = touchEvent(control) + let touch = touchEvent(control) touch.press(0, control).commit().release(0, control).commit() compare(control.checkState, data.expectedState) diff --git a/tests/auto/quickcontrols/controls/data/tst_checkdelegate.qml b/tests/auto/quickcontrols/controls/data/tst_checkdelegate.qml index d3e0910e8..69bdb8348 100644 --- a/tests/auto/quickcontrols/controls/data/tst_checkdelegate.qml +++ b/tests/auto/quickcontrols/controls/data/tst_checkdelegate.qml @@ -20,16 +20,18 @@ TestCase { // TODO: data-fy tst_checkbox (rename to tst_check?) so we don't duplicate its tests here? - function test_defaults() { + function init() { failOnWarning(/.?/) + } - var control = createTemporaryObject(checkDelegate, testCase); + function test_defaults() { + let control = createTemporaryObject(checkDelegate, testCase); verify(control); verify(!control.checked); } function test_checked() { - var control = createTemporaryObject(checkDelegate, testCase); + let control = createTemporaryObject(checkDelegate, testCase); verify(control); mouseClick(control); @@ -40,17 +42,17 @@ TestCase { } function test_baseline() { - var control = createTemporaryObject(checkDelegate, testCase); + let control = createTemporaryObject(checkDelegate, testCase); verify(control); compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset); } function test_spacing() { - var control = createTemporaryObject(checkDelegate, testCase, { text: "Some long, long, long text" }) + let control = createTemporaryObject(checkDelegate, testCase, { text: "Some long, long, long text" }) verify(control) verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth) - var textLabel = findChild(control.contentItem, "label") + let textLabel = findChild(control.contentItem, "label") verify(textLabel) // The implicitWidth of the IconLabel that all buttons use as their contentItem should be @@ -77,7 +79,7 @@ TestCase { } function test_display(data) { - var control = createTemporaryObject(checkDelegate, testCase, { + let control = createTemporaryObject(checkDelegate, testCase, { text: "CheckDelegate", display: data.display, width: 400, @@ -87,11 +89,11 @@ TestCase { verify(control) compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png") - var iconImage = findChild(control.contentItem, "image") - var textLabel = findChild(control.contentItem, "label") + let iconImage = findChild(control.contentItem, "image") + let textLabel = findChild(control.contentItem, "label") - var availableWidth = control.availableWidth - control.indicator.width - control.spacing - var indicatorOffset = control.mirrored ? control.indicator.width + control.spacing : 0 + let availableWidth = control.availableWidth - control.indicator.width - control.spacing + let indicatorOffset = control.mirrored ? control.indicator.width + control.spacing : 0 switch (control.display) { case CheckDelegate.IconOnly: @@ -148,7 +150,7 @@ TestCase { } function test_nextCheckState(data) { - var control = createTemporaryObject(nextCheckStateDelegate, testCase) + let control = createTemporaryObject(nextCheckStateDelegate, testCase) verify(control) // mouse @@ -160,7 +162,7 @@ TestCase { // touch control.checkState = data.checkState compare(control.checkState, data.checkState) - var touch = touchEvent(control) + let touch = touchEvent(control) touch.press(0, control).commit().release(0, control).commit() compare(control.checkState, data.expectedState) diff --git a/tests/auto/quickcontrols/controls/data/tst_container.qml b/tests/auto/quickcontrols/controls/data/tst_container.qml index 998862574..552889c96 100644 --- a/tests/auto/quickcontrols/controls/data/tst_container.qml +++ b/tests/auto/quickcontrols/controls/data/tst_container.qml @@ -24,16 +24,18 @@ TestCase { Rectangle { } } - function test_defaults() { + function init() { failOnWarning(/.?/) + } + function test_defaults() { let control = createTemporaryObject(container, testCase) verify(control) compare(control.count, 0) } function test_implicitSize() { - var control = createTemporaryObject(container, testCase) + let control = createTemporaryObject(container, testCase) verify(control) compare(control.implicitWidth, 0) @@ -53,16 +55,16 @@ TestCase { } function test_currentIndex() { - var control1 = createTemporaryObject(container, testCase) + let control1 = createTemporaryObject(container, testCase) verify(control1) - var control2 = createTemporaryObject(container, testCase) + let control2 = createTemporaryObject(container, testCase) verify(control2) compare(control1.currentIndex, -1) compare(control2.currentIndex, -1) - for (var i = 0; i < 3; ++i) { + for (let i = 0; i < 3; ++i) { control1.addItem(rectangle.createObject(control1)) control2.addItem(rectangle.createObject(control2)) } @@ -130,7 +132,7 @@ TestCase { // don't crash (QTBUG-61310) function test_repeater(data) { - var control = createTemporaryObject(data.component, testCase) + let control = createTemporaryObject(data.component, testCase) verify(control) compare(control.itemAt(0).objectName, "0") @@ -140,12 +142,12 @@ TestCase { } function test_removeTakeItem() { - var control = createTemporaryObject(container, testCase) + let control = createTemporaryObject(container, testCase) verify(control) - var item1 = rectangle.createObject(control) - var item2 = rectangle.createObject(control) - var item3 = rectangle.createObject(control) + let item1 = rectangle.createObject(control) + let item2 = rectangle.createObject(control) + let item3 = rectangle.createObject(control) item1.Component.onDestruction.connect(function() { item1 = null }) item2.Component.onDestruction.connect(function() { item2 = null }) @@ -210,9 +212,9 @@ TestCase { } function test_contentItemDeletionOrder() { - var control1 = createTemporaryObject(contentItemDeletionOrder1, testCase) + let control1 = createTemporaryObject(contentItemDeletionOrder1, testCase) verify(control1) - var control2 = createTemporaryObject(contentItemDeletionOrder2, testCase) + let control2 = createTemporaryObject(contentItemDeletionOrder2, testCase) verify(control2) } @@ -251,9 +253,9 @@ TestCase { } function test_backgroundDeletionOrder() { - var control1 = createTemporaryObject(backgroundDeletionOrder1, testCase) + let control1 = createTemporaryObject(backgroundDeletionOrder1, testCase) verify(control1) - var control2 = createTemporaryObject(backgroundDeletionOrder2, testCase) + let control2 = createTemporaryObject(backgroundDeletionOrder2, testCase) verify(control2) } } diff --git a/tests/auto/quickcontrols/controls/data/tst_control.qml b/tests/auto/quickcontrols/controls/data/tst_control.qml index 074794342..37de77467 100644 --- a/tests/auto/quickcontrols/controls/data/tst_control.qml +++ b/tests/auto/quickcontrols/controls/data/tst_control.qml @@ -34,9 +34,11 @@ TestCase { SignalSpy { } } - function test_defaults() { + function init() { failOnWarning(/.?/) + } + function test_defaults() { let control = createTemporaryObject(component, testCase) verify(control) compare(control.background, null) @@ -44,37 +46,37 @@ TestCase { } function test_padding() { - var control = createTemporaryObject(component, testCase) + let control = createTemporaryObject(component, testCase) verify(control) - var paddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "paddingChanged"}) + let paddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "paddingChanged"}) verify(paddingSpy.valid) - var topPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topPaddingChanged"}) + let topPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topPaddingChanged"}) verify(topPaddingSpy.valid) - var leftPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftPaddingChanged"}) + let leftPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftPaddingChanged"}) verify(leftPaddingSpy.valid) - var rightPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightPaddingChanged"}) + let rightPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightPaddingChanged"}) verify(rightPaddingSpy.valid) - var bottomPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomPaddingChanged"}) + let bottomPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomPaddingChanged"}) verify(bottomPaddingSpy.valid) - var horizontalPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "horizontalPaddingChanged"}) + let horizontalPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "horizontalPaddingChanged"}) verify(horizontalPaddingSpy.valid) - var verticalPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "verticalPaddingChanged"}) + let verticalPaddingSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "verticalPaddingChanged"}) verify(verticalPaddingSpy.valid) - var paddingChanges = 0 - var topPaddingChanges = 0 - var leftPaddingChanges = 0 - var rightPaddingChanges = 0 - var bottomPaddingChanges = 0 - var horizontalPaddingChanges = 0 - var verticalPaddingChanges = 0 + let paddingChanges = 0 + let topPaddingChanges = 0 + let leftPaddingChanges = 0 + let rightPaddingChanges = 0 + let bottomPaddingChanges = 0 + let horizontalPaddingChanges = 0 + let verticalPaddingChanges = 0 compare(control.padding, 0) compare(control.topPadding, 0) @@ -315,17 +317,17 @@ TestCase { } function test_availableSize() { - var control = createTemporaryObject(component, testCase) + let control = createTemporaryObject(component, testCase) verify(control) - var availableWidthSpy = signalSpy.createObject(control, {target: control, signalName: "availableWidthChanged"}) + let availableWidthSpy = signalSpy.createObject(control, {target: control, signalName: "availableWidthChanged"}) verify(availableWidthSpy.valid) - var availableHeightSpy = signalSpy.createObject(control, {target: control, signalName: "availableHeightChanged"}) + let availableHeightSpy = signalSpy.createObject(control, {target: control, signalName: "availableHeightChanged"}) verify(availableHeightSpy.valid) - var availableWidthChanges = 0 - var availableHeightChanges = 0 + let availableWidthChanges = 0 + let availableHeightChanges = 0 control.width = 100 compare(control.availableWidth, 100) @@ -385,10 +387,10 @@ TestCase { } function test_mirrored() { - var control = createTemporaryObject(component, testCase) + let control = createTemporaryObject(component, testCase) verify(control) - var mirroredSpy = signalSpy.createObject(control, {target: control, signalName: "mirroredChanged"}) + let mirroredSpy = signalSpy.createObject(control, {target: control, signalName: "mirroredChanged"}) verify(mirroredSpy.valid) control.locale = Qt.locale("en_US") @@ -414,7 +416,7 @@ TestCase { } function test_background() { - var control = createTemporaryObject(component, testCase) + let control = createTemporaryObject(component, testCase) verify(control) control.background = component.createObject(control) @@ -502,7 +504,7 @@ TestCase { } function test_font() { - var control2 = createTemporaryObject(component2, testCase) + let control2 = createTemporaryObject(component2, testCase) verify(control2) verify(control2.item2_2) verify(control2.item2_3) @@ -645,7 +647,7 @@ TestCase { } function test_font_2() { - var control3 = createTemporaryObject(component3, testCase) + let control3 = createTemporaryObject(component3, testCase) verify(control3) verify(control3.item3_2) verify(control3.item3_3) @@ -760,14 +762,14 @@ TestCase { } function test_font_3() { - var control4 = createTemporaryObject(component4, testCase) + let control4 = createTemporaryObject(component4, testCase) verify(control4) verify(control4.item4_2) verify(control4.item4_3) verify(control4.item4_4) - var family = control4.font.family - var ps = control4.font.pixelSize + let family = control4.font.family + let ps = control4.font.pixelSize compare(control4.item4_2.font.family, control4.font.family) compare(control4.item4_3.font.family, control4.font.family) @@ -797,19 +799,19 @@ TestCase { } function test_font_explicit_attributes(data) { - var control = createTemporaryObject(component, testCase) + let control = createTemporaryObject(component, testCase) verify(control) - var child = component.createObject(control) + let child = component.createObject(control) verify(child) - var controlSpy = signalSpy.createObject(control, {target: control, signalName: "fontChanged"}) + let controlSpy = signalSpy.createObject(control, {target: control, signalName: "fontChanged"}) verify(controlSpy.valid) - var childSpy = signalSpy.createObject(child, {target: child, signalName: "fontChanged"}) + let childSpy = signalSpy.createObject(child, {target: child, signalName: "fontChanged"}) verify(childSpy.valid) - var defaultValue = control.font[data.tag] + let defaultValue = control.font[data.tag] child.font[data.tag] = defaultValue compare(child.font[data.tag], defaultValue) @@ -825,7 +827,7 @@ TestCase { } function test_locale() { - var control = createTemporaryObject(component, testCase) + let control = createTemporaryObject(component, testCase) verify(control) control.locale = Qt.locale("en_US") @@ -896,12 +898,12 @@ TestCase { } function test_locale_2() { - var control = createTemporaryObject(component5, testCase) + let control = createTemporaryObject(component5, testCase) verify(control) verify(control.item2_2) verify(control.item2_3) - var defaultLocale = Qt.locale() + let defaultLocale = Qt.locale() compare(control.locale.name, defaultLocale.name) compare(control.item2_2.locale.name, defaultLocale.name) @@ -989,14 +991,14 @@ TestCase { } function test_locale_3() { - var control = createTemporaryObject(component6, testCase) + let control = createTemporaryObject(component6, testCase) verify(control) verify(control.item6_2) verify(control.item6_3) verify(control.item6_4) verify(control.item6_5) - var defaultLocale = Qt.locale() + let defaultLocale = Qt.locale() compare(control.locale.name, defaultLocale.name) compare(control.item6_5.locale.name, defaultLocale.name) @@ -1028,7 +1030,7 @@ TestCase { } function test_hover(data) { - var control = createTemporaryObject(data.target, testCase, {width: 100, height: 100}) + let control = createTemporaryObject(data.target, testCase, {width: 100, height: 100}) verify(control) compare(control.hovered, false) @@ -1065,17 +1067,17 @@ TestCase { } function test_hoverEnabled() { - var control = createTemporaryObject(component, testCase) + let control = createTemporaryObject(component, testCase) compare(control.hoverEnabled, Qt.styleHints.useHoverEffects) - var child = component.createObject(control) - var grandChild = component.createObject(child) + let child = component.createObject(control) + let grandChild = component.createObject(child) - var childExplicitHoverEnabled = component.createObject(control, {hoverEnabled: true}) - var grandChildExplicitHoverDisabled = component.createObject(childExplicitHoverEnabled, {hoverEnabled: false}) + let childExplicitHoverEnabled = component.createObject(control, {hoverEnabled: true}) + let grandChildExplicitHoverDisabled = component.createObject(childExplicitHoverEnabled, {hoverEnabled: false}) - var childExplicitHoverDisabled = component.createObject(control, {hoverEnabled: false}) - var grandChildExplicitHoverEnabled = component.createObject(childExplicitHoverDisabled, {hoverEnabled: true}) + let childExplicitHoverDisabled = component.createObject(control, {hoverEnabled: false}) + let grandChildExplicitHoverEnabled = component.createObject(childExplicitHoverDisabled, {hoverEnabled: true}) control.hoverEnabled = false compare(control.hoverEnabled, false) @@ -1099,33 +1101,33 @@ TestCase { } function test_implicitSize() { - var control = createTemporaryObject(component, testCase) + let control = createTemporaryObject(component, testCase) verify(control) - var implicitWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitWidthChanged"}) + let implicitWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitWidthChanged"}) verify(implicitWidthSpy.valid) - var implicitHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitHeightChanged"}) + let implicitHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitHeightChanged"}) verify(implicitHeightSpy.valid) - var implicitContentWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitContentWidthChanged"}) + let implicitContentWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitContentWidthChanged"}) verify(implicitContentWidthSpy.valid) - var implicitContentHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitContentHeightChanged"}) + let implicitContentHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitContentHeightChanged"}) verify(implicitContentHeightSpy.valid) - var implicitBackgroundWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundWidthChanged"}) + let implicitBackgroundWidthSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundWidthChanged"}) verify(implicitBackgroundWidthSpy.valid) - var implicitBackgroundHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundHeightChanged"}) + let implicitBackgroundHeightSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "implicitBackgroundHeightChanged"}) verify(implicitBackgroundHeightSpy.valid) - var implicitWidthChanges = 0 - var implicitHeightChanges = 0 - var implicitContentWidthChanges = 0 - var implicitContentHeightChanges = 0 - var implicitBackgroundWidthChanges = 0 - var implicitBackgroundHeightChanges = 0 + let implicitWidthChanges = 0 + let implicitHeightChanges = 0 + let implicitContentWidthChanges = 0 + let implicitContentHeightChanges = 0 + let implicitBackgroundWidthChanges = 0 + let implicitBackgroundHeightChanges = 0 compare(control.implicitWidth, 0) compare(control.implicitHeight, 0) @@ -1194,12 +1196,12 @@ TestCase { } function test_baseline() { - var control = createTemporaryObject(component, testCase) + let control = createTemporaryObject(component, testCase) verify(control) compare(control.baselineOffset, 0) - var baselineSpy = signalSpy.createObject(control, {target: control, signalName: "baselineOffsetChanged"}) + let baselineSpy = signalSpy.createObject(control, {target: control, signalName: "baselineOffsetChanged"}) verify(baselineSpy.valid) control.contentItem = rectangle.createObject(control, {baselineOffset: 12}) @@ -1232,25 +1234,25 @@ TestCase { } function test_inset() { - var control = createTemporaryObject(component, testCase, {background: rectangle.createObject(control)}) + let control = createTemporaryObject(component, testCase, {background: rectangle.createObject(null)}) verify(control) - var topInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topInsetChanged"}) + let topInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "topInsetChanged"}) verify(topInsetSpy.valid) - var leftInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftInsetChanged"}) + let leftInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "leftInsetChanged"}) verify(leftInsetSpy.valid) - var rightInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightInsetChanged"}) + let rightInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rightInsetChanged"}) verify(rightInsetSpy.valid) - var bottomInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomInsetChanged"}) + let bottomInsetSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "bottomInsetChanged"}) verify(bottomInsetSpy.valid) - var topInsetChanges = 0 - var leftInsetChanges = 0 - var rightInsetChanges = 0 - var bottomInsetChanges = 0 + let topInsetChanges = 0 + let leftInsetChanges = 0 + let rightInsetChanges = 0 + let bottomInsetChanges = 0 compare(control.topInset, 0) compare(control.leftInset, 0) @@ -1412,9 +1414,9 @@ TestCase { } function test_contentItemDeletionOrder() { - var control1 = createTemporaryObject(contentItemDeletionOrder1, testCase) + let control1 = createTemporaryObject(contentItemDeletionOrder1, testCase) verify(control1) - var control2 = createTemporaryObject(contentItemDeletionOrder2, testCase) + let control2 = createTemporaryObject(contentItemDeletionOrder2, testCase) verify(control2) } @@ -1453,9 +1455,9 @@ TestCase { } function test_backgroundDeletionOrder() { - var control1 = createTemporaryObject(backgroundDeletionOrder1, testCase) + let control1 = createTemporaryObject(backgroundDeletionOrder1, testCase) verify(control1) - var control2 = createTemporaryObject(backgroundDeletionOrder2, testCase) + let control2 = createTemporaryObject(backgroundDeletionOrder2, testCase) verify(control2) } } diff --git a/tests/auto/quickcontrols/controls/data/tst_dayofweekrow.qml b/tests/auto/quickcontrols/controls/data/tst_dayofweekrow.qml index 67403e240..b5a9e1bec 100644 --- a/tests/auto/quickcontrols/controls/data/tst_dayofweekrow.qml +++ b/tests/auto/quickcontrols/controls/data/tst_dayofweekrow.qml @@ -18,15 +18,17 @@ TestCase { DayOfWeekRow { } } - function test_defaults() { + function init () { failOnWarning(/.?/) + } + function test_defaults() { let control = createTemporaryObject(component, testCase) verify(control) } function test_locale() { - var control = component.createObject(testCase) + let control = component.createObject(testCase) verify(control.contentItem.children[0]) @@ -43,7 +45,7 @@ TestCase { } function test_font() { - var control = component.createObject(testCase) + let control = component.createObject(testCase) verify(control.contentItem.children[0]) diff --git a/tests/auto/quickcontrols/controls/data/tst_delaybutton.qml b/tests/auto/quickcontrols/controls/data/tst_delaybutton.qml index e2abe389c..27145cd2a 100644 --- a/tests/auto/quickcontrols/controls/data/tst_delaybutton.qml +++ b/tests/auto/quickcontrols/controls/data/tst_delaybutton.qml @@ -38,18 +38,20 @@ TestCase { SignalSpy { } } - function test_defaults() { + function init() { failOnWarning(/.?/) + } + function test_defaults() { let control = createTemporaryObject(defaultComponent, testCase) verify(control) } function test_mouse() { - var control = createTemporaryObject(delayButton, testCase) + let control = createTemporaryObject(delayButton, testCase) verify(control) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) // click sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], @@ -145,12 +147,12 @@ TestCase { } function test_touch() { - var control = createTemporaryObject(delayButton, testCase) + let control = createTemporaryObject(delayButton, testCase) verify(control) - var touch = touchEvent(control) + let touch = touchEvent(control) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) // click sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], @@ -224,13 +226,13 @@ TestCase { } function test_keys() { - var control = createTemporaryObject(delayButton, testCase) + let control = createTemporaryObject(delayButton, testCase) verify(control) control.forceActiveFocus() verify(control.activeFocus) - var sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) + let sequenceSpy = signalSequenceSpy.createObject(control, {target: control}) // click sequenceSpy.expectedSequence = [["pressedChanged", { "pressed": true }], @@ -275,8 +277,8 @@ TestCase { sequenceSpy.expectedSequence = [] // Not testing Key_Enter and Key_Return because QGnomeTheme uses them for // pressing buttons and the CI uses the QGnomeTheme platform theme. - var keys = [Qt.Key_Escape, Qt.Key_Tab] - for (var i = 0; i < keys.length; ++i) { + let keys = [Qt.Key_Escape, Qt.Key_Tab] + for (let i = 0; i < keys.length; ++i) { sequenceSpy.reset() keyClick(keys[i]) verify(sequenceSpy.success) @@ -284,10 +286,10 @@ TestCase { } function test_progress() { - var control = createTemporaryObject(delayButton, testCase) + let control = createTemporaryObject(delayButton, testCase) verify(control) - var progressSpy = signalSpy.createObject(control, {target: control, signalName: "progressChanged"}) + let progressSpy = signalSpy.createObject(control, {target: control, signalName: "progressChanged"}) verify(progressSpy.valid) compare(control.progress, 0.0) @@ -297,7 +299,7 @@ TestCase { } function test_baseline() { - var control = createTemporaryObject(delayButton, testCase) + let control = createTemporaryObject(delayButton, testCase) verify(control) compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset) } diff --git a/tests/auto/quickcontrols/controls/data/tst_dial.qml b/tests/auto/quickcontrols/controls/data/tst_dial.qml index ccc6beefb..01d305b1b 100644 --- a/tests/auto/quickcontrols/controls/data/tst_dial.qml +++ b/tests/auto/quickcontrols/controls/data/tst_dial.qml @@ -27,10 +27,13 @@ TestCase { SignalSpy {} } - function test_instance() { + function init() { + // Fail on any warning that we don't expect. failOnWarning(/.?/) + } - var dial = createTemporaryObject(dialComponent, testCase); + function test_instance() { + let dial = createTemporaryObject(dialComponent, testCase); verify(dial); compare(dial.value, 0.0); compare(dial.from, 0.0); @@ -41,7 +44,7 @@ TestCase { } function test_value() { - var dial = createTemporaryObject(dialComponent, testCase); + let dial = createTemporaryObject(dialComponent, testCase); verify(dial); compare(dial.value, 0.0); @@ -59,7 +62,7 @@ TestCase { } function test_range() { - var dial = createTemporaryObject(dialComponent, testCase); + let dial = createTemporaryObject(dialComponent, testCase); verify(dial); dial.from = 0; @@ -94,7 +97,7 @@ TestCase { } function test_inverted() { - var dial = createTemporaryObject(dialComponent, testCase, { from: 1.0, to: -1.0 }); + let dial = createTemporaryObject(dialComponent, testCase, { from: 1.0, to: -1.0 }); verify(dial); compare(dial.from, 1.0); compare(dial.to, -1.0); @@ -120,7 +123,7 @@ TestCase { } function test_pressed() { - var dial = createTemporaryObject(dialComponent, testCase); + let dial = createTemporaryObject(dialComponent, testCase); verify(dial); pressSpy.target = dial; @@ -135,7 +138,7 @@ TestCase { verify(!dial.pressed); compare(pressSpy.count, 2); - var touch = touchEvent(dial); + let touch = touchEvent(dial); touch.press(0).commit(); verify(dial.pressed); compare(pressSpy.count, 3); @@ -160,7 +163,7 @@ TestCase { } function test_dragging(data) { - var dial = createTemporaryObject(dialComponent, testCase); + let dial = createTemporaryObject(dialComponent, testCase); verify(dial); dial.wrap = true; @@ -172,10 +175,10 @@ TestCase { valueSpy.target = dial; verify(valueSpy.valid); - var moveSpy = createTemporaryObject(signalSpy, testCase, {target: dial, signalName: "moved"}); + let moveSpy = createTemporaryObject(signalSpy, testCase, {target: dial, signalName: "moved"}); verify(moveSpy.valid); - var minimumExpectedValueCount = data.live ? 2 : 1; + let minimumExpectedValueCount = data.live ? 2 : 1; // drag to the left // we always add or subtract 1 to ensure we start the drag from the opposite side @@ -217,16 +220,16 @@ TestCase { } function test_nonWrapping() { - var dial = createTemporaryObject(dialComponent, testCase); + let dial = createTemporaryObject(dialComponent, testCase); verify(dial); compare(dial.wrap, false); dial.value = 0; // Ensure that dragging from bottom left to bottom right doesn't work. - var yPos = dial.height * 0.75; + let yPos = dial.height * 0.75; mousePress(dial, dial.width * 0.25, yPos, Qt.LeftButton); - var positionAtPress = dial.position; + let positionAtPress = dial.position; mouseMove(dial, dial.width * 0.5, yPos); verify(dial.position < positionAtPress); mouseMove(dial, dial.width * 0.75, yPos); @@ -258,15 +261,15 @@ TestCase { } function test_touch() { - var dial = createTemporaryObject(dialComponent, testCase); + let dial = createTemporaryObject(dialComponent, testCase); verify(dial); - var touch = touchEvent(dial); + let touch = touchEvent(dial); // Ensure that dragging from bottom left to bottom right doesn't work. - var yPos = dial.height * 0.75; + let yPos = dial.height * 0.75; touch.press(0, dial, dial.width * 0.25, yPos).commit(); - var positionAtPress = dial.position; + let positionAtPress = dial.position; touch.move(0, dial, dial.width * 0.5, yPos).commit(); compare(dial.position, positionAtPress); touch.move(0, dial, dial.width * 0.75, yPos).commit(); @@ -298,15 +301,15 @@ TestCase { } function test_multiTouch() { - var dial1 = createTemporaryObject(dialComponent, testCase); + let dial1 = createTemporaryObject(dialComponent, testCase); verify(dial1); - var touch = touchEvent(dial1); + let touch = touchEvent(dial1); touch.press(0, dial1).commit().move(0, dial1, dial1.width / 4, dial1.height / 4).commit(); compare(dial1.pressed, true); verify(dial1.position > 0.0); - var pos1Before = dial1.position; + let pos1Before = dial1.position; // second touch point on the same control is ignored touch.stationary(0).press(1, dial1, 0, 0).commit() @@ -315,7 +318,7 @@ TestCase { compare(dial1.pressed, true); compare(dial1.position, pos1Before); - var dial2 = createTemporaryObject(dialComponent, testCase, {y: dial1.height}); + let dial2 = createTemporaryObject(dialComponent, testCase, {y: dial1.height}); verify(dial2); // press the second dial @@ -324,7 +327,7 @@ TestCase { compare(dial2.position, 0.0); pos1Before = dial1.position; - var pos2Before = dial2.position; + let pos2Before = dial2.position; // move both dials touch.move(0, dial1).move(2, dial2, dial2.width / 4, dial2.height / 4).commit(); @@ -356,19 +359,19 @@ TestCase { } function test_keyboardNavigation() { - var dial = createTemporaryObject(dialComponent, testCase); + let dial = createTemporaryObject(dialComponent, testCase); verify(dial); - var focusScope = createTemporaryObject(focusTest, testCase); + let focusScope = createTemporaryObject(focusTest, testCase); verify(focusScope); - var moveCount = 0; + let moveCount = 0; // Tests that we've accepted events that we're interested in. parentEventSpy.target = focusScope; parentEventSpy.signalName = "receivedKeyPress"; - var moveSpy = createTemporaryObject(signalSpy, testCase, {target: dial, signalName: "moved"}); + let moveSpy = createTemporaryObject(signalSpy, testCase, {target: dial, signalName: "moved"}); verify(moveSpy.valid); dial.parent = focusScope; @@ -384,10 +387,10 @@ TestCase { compare(moveSpy.count, moveCount); compare(dial.value, 0); - var oldValue = 0.0; - var keyPairs = [[Qt.Key_Left, Qt.Key_Right], [Qt.Key_Down, Qt.Key_Up]]; - for (var keyPairIndex = 0; keyPairIndex < 2; ++keyPairIndex) { - for (var i = 1; i <= 10; ++i) { + let oldValue = 0.0; + let keyPairs = [[Qt.Key_Left, Qt.Key_Right], [Qt.Key_Down, Qt.Key_Up]]; + for (let keyPairIndex = 0; keyPairIndex < 2; ++keyPairIndex) { + for (let i = 1; i <= 10; ++i) { oldValue = dial.value; keyClick(keyPairs[keyPairIndex][1]); compare(parentEventSpy.count, 0); @@ -398,7 +401,7 @@ TestCase { compare(dial.value, dial.to); - for (i = 10; i > 0; --i) { + for (let i = 10; i > 0; --i) { oldValue = dial.value; keyClick(keyPairs[keyPairIndex][0]); compare(parentEventSpy.count, 0); @@ -450,7 +453,7 @@ TestCase { } function test_snapMode_mouse(data) { - var dial = createTemporaryObject(dialComponent, testCase, {live: false}); + let dial = createTemporaryObject(dialComponent, testCase, {live: false}); verify(dial); dial.snapMode = data.snapMode; @@ -458,7 +461,7 @@ TestCase { dial.to = data.to; dial.stepSize = 0.2; - var fuzz = 0.055; + let fuzz = 0.055; mousePress(dial, dial.width * 0.25, dial.height * 0.75); fuzzyCompare(dial.value, data.values[0], fuzz); @@ -478,7 +481,7 @@ TestCase { } function test_snapMode_touch(data) { - var dial = createTemporaryObject(dialComponent, testCase, {live: false}); + let dial = createTemporaryObject(dialComponent, testCase, {live: false}); verify(dial); dial.snapMode = data.snapMode; @@ -486,9 +489,9 @@ TestCase { dial.to = data.to; dial.stepSize = 0.2; - var fuzz = 0.05; + let fuzz = 0.05; - var touch = touchEvent(dial); + let touch = touchEvent(dial); touch.press(0, dial, dial.width * 0.25, dial.height * 0.75).commit() compare(dial.value, data.values[0]); compare(dial.position, data.positions[0]); @@ -504,13 +507,13 @@ TestCase { function test_wheel_data() { return [ - { tag: "horizontal", orientation: Qt.Horizontal, dx: 120, dy: 0 }, - { tag: "vertical", orientation: Qt.Vertical, dx: 0, dy: 120 } + { tag: "horizontal", dx: 120, dy: 0 }, + { tag: "vertical", dx: 0, dy: 120 } ] } function test_wheel(data) { - var control = createTemporaryObject(dialComponent, testCase, {wheelEnabled: true, orientation: data.orientation}) + let control = createTemporaryObject(dialComponent, testCase, {wheelEnabled: true}) verify(control) compare(control.value, 0.0) @@ -548,7 +551,7 @@ TestCase { } function test_nullHandle() { - var control = createTemporaryObject(dialComponent, testCase) + let control = createTemporaryObject(dialComponent, testCase) verify(control) control.handle = null @@ -564,7 +567,7 @@ TestCase { if (inputEventType === "mouseInput") { mouseMove(control, x, y); } else { - var touch = touchEvent(control); + let touch = touchEvent(control); touch.move(0, control, x, y).commit(); } } @@ -573,7 +576,7 @@ TestCase { if (inputEventType === "mouseInput") { mousePress(control, x, y); } else { - var touch = touchEvent(control); + let touch = touchEvent(control); touch.press(0, control, x, y).commit(); } } @@ -582,13 +585,13 @@ TestCase { if (inputEventType === "mouseInput") { mouseRelease(control, x, y); } else { - var touch = touchEvent(control); + let touch = touchEvent(control); touch.release(0, control, x, y).commit(); } } function test_horizontalAndVertical_data() { - var data = [ + let data = [ { eventType: "mouseInput", inputMode: Dial.Vertical, moveToX: 0.5, moveToY: 0.25, expectedPosition: 0.125 }, // Horizontal movement should have no effect on a vertical dial. { eventType: "mouseInput", inputMode: Dial.Vertical, moveToX: 2.0, moveToY: 0.25, expectedPosition: 0.125 }, @@ -614,15 +617,15 @@ TestCase { ]; // Do the same tests for touch by copying the mouse tests and adding them to the end of the array. - var mouseTestCount = data.length; - for (var i = mouseTestCount; i < mouseTestCount * 2; ++i) { + let mouseTestCount = data.length; + for (let i = mouseTestCount; i < mouseTestCount * 2; ++i) { // Shallow-copy the object. data[i] = JSON.parse(JSON.stringify(data[i - mouseTestCount])); data[i].eventType = "touchInput"; } - for (i = 0; i < data.length; ++i) { - var row = data[i]; + for (let i = 0; i < data.length; ++i) { + let row = data[i]; row.tag = "eventType=" + row.eventType + ", " + "inputMode=" + (row.inputMode === Dial.Vertical ? "Vertical" : "Horizontal") + ", " + "moveToX=" + row.moveToX + ", moveToY=" + row.moveToY + ", " @@ -633,7 +636,7 @@ TestCase { } function test_horizontalAndVertical(data) { - var control = createTemporaryObject(dialComponent, testCase, { inputMode: data.inputMode }); + let control = createTemporaryObject(dialComponent, testCase, { inputMode: data.inputMode }); verify(control); press(data.eventType, control); @@ -650,7 +653,7 @@ TestCase { } function test_integerStepping() { - var dial = createTemporaryObject(dialComponent, testCase) + let dial = createTemporaryObject(dialComponent, testCase) verify(dial) dial.from = 1 @@ -765,7 +768,7 @@ TestCase { compare(dial.startAngle, data.startAngle) compare(dial.endAngle, data.endAngle) - var wrappedSpy = signalSpy.createObject(dial, {target: dial, signalName: "wrapped"}) + let wrappedSpy = signalSpy.createObject(dial, {target: dial, signalName: "wrapped"}) verify(wrappedSpy.valid) for (let i = 0; i < data.x.length; i++) { @@ -785,13 +788,9 @@ TestCase { compare(clockwiseCount, data.wrapClockwise) compare(counterClockwiseCount, data.wrapCounterClockwise) - } function test_startEndAngleWarnings(data) { - // Fail on any warning that we don't expect. - failOnWarning(/.?/) - let dial = createTemporaryObject(dialComponent, testCase) verify(dial) diff --git a/tests/auto/quickcontrols/controls/data/tst_dialog.qml b/tests/auto/quickcontrols/controls/data/tst_dialog.qml index 180dbaf73..2c29fb366 100644 --- a/tests/auto/quickcontrols/controls/data/tst_dialog.qml +++ b/tests/auto/quickcontrols/controls/data/tst_dialog.qml @@ -39,13 +39,12 @@ TestCase { } function init() { + failOnWarning(/.?/) tryCompare(testCase.Window.window, "active", true) } function test_defaults() { - failOnWarning(/.?/) - - var control = createTemporaryObject(dialog, testCase) + let control = createTemporaryObject(dialog, testCase) verify(control) verify(control.header) verify(control.footer) @@ -54,9 +53,9 @@ TestCase { } function test_accept() { - var control = createTemporaryObject(dialog, testCase) + let control = createTemporaryObject(dialog, testCase) - var openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"}) + let openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"}) verify(openedSpy.valid) control.open() @@ -64,10 +63,10 @@ TestCase { compare(openedSpy.count, 1) verify(control.visible) - var acceptedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "accepted"}) + let acceptedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "accepted"}) verify(acceptedSpy.valid) - var closedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "closed"}) + let closedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "closed"}) verify(closedSpy.valid) control.accept() @@ -80,9 +79,9 @@ TestCase { } function test_reject() { - var control = createTemporaryObject(dialog, testCase) + let control = createTemporaryObject(dialog, testCase) - var openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"}) + let openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"}) verify(openedSpy.valid) control.open() @@ -90,10 +89,10 @@ TestCase { compare(openedSpy.count, 1) verify(control.visible) - var rejectedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rejected"}) + let rejectedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rejected"}) verify(rejectedSpy.valid) - var closedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "closed"}) + let closedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "closed"}) verify(closedSpy.valid) control.reject() @@ -168,46 +167,46 @@ TestCase { } function test_buttonBox(data) { - var control = createTemporaryObject(dialog, testCase) + let control = createTemporaryObject(dialog, testCase) if (data.custom) control.footer = buttonBox.createObject(testCase) control.standardButtons = Dialog.Ok | Dialog.Cancel - var box = control.footer + let box = control.footer verify(box) compare(box.standardButtons, Dialog.Ok | Dialog.Cancel) - var acceptedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "accepted"}) + let acceptedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "accepted"}) verify(acceptedSpy.valid) box.accepted() compare(acceptedSpy.count, 1) - var rejectedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rejected"}) + let rejectedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "rejected"}) verify(rejectedSpy.valid) box.rejected() compare(rejectedSpy.count, 1) } function test_qtbug71444() { - var control = createTemporaryObject(qtbug71444, testCase) + let control = createTemporaryObject(qtbug71444, testCase) verify(control) } function test_standardButtons() { - var control = createTemporaryObject(dialog, testCase) + let control = createTemporaryObject(dialog, testCase) control.standardButtons = Dialog.Ok - var box = control.footer ? control.footer : control.header + let box = control.footer ? control.footer : control.header verify(box) compare(box.count, 1) - var okButton = box.itemAt(0) + let okButton = box.itemAt(0) verify(okButton) compare(okButton.text.toUpperCase(), "OK") control.standardButtons = Dialog.Cancel compare(box.count, 1) - var cancelButton = control.footer.itemAt(0) + let cancelButton = control.footer.itemAt(0) verify(cancelButton) compare(cancelButton.text.toUpperCase(), "CANCEL") @@ -230,10 +229,10 @@ TestCase { } function test_layout() { - var control = createTemporaryObject(dialog, testCase, {width: 100, height: 100}) + let control = createTemporaryObject(dialog, testCase, {width: 100, height: 100}) verify(control) - var openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"}) + let openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"}) verify(openedSpy.valid) control.open() @@ -324,10 +323,10 @@ TestCase { } function test_spacing(data) { - var control = createTemporaryObject(dialog, testCase, {spacing: 20, width: 100, height: 100}) + let control = createTemporaryObject(dialog, testCase, {spacing: 20, width: 100, height: 100}) verify(control) - var openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"}) + let openedSpy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: "opened"}) verify(openedSpy.valid) control.open() @@ -381,14 +380,14 @@ TestCase { } function test_signals(data) { - var control = createTemporaryObject(dialog, testCase) + let control = createTemporaryObject(dialog, testCase) verify(control) control.standardButtons = data.standardButton - var button = control.standardButton(data.standardButton) + let button = control.standardButton(data.standardButton) verify(button) - var buttonSpy = signalSpy.createObject(control.contentItem, {target: control, signalName: data.signalName}) + let buttonSpy = signalSpy.createObject(control.contentItem, {target: control, signalName: data.signalName}) verify(buttonSpy.valid) button.clicked() @@ -432,7 +431,7 @@ TestCase { if (Qt.platform.pluginName === "offscreen") skip("QTBUG-89909") - var window = createTemporaryObject(qtbug85884, testCase) + let window = createTemporaryObject(qtbug85884, testCase) verify(window) tryCompare(window, "focusItemActiveFocus", true) diff --git a/tests/auto/quickcontrols/controls/data/tst_frame.qml b/tests/auto/quickcontrols/controls/data/tst_frame.qml index bef46f765..5a6ce64bc 100644 --- a/tests/auto/quickcontrols/controls/data/tst_frame.qml +++ b/tests/auto/quickcontrols/controls/data/tst_frame.qml @@ -52,10 +52,12 @@ TestCase { } } - function test_empty() { + function init() { failOnWarning(/.?/) + } - var control = createTemporaryObject(frame, testCase) + function test_empty() { + let control = createTemporaryObject(frame, testCase) verify(control) verify(control.contentItem) @@ -66,7 +68,7 @@ TestCase { } function test_oneChild() { - var control = createTemporaryObject(oneChildFrame, testCase) + let control = createTemporaryObject(oneChildFrame, testCase) verify(control) compare(control.contentWidth, 100) @@ -78,7 +80,7 @@ TestCase { } function test_twoChildren() { - var control = createTemporaryObject(twoChildrenFrame, testCase) + let control = createTemporaryObject(twoChildrenFrame, testCase) verify(control) compare(control.contentWidth, 0) @@ -90,7 +92,7 @@ TestCase { } function test_contentItem() { - var control = createTemporaryObject(contentFrame, testCase) + let control = createTemporaryObject(contentFrame, testCase) verify(control) compare(control.contentWidth, 100) diff --git a/tests/auto/quickcontrols/controls/data/tst_groupbox.qml b/tests/auto/quickcontrols/controls/data/tst_groupbox.qml index b5867dd95..c5da5634a 100644 --- a/tests/auto/quickcontrols/controls/data/tst_groupbox.qml +++ b/tests/auto/quickcontrols/controls/data/tst_groupbox.qml @@ -52,10 +52,12 @@ TestCase { } } - function test_empty() { + function init() { failOnWarning(/.?/) + } - var control = createTemporaryObject(groupBox, testCase) + function test_empty() { + let control = createTemporaryObject(groupBox, testCase) verify(control) verify(control.contentItem) @@ -66,7 +68,7 @@ TestCase { } function test_oneChild() { - var control = createTemporaryObject(oneChildBox, testCase) + let control = createTemporaryObject(oneChildBox, testCase) verify(control) compare(control.contentWidth, 100) @@ -78,7 +80,7 @@ TestCase { } function test_twoChildren() { - var control = createTemporaryObject(twoChildrenBox, testCase) + let control = createTemporaryObject(twoChildrenBox, testCase) verify(control) compare(control.contentWidth, 0) @@ -90,7 +92,7 @@ TestCase { } function test_contentItem() { - var control = createTemporaryObject(contentBox, testCase) + let control = createTemporaryObject(contentBox, testCase) verify(control) compare(control.contentWidth, 100) diff --git a/tests/auto/quickcontrols/controls/data/tst_itemdelegate.qml b/tests/auto/quickcontrols/controls/data/tst_itemdelegate.qml index 9d4847b4b..25ad8e26f 100644 --- a/tests/auto/quickcontrols/controls/data/tst_itemdelegate.qml +++ b/tests/auto/quickcontrols/controls/data/tst_itemdelegate.qml @@ -18,21 +18,23 @@ TestCase { ItemDelegate { } } - function test_defaults() { + function init() { failOnWarning(/.?/) + } + function test_defaults() { let control = createTemporaryObject(itemDelegate, testCase) verify(control) } function test_baseline() { - var control = createTemporaryObject(itemDelegate, testCase) + let control = createTemporaryObject(itemDelegate, testCase) verify(control) compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset) } function test_highlighted() { - var control = createTemporaryObject(itemDelegate, testCase) + let control = createTemporaryObject(itemDelegate, testCase) verify(control) verify(!control.highlighted) @@ -41,11 +43,11 @@ TestCase { } function test_spacing() { - var control = createTemporaryObject(itemDelegate, testCase, { text: "Some long, long, long text" }) + let control = createTemporaryObject(itemDelegate, testCase, { text: "Some long, long, long text" }) verify(control) verify(control.contentItem.implicitWidth + control.leftPadding + control.rightPadding > control.background.implicitWidth) - var textLabel = findChild(control.contentItem, "label") + let textLabel = findChild(control.contentItem, "label") verify(textLabel) // The implicitWidth of the IconLabel that all buttons use as their contentItem @@ -74,7 +76,7 @@ TestCase { } function test_display(data) { - var control = createTemporaryObject(itemDelegate, testCase, { + let control = createTemporaryObject(itemDelegate, testCase, { text: "ItemDelegate", display: data.display, width: 400, @@ -84,8 +86,8 @@ TestCase { verify(control) compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png") - var iconImage = findChild(control.contentItem, "image") - var textLabel = findChild(control.contentItem, "label") + let iconImage = findChild(control.contentItem, "image") + let textLabel = findChild(control.contentItem, "label") switch (control.display) { case ItemDelegate.IconOnly: diff --git a/tests/auto/quickcontrols/controls/data/tst_menuitem.qml b/tests/auto/quickcontrols/controls/data/tst_menuitem.qml index d1ed07670..4b801d774 100644 --- a/tests/auto/quickcontrols/controls/data/tst_menuitem.qml +++ b/tests/auto/quickcontrols/controls/data/tst_menuitem.qml @@ -23,21 +23,23 @@ TestCase { Menu { } } - function test_defaults() { + function init() { failOnWarning(/.?/) + } + function test_defaults() { let control = createTemporaryObject(menuItem, testCase) verify(control) } function test_baseline() { - var control = createTemporaryObject(menuItem, testCase) + let control = createTemporaryObject(menuItem, testCase) verify(control) compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset) } function test_checkable() { - var control = createTemporaryObject(menuItem, testCase) + let control = createTemporaryObject(menuItem, testCase) verify(control) verify(control.hasOwnProperty("checkable")) verify(!control.checkable) @@ -54,7 +56,7 @@ TestCase { } function test_highlighted() { - var control = createTemporaryObject(menuItem, testCase) + let control = createTemporaryObject(menuItem, testCase) verify(control) verify(!control.highlighted) @@ -76,7 +78,7 @@ TestCase { } function test_display(data) { - var control = createTemporaryObject(menuItem, testCase, { + let control = createTemporaryObject(menuItem, testCase, { text: "MenuItem", display: data.display, "icon.source": "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png", @@ -85,9 +87,9 @@ TestCase { verify(control) compare(control.icon.source, "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png") - var padding = data.mirrored ? control.contentItem.rightPadding : control.contentItem.leftPadding - var iconImage = findChild(control.contentItem, "image") - var textLabel = findChild(control.contentItem, "label") + let padding = data.mirrored ? control.contentItem.rightPadding : control.contentItem.leftPadding + let iconImage = findChild(control.contentItem, "image") + let textLabel = findChild(control.contentItem, "label") switch (control.display) { case MenuItem.IconOnly: @@ -123,14 +125,14 @@ TestCase { } function test_menu() { - var control = createTemporaryObject(menu, testCase) + let control = createTemporaryObject(menu, testCase) verify(control) - var item1 = createTemporaryObject(menuItem, testCase) + let item1 = createTemporaryObject(menuItem, testCase) verify(item1) compare(item1.menu, null) - var item2 = createTemporaryObject(menuItem, testCase) + let item2 = createTemporaryObject(menuItem, testCase) verify(item2) compare(item2.menu, null) diff --git a/tests/auto/quickcontrols/controls/data/tst_monthgrid.qml b/tests/auto/quickcontrols/controls/data/tst_monthgrid.qml index 5b1081675..7db8855b8 100644 --- a/tests/auto/quickcontrols/controls/data/tst_monthgrid.qml +++ b/tests/auto/quickcontrols/controls/data/tst_monthgrid.qml @@ -37,15 +37,17 @@ TestCase { SignalSpy { } } - function test_defaults() { + function init() { failOnWarning(/.?/) + } + function test_defaults() { let control = createTemporaryObject(defaultGrid, testCase) verify(control) } function test_locale() { - var control = delegateGrid.createObject(testCase, {month: 0, year: 2013}) + let control = delegateGrid.createObject(testCase, {month: 0, year: 2013}) compare(control.contentItem.children.length, 6 * 7 + 1) @@ -58,15 +60,15 @@ TestCase { compare(control.locale.name, "en_GB") // M T W T F S S - var en_GB = ["2012-12-31", "2013-01-01", "2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05", "2013-01-06", + let en_GB = ["2012-12-31", "2013-01-01", "2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05", "2013-01-06", "2013-01-07", "2013-01-08", "2013-01-09", "2013-01-10", "2013-01-11", "2013-01-12", "2013-01-13", "2013-01-14", "2013-01-15", "2013-01-16", "2013-01-17", "2013-01-18", "2013-01-19", "2013-01-20", "2013-01-21", "2013-01-22", "2013-01-23", "2013-01-24", "2013-01-25", "2013-01-26", "2013-01-27", "2013-01-28", "2013-01-29", "2013-01-30", "2013-01-31", "2013-02-01", "2013-02-02", "2013-02-03", "2013-02-04", "2013-02-05", "2013-02-06", "2013-02-07", "2013-02-08", "2013-02-09", "2013-02-10"] - for (var i = 0; i < 42; ++i) { - var cellDate = new Date(en_GB[i]) + for (let i = 0; i < 42; ++i) { + let cellDate = new Date(en_GB[i]) compare(control.contentItem.children[i].date.getFullYear(), cellDate.getUTCFullYear()) compare(control.contentItem.children[i].date.getMonth(), cellDate.getUTCMonth()) compare(control.contentItem.children[i].date.getDate(), cellDate.getUTCDate()) @@ -81,15 +83,15 @@ TestCase { compare(control.locale.name, "en_US") // S M T W T F S - var en_US = ["2012-12-30", "2012-12-31", "2013-01-01", "2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05", + let en_US = ["2012-12-30", "2012-12-31", "2013-01-01", "2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05", "2013-01-06", "2013-01-07", "2013-01-08", "2013-01-09", "2013-01-10", "2013-01-11", "2013-01-12", "2013-01-13", "2013-01-14", "2013-01-15", "2013-01-16", "2013-01-17", "2013-01-18", "2013-01-19", "2013-01-20", "2013-01-21", "2013-01-22", "2013-01-23", "2013-01-24", "2013-01-25", "2013-01-26", "2013-01-27", "2013-01-28", "2013-01-29", "2013-01-30", "2013-01-31", "2013-02-01", "2013-02-02", "2013-02-03", "2013-02-04", "2013-02-05", "2013-02-06", "2013-02-07", "2013-02-08", "2013-02-09"] - for (var j = 0; j < 42; ++j) { - cellDate = new Date(en_US[j]) + for (let j = 0; j < 42; ++j) { + let cellDate = new Date(en_US[j]) compare(control.contentItem.children[j].date.getFullYear(), cellDate.getUTCFullYear()) compare(control.contentItem.children[j].date.getMonth(), cellDate.getUTCMonth()) compare(control.contentItem.children[j].date.getDate(), cellDate.getUTCDate()) @@ -103,7 +105,7 @@ TestCase { } function test_range() { - var control = defaultGrid.createObject(testCase) + let control = defaultGrid.createObject(testCase) control.month = 0 compare(control.month, 0) @@ -138,7 +140,7 @@ TestCase { } function test_bce() { - var control = defaultGrid.createObject(testCase) + let control = defaultGrid.createObject(testCase) compare(control.contentItem.children.length, 6 * 7 + 1) @@ -153,14 +155,14 @@ TestCase { compare(control.year, -1) // M T W T F S S - var jan1bce = [27, 28, 29, 30, 31, 1, 2, + let jan1bce = [27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1, 2, 3, 4, 5, 6] - for (var i = 0; i < 42; ++i) + for (let i = 0; i < 42; ++i) compare(control.contentItem.children[i].text, jan1bce[i].toString()) // February 1 BCE @@ -170,21 +172,21 @@ TestCase { compare(control.year, -1) // M T W T F S S - var feb1bce = [31, 1, 2, 3, 4, 5, 6, + let feb1bce = [31, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] - for (var j = 0; j < 42; ++j) + for (let j = 0; j < 42; ++j) compare(control.contentItem.children[j].text, feb1bce[j].toString()) control.destroy() } function test_font() { - var control = defaultGrid.createObject(testCase) + let control = defaultGrid.createObject(testCase) verify(control.contentItem.children[0]) @@ -202,24 +204,24 @@ TestCase { } function test_clicked(data) { - var control = createTemporaryObject(defaultGrid, testCase) + let control = createTemporaryObject(defaultGrid, testCase) verify(control) compare(control.contentItem.children.length, 6 * 7 + 1) - var pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"}) + let pressedSpy = signalSpy.createObject(control, {target: control, signalName: "pressed"}) verify(pressedSpy.valid) - var releasedSpy = signalSpy.createObject(control, {target: control, signalName: "released"}) + let releasedSpy = signalSpy.createObject(control, {target: control, signalName: "released"}) verify(releasedSpy.valid) - var clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"}) + let clickedSpy = signalSpy.createObject(control, {target: control, signalName: "clicked"}) verify(clickedSpy.valid) - var touch = touchEvent(control) + let touch = touchEvent(control) - for (var i = 0; i < 42; ++i) { - var cell = control.contentItem.children[i] + for (let i = 0; i < 42; ++i) { + let cell = control.contentItem.children[i] verify(cell) if (data.touch) diff --git a/tests/auto/quickcontrols/controls/data/tst_popup.qml b/tests/auto/quickcontrols/controls/data/tst_popup.qml index 48484f588..805443a4d 100644 --- a/tests/auto/quickcontrols/controls/data/tst_popup.qml +++ b/tests/auto/quickcontrols/controls/data/tst_popup.qml @@ -1430,6 +1430,8 @@ TestCase { let popup = window.popup popup.open() + tryCompare(popup, "opened", true) + waitForRendering(popup.contentItem) // mouse clicks into the popup must not propagate to the parent mouseClick(window) diff --git a/tests/auto/quickcontrols/controls/data/tst_scrollview.qml b/tests/auto/quickcontrols/controls/data/tst_scrollview.qml index d8868b027..f5f9e882a 100644 --- a/tests/auto/quickcontrols/controls/data/tst_scrollview.qml +++ b/tests/auto/quickcontrols/controls/data/tst_scrollview.qml @@ -146,6 +146,7 @@ TestCase { } } } + Component { id: scrollableTextAreaWithSibling ScrollView { @@ -728,4 +729,35 @@ TestCase { // Shouldn't crash. } + + Component { + id: scrollViewContentItemComp + + ScrollView { + id: scrollView + anchors.fill: parent + Column { + width: parent.width + Repeater { + model: 20 + Rectangle { + width: scrollView.width + height: 60 + color: (index % 2 == 0) ? "red" : "green" + } + } + } + } + } + + function test_scrollViewContentItemSize() { + let scrollview = createTemporaryObject(scrollViewContentItemComp, testCase) + verify(scrollview) + let contentItem = scrollview.contentItem + waitForRendering(contentItem) + compare(contentItem.contentWidth, 400) + compare(contentItem.contentHeight, 1200) + compare(scrollview.contentWidth, 400) + compare(scrollview.contentHeight, 1200) + } } diff --git a/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml b/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml index d835dc93a..5f6f60eba 100644 --- a/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml +++ b/tests/auto/quickcontrols/controls/data/tst_selectionrectangle.qml @@ -278,7 +278,7 @@ TestCase { // Ensure that a press and hold doesn't start a selection mousePress(tableView, 1, 1, Qt.LeftButton) - mousePress(tableView, 1, 1, Qt.LeftButton, Qt.NoModifier, 1000) + mouseRelease(tableView, 1, 1, Qt.LeftButton, Qt.NoModifier, 1000) verify(!tableView.selectionModel.hasSelection) } @@ -316,7 +316,14 @@ TestCase { verify(tableView.selectionModel.isSelected(tableView.selectionModel.model.index(0, 1))) } - function test_tableView_contiguousSelection() { + function test_tableView_contiguousSelection_data() { + return [ + { startFromCurrentIndex: false }, + { startFromCurrentIndex: true }, + ] + } + + function test_tableView_contiguousSelection(data) { let tableView = createTemporaryObject(tableviewComp, testCase) verify(tableView) let selectionRectangle = tableView.selectionRectangle @@ -325,13 +332,21 @@ TestCase { selectionRectangle.selectionMode = SelectionRectangle.Drag tableView.selectionMode = TableView.ContiguousSelection - // Select two cells by dragging - verify(!tableView.selectionModel.hasSelection) - mouseDrag(tableView, 1, 1, (cellWidth * 2) - 2, 1, Qt.LeftButton) - verify(tableView.selectionModel.hasSelection) - compare(tableView.selectionModel.selectedIndexes.length, 2) - verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0))) - verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1))) + if (data.startFromCurrentIndex) { + // Click on a cell to set current index, but set no selection. + // A later shift-click should then start a new selection from the + // current cell. + mouseClick(tableView, 1, 1, Qt.LeftButton, Qt.NoModifier) + verify(!tableView.selectionModel.hasSelection) + compare(tableView.selectionModel.currentIndex, tableView.index(0, 0)) + } else { + // Start a new selection by dragging on two cells + mouseDrag(tableView, 1, 1, (cellWidth * 2) - 2, 1, Qt.LeftButton) + verify(tableView.selectionModel.hasSelection) + compare(tableView.selectionModel.selectedIndexes.length, 2) + verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0))) + verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1))) + } // A shift click should extend the selection mouseClick(tableView, (cellWidth * 4) - 3, 1, Qt.LeftButton, Qt.ShiftModifier) @@ -400,6 +415,23 @@ TestCase { for (let r = 0; r < 2; ++r) for (let c = 0; c < 3; ++c) verify(tableView.selectionModel.isSelected(tableView.model.index(r, c))) + + // Shift click the second selection so that it overlaps with the first + mouseClick(tableView, 1, 1, Qt.LeftButton, Qt.ShiftModifier) + compare(tableView.selectionModel.selectedIndexes.length, 4) + verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0))) + verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1))) + verify(tableView.selectionModel.isSelected(tableView.model.index(0, 2))) + verify(tableView.selectionModel.isSelected(tableView.model.index(1, 0))) + + // Shift click the selection back again. The first selection on + // row 0 should still be present, even if the second selection + // no longer overlaps it. + mouseClick(tableView, (cellWidth * 3) - 2, (cellHeight * 2) - 1, Qt.LeftButton, Qt.ShiftModifier) + compare(tableView.selectionModel.selectedIndexes.length, 6) + for (let r = 0; r < 2; ++r) + for (let c = 0; c < 3; ++c) + verify(tableView.selectionModel.isSelected(tableView.model.index(r, c))) } function test_handle_position() { @@ -537,7 +569,7 @@ TestCase { verify(!tableView.selectionModel.hasSelection) // Do a press and hold mousePress(tableView, 1, 1, Qt.LeftButton) - mousePress(tableView, 1, 1, Qt.LeftButton, Qt.NoModifier, 1000) + mouseRelease(tableView, 1, 1, Qt.LeftButton, Qt.NoModifier, 1000) verify(tableView.selectionModel.hasSelection) compare(tableView.selectionModel.selectedIndexes.length, 1) verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0))) @@ -546,7 +578,7 @@ TestCase { compare(activeSpy.count, 1) // Remove selection - mouseClick(tableView, 1, 1, Qt.LeftButton) + mouseClick(tableView, 100, 100, Qt.LeftButton) verify(!tableView.selectionModel.hasSelection) compare(draggingSpy.count, 0) compare(activeSpy.count, 2) @@ -556,6 +588,31 @@ TestCase { verify(!tableView.selectionModel.hasSelection) } + function test_pressAndHoldPlussShift() { + let tableView = createTemporaryObject(tableviewComp, testCase) + verify(tableView) + let selectionRectangle = tableView.selectionRectangle + verify(selectionRectangle) + + selectionRectangle.selectionMode = SelectionRectangle.Drag + + verify(!tableView.selectionModel.hasSelection) + verify(!tableView.selectionModel.currentIndex.isValid) + + // select cell 0,0 + mouseClick(tableView, 1, 1, Qt.LeftButton) + compare(tableView.selectionModel.currentIndex, tableView.index(0, 0)) + + // do a long press on cell 1,0 while holding down Shift. This will + // select both cells. + mousePress(tableView, cellWidth + 1, 1, Qt.LeftButton, Qt.ShiftModifier) + mouseRelease(tableView, cellWidth + 1, 1, Qt.LeftButton, Qt.ShiftModifier, 2000) + verify(tableView.selectionModel.hasSelection) + compare(tableView.selectionModel.selectedIndexes.length, 2) + verify(tableView.selectionModel.isSelected(tableView.model.index(0, 0))) + verify(tableView.selectionModel.isSelected(tableView.model.index(0, 1))) + } + function test_pressAndHold_on_top_of_handle() { let tableView = createTemporaryObject(tableviewComp, testCase) verify(tableView) diff --git a/tests/auto/quickcontrols/controls/data/tst_stackview.qml b/tests/auto/quickcontrols/controls/data/tst_stackview.qml index f9b802247..b0b209728 100644 --- a/tests/auto/quickcontrols/controls/data/tst_stackview.qml +++ b/tests/auto/quickcontrols/controls/data/tst_stackview.qml @@ -1604,7 +1604,7 @@ TestCase { StackView { id: stackView anchors.fill: parent - initialItem: cppComponent + initialItem: stackView.cppComponent property Component cppComponent: ComponentCreator.createComponent("import QtQuick; Rectangle { color: \"navajowhite\" }") } diff --git a/tests/auto/quickcontrols/controls/data/tst_textarea.qml b/tests/auto/quickcontrols/controls/data/tst_textarea.qml index 1e03947e0..183170034 100644 --- a/tests/auto/quickcontrols/controls/data/tst_textarea.qml +++ b/tests/auto/quickcontrols/controls/data/tst_textarea.qml @@ -207,10 +207,12 @@ TestCase { } function test_alignment(data) { - var control = createTemporaryObject(textArea, testCase, {text: data.text, placeholderText: data.placeholderText, horizontalAlignment: data.textAlignment}) + var control = createTemporaryObject(textArea, testCase, {text: data.text, placeholderText: data.placeholderText}) - if (data.textAlignment !== undefined) + if (data.textAlignment !== undefined) { + control.horizontalAlignment = data.textAlignment compare(control.horizontalAlignment, data.textAlignment) + } // The placeholder text of the Material style doesn't currently respect the alignment of the control. if (StyleInfo.styleName !== "Material") { @@ -234,7 +236,7 @@ TestCase { return [ {tag: "bold", value: true}, {tag: "capitalization", value: Font.Capitalize}, - {tag: "family", value: "Courier"}, + {tag: "family", value: "Tahoma"}, {tag: "italic", value: true}, {tag: "strikeout", value: true}, {tag: "underline", value: true}, @@ -272,7 +274,7 @@ TestCase { } function test_flickable() { - var control = createTemporaryObject(flickable, testCase, {text:"line0", selectByMouse: true}) + var control = createTemporaryObject(flickable, testCase) verify(control) var textArea = control.TextArea.flickable diff --git a/tests/auto/quickcontrols/controls/data/tst_textfield.qml b/tests/auto/quickcontrols/controls/data/tst_textfield.qml index 66dcdc397..795e6a79b 100644 --- a/tests/auto/quickcontrols/controls/data/tst_textfield.qml +++ b/tests/auto/quickcontrols/controls/data/tst_textfield.qml @@ -154,10 +154,12 @@ TestCase { } function test_alignment(data) { - var control = createTemporaryObject(textField, testCase, {text: data.text, placeholderText: data.placeholderText, horizontalAlignment: data.textAlignment}) + var control = createTemporaryObject(textField, testCase, {text: data.text, placeholderText: data.placeholderText}) - if (data.textAlignment !== undefined) + if (data.textAlignment !== undefined) { + control.horizontalAlignment = data.textAlignment compare(control.horizontalAlignment, data.textAlignment) + } // The placeholder text of the Material style doesn't currently respect the alignment of the control. if (StyleInfo.styleName !== "Material") { for (var i = 0; i < control.children.length; ++i) { @@ -180,7 +182,7 @@ TestCase { return [ {tag: "bold", value: true}, {tag: "capitalization", value: Font.Capitalize}, - {tag: "family", value: "Courier"}, + {tag: "family", value: "Tahoma"}, {tag: "italic", value: true}, {tag: "strikeout", value: true}, {tag: "underline", value: true}, diff --git a/tests/auto/quickcontrols/controls/data/tst_tooltip.qml b/tests/auto/quickcontrols/controls/data/tst_tooltip.qml index 1aa63e56a..3a42f19ec 100644 --- a/tests/auto/quickcontrols/controls/data/tst_tooltip.qml +++ b/tests/auto/quickcontrols/controls/data/tst_tooltip.qml @@ -53,12 +53,12 @@ TestCase { } function test_properties(data) { - var control = createTemporaryObject(toolTip, testCase) + let control = createTemporaryObject(toolTip, testCase) verify(control) compare(control[data.property], data.defaultValue) - var spy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: data.signalName}) + let spy = createTemporaryObject(signalSpy, testCase, {target: control, signalName: data.signalName}) verify(spy.valid) control[data.property] = data.setValue @@ -75,24 +75,24 @@ TestCase { } function test_attached(data) { - var item1 = createTemporaryObject(mouseArea, testCase) + let item1 = createTemporaryObject(mouseArea, testCase) verify(item1) - var item2 = createTemporaryObject(mouseArea, testCase) + let item2 = createTemporaryObject(mouseArea, testCase) verify(item2) // Reset the properties to the expected default values, in case // we're not the first test that uses attached properties to be run. - var sharedTip = ToolTip.toolTip + let sharedTip = ToolTip.toolTip sharedTip[data.property] = data.defaultValue compare(item1.ToolTip[data.property], data.defaultValue) compare(item2.ToolTip[data.property], data.defaultValue) - var spy1 = signalSpy.createObject(item1, {target: item1.ToolTip, signalName: data.signalName}) + let spy1 = signalSpy.createObject(item1, {target: item1.ToolTip, signalName: data.signalName}) verify(spy1.valid) - var spy2 = signalSpy.createObject(item2, {target: item2.ToolTip, signalName: data.signalName}) + let spy2 = signalSpy.createObject(item2, {target: item2.ToolTip, signalName: data.signalName}) verify(spy2.valid) sharedSpy.signalName = data.signalName @@ -138,7 +138,7 @@ TestCase { } function test_delay(data) { - var control = createTemporaryObject(toolTip, testCase, {delay: data.delay}) + let control = createTemporaryObject(toolTip, testCase, {delay: data.delay}) compare(control.visible, false) if (data.imperative) @@ -157,7 +157,7 @@ TestCase { } function test_timeout(data) { - var control = createTemporaryObject(toolTip, testCase, {timeout: 100}) + let control = createTemporaryObject(toolTip, testCase, {timeout: 100}) compare(control.visible, false) if (data.imperative) @@ -179,7 +179,6 @@ TestCase { function test_warning() { ignoreWarning(new RegExp(".*QML QtObject: ToolTip must be attached to an Item")) - ignoreWarning(new RegExp(".*: QML ToolTip: cannot find any window to open popup in.")) object.ToolTip.show("") // don't crash (QTBUG-56243) } @@ -206,7 +205,7 @@ TestCase { } function test_makeVisibleWhileExitTransitionRunning(data) { - var control = createTemporaryObject(toolTipWithExitTransition, testCase) + let control = createTemporaryObject(toolTipWithExitTransition, testCase) // Show, hide, and show the tooltip again. Its exit transition should // start and get cancelled, and then its enter transition should run. @@ -259,18 +258,18 @@ TestCase { skip("Mouse hovering not functional on offscreen/minimal platforms") // Window shortcuts (the default context for Shortcut) require the window to have focus. - var window = testCase.Window.window + let window = testCase.Window.window verify(window) window.requestActivate() tryCompare(window, "active", true) - var root = createTemporaryObject(buttonAndShortcutComponent, testCase) + let root = createTemporaryObject(buttonAndShortcutComponent, testCase) verify(root) mouseMove(root.button, root.button.width / 2, root.button.height / 2) tryCompare(root.button.ToolTip.toolTip, "visible", true) - var shortcutActivatedSpy = signalSpy.createObject(root, { target: root.shortcut, signalName: "activated" }) + let shortcutActivatedSpy = signalSpy.createObject(root, { target: root.shortcut, signalName: "activated" }) verify(shortcutActivatedSpy.valid) keyPress(Qt.Key_A) compare(shortcutActivatedSpy.count, 1) @@ -295,13 +294,13 @@ TestCase { // QTBUG-63644 function test_hover() { - var root = createTemporaryObject(hoverComponent, testCase) + let root = createTemporaryObject(hoverComponent, testCase) verify(root) - var tooltip = root.tooltip + let tooltip = root.tooltip verify(tooltip) - for (var pos = 0; pos <= 25; pos += 5) { + for (let pos = 0; pos <= 25; pos += 5) { mouseMove(root, pos, pos) verify(tooltip.visible) } @@ -313,7 +312,7 @@ TestCase { } function test_nonAttachedToolTipShowAndHide() { - var tip = createTemporaryObject(nonAttachedToolTipComponent, testCase) + let tip = createTemporaryObject(nonAttachedToolTipComponent, testCase) verify(tip) tip.show("hello"); verify(tip.visible) @@ -346,11 +345,11 @@ TestCase { // QTBUG-74226 function test_attachedTimeout() { - var row = createTemporaryObject(timeoutButtonRowComponent, testCase) + let row = createTemporaryObject(timeoutButtonRowComponent, testCase) verify(row) // Press the button that has no timeout; it should stay visible. - var button2 = row.children[1] + let button2 = row.children[1] mousePress(button2) compare(button2.down, true) tryCompare(button2.ToolTip.toolTip, "opened", true) @@ -365,7 +364,7 @@ TestCase { tryCompare(button2.ToolTip, "visible", false) // Now, press the first button that does have a timeout; it should close on its own eventually. - var button1 = row.children[0] + let button1 = row.children[0] mousePress(button1) compare(button1.down, true) // We use a short timeout to speed up the test, but tryCompare(...opened, true) then @@ -402,7 +401,7 @@ TestCase { // QTBUG-62350 function test_wrap() { - var item = createTemporaryObject(wrapComponent, testCase) + let item = createTemporaryObject(wrapComponent, testCase) verify(item) // Avoid "cannot find window to popup in" warning that can occur if it's made visible too early. @@ -466,4 +465,22 @@ TestCase { mouseRelease(longTextButton) tryCompare(longTextButton.ToolTip.toolTip, "visible", false) } + + Component { + id: initiallyVisibleComponent + + Item { + ToolTip.text: "Some text" + ToolTip.visible: true + } + } + + // QTBUG-75483 + function test_initiallyVisible() { + failOnWarning(/.?/) //"QML ToolTip: cannot find any window to open popup in" in particularly + + let item = createTemporaryObject(initiallyVisibleComponent, testCase) + verify(item) + verify(item.ToolTip.visible) + } } diff --git a/tests/auto/quickcontrols/palette/qtquickcontrols2.conf b/tests/auto/quickcontrols/palette/qtquickcontrols2.conf index c5de6b36d..97b122c56 100644 --- a/tests/auto/quickcontrols/palette/qtquickcontrols2.conf +++ b/tests/auto/quickcontrols/palette/qtquickcontrols2.conf @@ -1,5 +1,3 @@ [Basic] Palette\Base=#efefef - -[Basic\Palette] -Text=#101010 +Palette\Text=#101010 diff --git a/tests/auto/quickcontrols/qquickiconimage/tst_qquickiconimage.cpp b/tests/auto/quickcontrols/qquickiconimage/tst_qquickiconimage.cpp index 83df118de..5a0b90b64 100644 --- a/tests/auto/quickcontrols/qquickiconimage/tst_qquickiconimage.cpp +++ b/tests/auto/quickcontrols/qquickiconimage/tst_qquickiconimage.cpp @@ -49,9 +49,6 @@ private slots: private: void setTheme(); - - qreal dpr; - int integerDpr; }; static QImage grabItemToImage(QQuickItem *item) @@ -62,14 +59,14 @@ static QImage grabItemToImage(QQuickItem *item) return result->image(); } -#define SKIP_IF_DPR_TOO_HIGH() \ +#define INIT_DPR(view) \ + [[maybe_unused]] const qreal dpr = view.devicePixelRatio(); \ + [[maybe_unused]] const int integerDpr = qCeil(dpr); \ if (dpr > 2) \ QSKIP("Test does not support device pixel ratio greater than 2") tst_qquickiconimage::tst_qquickiconimage() : - QQmlDataTest(QT_QMLTEST_DATADIR), - dpr(qGuiApp->devicePixelRatio()), - integerDpr(qCeil(dpr)) + QQmlDataTest(QT_QMLTEST_DATADIR) { QQuickStyle::setStyle("Basic"); } @@ -78,6 +75,7 @@ void tst_qquickiconimage::initTestCase() { QQmlDataTest::initTestCase(); QIcon::setThemeName(QStringLiteral("testtheme")); + } void tst_qquickiconimage::defaults() @@ -91,14 +89,12 @@ void tst_qquickiconimage::defaults() void tst_qquickiconimage::nameBindingSourceSize() { - // We can't have images for every DPR. - SKIP_IF_DPR_TOO_HIGH(); - QQuickView view(testFileUrl("nameBindingSourceSize.qml")); QCOMPARE(view.status(), QQuickView::Ready); view.show(); view.requestActivate(); QVERIFY(QTest::qWaitForWindowActive(&view)); + INIT_DPR(view); QQuickIconImage *iconImage = qobject_cast(view.rootObject()->childItems().at(0)); QVERIFY(iconImage); @@ -132,11 +128,10 @@ void tst_qquickiconimage::nameBindingSourceSize() void tst_qquickiconimage::nameBindingSourceSizeWidthHeight() { - SKIP_IF_DPR_TOO_HIGH(); - QQuickView view(testFileUrl("nameBindingSourceSizeWidthHeight.qml")); QCOMPARE(view.status(), QQuickView::Ready); view.show(); + INIT_DPR(view); QQuickIconImage *iconImage = qobject_cast(view.rootObject()); QVERIFY(iconImage); @@ -150,11 +145,10 @@ void tst_qquickiconimage::nameBindingSourceSizeWidthHeight() void tst_qquickiconimage::nameBindingNoSizes() { - SKIP_IF_DPR_TOO_HIGH(); - QQuickView view(testFileUrl("nameBindingNoSizes.qml")); QCOMPARE(view.status(), QQuickView::Ready); view.show(); + INIT_DPR(view); QQuickIconImage *iconImage = qobject_cast(view.rootObject()); QVERIFY(iconImage); @@ -169,11 +163,11 @@ void tst_qquickiconimage::nameBindingNoSizes() void tst_qquickiconimage::sourceBindingNoSizes() { - SKIP_IF_DPR_TOO_HIGH(); - QQuickView view(testFileUrl("sourceBindingNoSizes.qml")); QCOMPARE(view.status(), QQuickView::Ready); view.show(); + INIT_DPR(view); + view.requestActivate(); QVERIFY(QTest::qWaitForWindowActive(&view)); @@ -194,13 +188,12 @@ void tst_qquickiconimage::sourceBindingNoSizes() void tst_qquickiconimage::sourceBindingSourceSize() { - SKIP_IF_DPR_TOO_HIGH(); - QQuickView view(testFileUrl("sourceBindingSourceSize.qml")); QCOMPARE(view.status(), QQuickView::Ready); view.show(); view.requestActivate(); QVERIFY(QTest::qWaitForWindowActive(&view)); + INIT_DPR(view); QQuickIconImage *iconImage = qobject_cast(view.rootObject()->childItems().at(0)); QVERIFY(iconImage); @@ -227,13 +220,12 @@ void tst_qquickiconimage::sourceBindingSourceSize() void tst_qquickiconimage::sourceBindingSourceSizeWidthHeight() { - SKIP_IF_DPR_TOO_HIGH(); - QQuickView view(testFileUrl("sourceBindingSourceSizeWidthHeight.qml")); QCOMPARE(view.status(), QQuickView::Ready); view.show(); view.requestActivate(); QVERIFY(QTest::qWaitForWindowActive(&view)); + INIT_DPR(view); QQuickIconImage *iconImage = qobject_cast(view.rootObject()); QVERIFY(iconImage); @@ -247,13 +239,12 @@ void tst_qquickiconimage::sourceBindingSourceSizeWidthHeight() void tst_qquickiconimage::sourceBindingSourceTooLarge() { - SKIP_IF_DPR_TOO_HIGH(); - QQuickView view(testFileUrl("sourceBindingSourceTooLarge.qml")); QCOMPARE(view.status(), QQuickView::Ready); view.show(); view.requestActivate(); QVERIFY(QTest::qWaitForWindowActive(&view)); + INIT_DPR(view); QQuickIconImage *iconImage = qobject_cast(view.rootObject()); QVERIFY(iconImage); @@ -283,8 +274,6 @@ void tst_qquickiconimage::alignment_data() void tst_qquickiconimage::alignment() { - SKIP_IF_DPR_TOO_HIGH(); - QFETCH(QQuickImage::HAlignment, horizontalAlignment); QFETCH(QQuickImage::VAlignment, verticalAlignment); @@ -293,6 +282,7 @@ void tst_qquickiconimage::alignment() view.show(); view.requestActivate(); QVERIFY(QTest::qWaitForWindowActive(&view)); + INIT_DPR(view); QQuickIconImage *iconImage = qobject_cast(view.rootObject()->childItems().at(0)); QVERIFY(iconImage); @@ -335,6 +325,9 @@ void tst_qquickiconimage::svgNoSizes() QQuickView view(testFileUrl("svgNoSizes.qml")); QCOMPARE(view.status(), QQuickView::Ready); view.show(); + + INIT_DPR(view); + view.requestActivate(); QVERIFY(QTest::qWaitForWindowActive(&view)); @@ -344,8 +337,8 @@ void tst_qquickiconimage::svgNoSizes() QQuickImage *image = qobject_cast(view.rootObject()->childItems().at(1)); QVERIFY(image); - QCOMPARE(iconImage->sourceSize().width(), 48); - QCOMPARE(iconImage->sourceSize().height(), 48); + QCOMPARE(iconImage->sourceSize().width(), 48 * integerDpr); + QCOMPARE(iconImage->sourceSize().height(), 48 * integerDpr); QCOMPARE(iconImage->implicitWidth(), 48.0); QCOMPARE(iconImage->implicitHeight(), 48.0); QCOMPARE(iconImage->width(), 48.0); @@ -383,13 +376,12 @@ void tst_qquickiconimage::svgSourceBindingSourceSize() void tst_qquickiconimage::color() { - SKIP_IF_DPR_TOO_HIGH(); - QQuickView view(testFileUrl("color.qml")); QCOMPARE(view.status(), QQuickView::Ready); view.show(); view.requestActivate(); QVERIFY(QTest::qWaitForWindowActive(&view)); + INIT_DPR(view); QQuickIconImage *iconImage = qobject_cast(view.rootObject()->childItems().at(0)); QVERIFY(iconImage); @@ -438,8 +430,6 @@ void tst_qquickiconimage::changeSourceSize() void tst_qquickiconimage::fileSelectors() { - SKIP_IF_DPR_TOO_HIGH(); - QQuickView view; QScopedPointer fileSelector(new QQmlFileSelector(view.engine())); fileSelector->setExtraSelectors(QStringList() << "testselector"); @@ -448,6 +438,7 @@ void tst_qquickiconimage::fileSelectors() view.show(); view.requestActivate(); QVERIFY(QTest::qWaitForWindowActive(&view)); + INIT_DPR(view); QQuickIconImage *iconImage = qobject_cast(view.rootObject()->childItems().at(0)); QVERIFY(iconImage); diff --git a/tests/auto/quickcontrols/qquickmaterialstyleconf/qtquickcontrols2.conf b/tests/auto/quickcontrols/qquickmaterialstyleconf/qtquickcontrols2.conf index 30cee878b..af51b66f0 100644 --- a/tests/auto/quickcontrols/qquickmaterialstyleconf/qtquickcontrols2.conf +++ b/tests/auto/quickcontrols/qquickmaterialstyleconf/qtquickcontrols2.conf @@ -4,7 +4,5 @@ Style=Material [Material] Background=#444444 Foreground=Red +Font\Family=Courier Font\PixelSize=22 - -[Material\Font] -Family=Courier diff --git a/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml b/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml new file mode 100644 index 000000000..1156d30ae --- /dev/null +++ b/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml @@ -0,0 +1,27 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls +import QtQuick.Window + +Window { + width: 300 + height: 300 + + property alias menu: menu + + Menu { + id: menu + anchors.centerIn: parent + height: 100 + visible: true + Repeater { + model: 10 + delegate: MenuItem { + objectName: text + text: (index + 1) + } + } + } +} diff --git a/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp b/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp index 503485741..fbb4e7d5f 100644 --- a/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp +++ b/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp @@ -1788,6 +1788,7 @@ void tst_QQuickMenu::scrollable_data() QTest::addRow("Window") << QString::fromLatin1("windowScrollable.qml"); QTest::addRow("ApplicationWindow") << QString::fromLatin1("applicationWindowScrollable.qml"); QTest::addRow("WithPadding") << QString::fromLatin1("scrollableWithPadding.qml"); + QTest::addRow("FixedHeight") << QString::fromLatin1("scrollableWithFixedHeight.qml"); } void tst_QQuickMenu::scrollable() diff --git a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml index d4c8b7835..f89e22afc 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml @@ -15,22 +15,24 @@ ApplicationWindow { Button { id: parentButton text: "Parent" + palette.buttonText: hovered ? "tomato" : "black" anchors.fill: parent + anchors.margins: 10 Popup { id: popup - x: 1 - y: 1 - leftPadding: 1 - rightPadding: 1 - topPadding: 1 - bottomPadding: 1 - + x: 10 + y: 10 + leftPadding: 10 + rightPadding: 10 + topPadding: 10 + bottomPadding: 10 Button { anchors.centerIn: parent id: childButton text: "Child" + palette.buttonText: hovered ? "tomato" : "black" } } } diff --git a/tests/auto/quickcontrols/qquickpopup/data/noDimmer.qml b/tests/auto/quickcontrols/qquickpopup/data/noDimmer.qml new file mode 100644 index 000000000..6103c9c8a --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/noDimmer.qml @@ -0,0 +1,22 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Templates as T + +Window { + T.Drawer { + id: root + onModalChanged: { + if (!modal) { + open() + } + } + } + Timer { + interval: 100 + running: true + repeat: false + onTriggered: root.modal = false + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/data/window-hover.qml b/tests/auto/quickcontrols/qquickpopup/data/window-hover.qml index fa61e8b70..054bcf4c0 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/window-hover.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/window-hover.qml @@ -16,21 +16,24 @@ Window { Button { id: parentButton text: "Parent" + palette.buttonText: hovered ? "tomato" : "black" anchors.fill: parent + anchors.margins: 10 Popup { id: popup - x: 1 - y: 1 - topPadding: 1 - bottomPadding: 1 - leftPadding: 1 - rightPadding: 1 + x: 10 + y: 10 + leftPadding: 10 + rightPadding: 10 + topPadding: 10 + bottomPadding: 10 Button { anchors.centerIn: parent id: childButton text: "Child" + palette.buttonText: hovered ? "tomato" : "black" } } } diff --git a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp index 0eb67b432..a7aba76e6 100644 --- a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp +++ b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp @@ -104,6 +104,7 @@ private slots: void doubleClickInMouseArea(); void fadeDimmer_data(); void fadeDimmer(); + void noDimmer(); private: static bool hasWindowActivation(); @@ -993,18 +994,19 @@ void tst_QQuickPopup::hover() QVERIFY(openedSpy.size() == 1 || openedSpy.wait()); QTRY_VERIFY(popup->width() > 10); // somehow this can take a short time with macOS style - // hover the parent button outside the popup - QTest::mouseMove(window, QPoint(window->width() - 1, window->height() - 1)); + // Hover the parent button outside the popup. It has 10 pixel anchor margins around the window. + PointLerper pointLerper(window); + pointLerper.move(15, 15); QCOMPARE(parentButton->isHovered(), !modal); QVERIFY(!childButton->isHovered()); - // hover the popup background - QTest::mouseMove(window, QPoint(1, 1)); + // Hover the popup background. Its top-left is 10 pixels in from its parent. + pointLerper.move(25, 25); QVERIFY(!parentButton->isHovered()); QVERIFY(!childButton->isHovered()); - // hover the child button in a popup - QTest::mouseMove(window, QPoint(popup->x() + popup->width() / 2, popup->y() + popup->height() / 2)); + // Hover the child button in a popup. + pointLerper.move(mapCenterToWindow(childButton)); QVERIFY(!parentButton->isHovered()); QVERIFY(childButton->isHovered()); @@ -2327,6 +2329,25 @@ void tst_QQuickPopup::fadeDimmer() QCOMPARE_GT(opacityChangeCount, 2); } +void tst_QQuickPopup::noDimmer() +{ + QQuickApplicationHelper helper(this, "noDimmer.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *drawer = window->contentItem()->findChild(); + QVERIFY(drawer); + + drawer->open(); + auto dimmer = QQuickPopupPrivate::get(drawer)->dimmer; + QVERIFY(dimmer); + // this must not crash + QTRY_VERIFY(!drawer->isModal()); +} + QTEST_QUICKCONTROLS_MAIN(tst_QQuickPopup) #include "tst_qquickpopup.moc" diff --git a/tests/auto/quickcontrols/qquickuniversalstyleconf/qtquickcontrols2.conf b/tests/auto/quickcontrols/qquickuniversalstyleconf/qtquickcontrols2.conf index 0ec132587..aef058c7d 100644 --- a/tests/auto/quickcontrols/qquickuniversalstyleconf/qtquickcontrols2.conf +++ b/tests/auto/quickcontrols/qquickuniversalstyleconf/qtquickcontrols2.conf @@ -4,7 +4,5 @@ Style=Universal [Universal] Background=#444444 Foreground=Red +Font\Family=Courier Font\PixelSize=22 - -[Universal\Font] -Family=Courier diff --git a/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindow.qml b/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindow.qml new file mode 100644 index 000000000..5b9bab708 --- /dev/null +++ b/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindow.qml @@ -0,0 +1,27 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +Rectangle { + width: 480 + height: 640 + color: dialog.selectedColor + + property alias dialog: dialog + + function doneAccepted() { + dialog.done(ColorDialog.Accepted) + } + + function doneRejected() { + dialog.done(ColorDialog.Rejected) + } + + ColorDialog { + id: dialog + objectName: "ColorDialog" + } +} diff --git a/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindowVisibleTrue.qml b/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindowVisibleTrue.qml new file mode 100644 index 000000000..b146d6151 --- /dev/null +++ b/tests/auto/quickdialogs/qquickcolordialogimpl/data/colorDialogWithoutWindowVisibleTrue.qml @@ -0,0 +1,28 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +Rectangle { + width: 480 + height: 640 + color: dialog.selectedColor + + property alias dialog: dialog + + function doneAccepted() { + dialog.done(ColorDialog.Accepted) + } + + function doneRejected() { + dialog.done(ColorDialog.Rejected) + } + + ColorDialog { + id: dialog + objectName: "ColorDialog" + visible: true + } +} diff --git a/tests/auto/quickdialogs/qquickcolordialogimpl/data/windowSwapping.qml b/tests/auto/quickdialogs/qquickcolordialogimpl/data/windowSwapping.qml new file mode 100644 index 000000000..5215feb24 --- /dev/null +++ b/tests/auto/quickdialogs/qquickcolordialogimpl/data/windowSwapping.qml @@ -0,0 +1,58 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs + +Window { + width: 480 + height: 640 + + property alias dialog: dialog + + function getSubWindow1 () { + return subwindow1 + } + + function getSubWindow2 () { + return subwindow2 + } + + function goToSubWindow1() { + dialog.close() + dialog.parentWindow = subwindow1 + dialog.open() + } + + function goToSubWindow2() { + dialog.close() + dialog.parentWindow = subwindow2 + dialog.open() + } + + function resetParentWindow() { + dialog.close() + dialog.parentWindow = undefined + dialog.open() + } + + Window { + id: subwindow1 + width: 480 + height: 640 + visible: true + } + + Window { + id: subwindow2 + width: 480 + height: 640 + visible: true + } + + ColorDialog { + id: dialog + objectName: "ColorDialog" + } +} diff --git a/tests/auto/quickdialogs/qquickcolordialogimpl/tst_qquickcolordialogimpl.cpp b/tests/auto/quickdialogs/qquickcolordialogimpl/tst_qquickcolordialogimpl.cpp index 23f1e6844..c93ef3d12 100644 --- a/tests/auto/quickdialogs/qquickcolordialogimpl/tst_qquickcolordialogimpl.cpp +++ b/tests/auto/quickdialogs/qquickcolordialogimpl/tst_qquickcolordialogimpl.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,9 @@ private slots: void changeColorFromTextFields(); void windowTitle_data(); void windowTitle(); + void workingInsideQQuickViewer_data(); + void workingInsideQQuickViewer(); + void dialogCanMoveBetweenWindows(); private: bool closePopup(DialogTestHelper *dialogHelper, @@ -456,6 +460,60 @@ void tst_QQuickColorDialogImpl::windowTitle() CLOSE_DIALOG("Ok"); } +void tst_QQuickColorDialogImpl::workingInsideQQuickViewer_data() +{ + QTest::addColumn("initialVisible"); + QTest::addColumn("urlToQmlFile"); + QTest::newRow("visible: false") << false << "colorDialogWithoutWindow.qml"; + QTest::newRow("visible: true") << true << "colorDialogWithoutWindowVisibleTrue.qml"; +} + +void tst_QQuickColorDialogImpl::workingInsideQQuickViewer() // QTBUG-106598 +{ + QFETCH(bool, initialVisible); + QFETCH(QString, urlToQmlFile); + + QQuickView dialogView; + dialogView.setSource(testFileUrl(urlToQmlFile)); + dialogView.show(); + + auto dialog = dialogView.findChild("ColorDialog"); + QVERIFY(dialog); + QCOMPARE(dialog->isVisible(), initialVisible); + + dialog->open(); + QVERIFY(dialog->isVisible()); +} + +void tst_QQuickColorDialogImpl::dialogCanMoveBetweenWindows() +{ + DialogTestHelper dialogHelper(this, "windowSwapping.qml"); + QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage()); + QVERIFY(dialogHelper.waitForWindowActive()); + + QVERIFY(dialogHelper.openDialog()); + QTRY_VERIFY(dialogHelper.isQuickDialogOpen()); + + QCOMPARE(dialogHelper.quickDialog->parent(), dialogHelper.window()); + QVariant subWindow1; + QVariant subWindow2; + + QMetaObject::invokeMethod(dialogHelper.window(), "getSubWindow1", Q_RETURN_ARG(QVariant, subWindow1)); + QMetaObject::invokeMethod(dialogHelper.window(), "getSubWindow2", Q_RETURN_ARG(QVariant, subWindow2)); + + // Confirm that the dialog can swap to different windows + QMetaObject::invokeMethod(dialogHelper.window(), "goToSubWindow1"); + QCOMPARE(dialogHelper.dialog->parentWindow(), qvariant_cast(subWindow1)); + + QMetaObject::invokeMethod(dialogHelper.window(), "goToSubWindow2"); + QCOMPARE(dialogHelper.dialog->parentWindow(), qvariant_cast(subWindow2)); + + QMetaObject::invokeMethod(dialogHelper.window(), "resetParentWindow"); + QCOMPARE(dialogHelper.quickDialog->parent(), dialogHelper.window()); + + CLOSE_DIALOG("Ok"); +} + QTEST_MAIN(tst_QQuickColorDialogImpl) #include "tst_qquickcolordialogimpl.moc" diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp b/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp index 8b4bdad90..7ba297674 100644 --- a/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp +++ b/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp @@ -89,6 +89,8 @@ private slots: void setSelectedFile(); void selectNewFileViaTextField_data(); void selectNewFileViaTextField(); + void selectExistingFileShouldWarnUserWhenFileModeEqualsSaveFile(); + void fileNameTextFieldOnlyChangesWhenSelectingFiles(); private: enum DelegateOrderPolicy @@ -1374,6 +1376,9 @@ void tst_QQuickFileDialogImpl::setSelectedFile() }; FileDialogTestHelper dialogHelper( this, "setSelectedFile.qml", {}, initialProperties); + + dialogHelper.dialog->setOptions(QFileDialogOptions::DontConfirmOverwrite); + OPEN_QUICK_DIALOG(); // The selected file should be what we set. @@ -1480,6 +1485,135 @@ void tst_QQuickFileDialogImpl::selectNewFileViaTextField() } } +void tst_QQuickFileDialogImpl::selectExistingFileShouldWarnUserWhenFileModeEqualsSaveFile() +{ + FileDialogTestHelper dialogHelper(this, "fileDialog.qml"); + dialogHelper.dialog->setFileMode(QQuickFileDialog::SaveFile); + dialogHelper.dialog->setSelectedFile(QUrl::fromLocalFile(tempFile1->fileName())); + + OPEN_QUICK_DIALOG(); + QQuickTest::qWaitForPolish(dialogHelper.window()); + + QSignalSpy acceptedSpy(dialogHelper.dialog, SIGNAL(accepted())); + + auto *dialogButtonBox = dialogHelper.quickDialog->footer()->findChild(); + QVERIFY(dialogButtonBox); + + auto *confirmationDialog = dialogHelper.quickDialog->findChild("confirmationDialog"); + QVERIFY(confirmationDialog); + + auto *openButton = dialogButtonBox->standardButton(QPlatformDialogHelper::Open); + QVERIFY(openButton); + + auto *confirmationButtonBox = qobject_cast(confirmationDialog->footer()); + QVERIFY(confirmationButtonBox); + + const QPoint openButtonCenterPos = + openButton->mapToScene({ openButton->width() / 2, openButton->height() / 2 }).toPoint(); + + QTest::mouseClick(dialogHelper.window(), Qt::LeftButton, Qt::NoModifier, openButtonCenterPos); + + QTRY_VERIFY(confirmationDialog->isOpened()); + QVERIFY(dialogHelper.dialog->isVisible()); + + // Yes button should have focus by default + QTest::keyClick(dialogHelper.window(), Qt::Key_Space, Qt::NoModifier); + + QTRY_VERIFY(!confirmationDialog->isOpened()); + QVERIFY(!dialogHelper.dialog->isVisible()); + QCOMPARE(acceptedSpy.count(), 1); + + // Try again, but click "No" this time. + QVERIFY(dialogHelper.openDialog()); + QTRY_VERIFY(dialogHelper.isQuickDialogOpen()); + + QTest::keyClick(dialogHelper.window(), Qt::Key_Enter, Qt::NoModifier); + + QTRY_VERIFY(confirmationDialog->isOpened()); + QVERIFY(dialogHelper.dialog->isVisible()); + + // Make No button trigger a clicked() event. + auto *confirmationNoButton = confirmationButtonBox->standardButton(QPlatformDialogHelper::No); + QVERIFY(confirmationNoButton); + QVERIFY(clickButton(confirmationNoButton)); + + // FileDialog is still opened + QTRY_VERIFY(!confirmationDialog->isOpened()); + QVERIFY(dialogHelper.dialog->isVisible()); + QCOMPARE(acceptedSpy.count(), 1); + + // Try again + QTest::keyClick(dialogHelper.window(), Qt::Key_Enter, Qt::NoModifier); + + QTRY_VERIFY(confirmationDialog->isOpened()); + QVERIFY(dialogHelper.dialog->isVisible()); + + QTest::keyClick(dialogHelper.window(), Qt::Key_Space, Qt::NoModifier); + + QTRY_VERIFY(!confirmationDialog->isOpened()); + QVERIFY(!dialogHelper.dialog->isVisible()); + QCOMPARE(acceptedSpy.count(), 2); + + // Make sure that DontConfirmOverwrite works + dialogHelper.dialog->setOptions(QFileDialogOptions::DontConfirmOverwrite); + + QVERIFY(dialogHelper.openDialog()); + QTRY_VERIFY(dialogHelper.isQuickDialogOpen()); + + QTest::keyClick(dialogHelper.window(), Qt::Key_Enter, Qt::NoModifier); + QTRY_VERIFY(!confirmationDialog->isOpened()); + QVERIFY(!dialogHelper.dialog->isVisible()); + QCOMPARE(acceptedSpy.count(), 3); +} + +void tst_QQuickFileDialogImpl::fileNameTextFieldOnlyChangesWhenSelectingFiles() +{ + const auto tempSubFile1Url = QUrl::fromLocalFile(tempSubFile1->fileName()); + const auto tempSubDirUrl = QUrl::fromLocalFile(tempSubDir.path()); + const auto tempFile11Url = QUrl::fromLocalFile(tempFile1->fileName()); + + const QVariantMap initialProperties = { + { "tempFile1Url", QVariant::fromValue(tempSubFile1Url) }, + { "fileMode", QVariant::fromValue(QQuickFileDialog::SaveFile) } + }; + FileDialogTestHelper dialogHelper(this, "setSelectedFile.qml", {}, initialProperties); + + OPEN_QUICK_DIALOG(); + QQuickTest::qWaitForPolish(dialogHelper.window()); + + QQuickTextField *fileNameTextField = + dialogHelper.quickDialog->findChild("fileNameTextField"); + QVERIFY(fileNameTextField); + + auto getSelectedFileInfo = [&dialogHelper]() { + return QFileInfo(dialogHelper.dialog->selectedFile().toLocalFile()); + }; + + QVERIFY(getSelectedFileInfo().isFile()); + QCOMPARE(fileNameTextField->text(), tempSubFile1Url.fileName()); + QCOMPARE(dialogHelper.dialog->selectedFile(), tempSubFile1Url); + + auto *breadcrumbBar = dialogHelper.quickDialog->findChild(); + QVERIFY(breadcrumbBar); + + // Pressing the up button causes tempSubDir to be selected + QVERIFY(clickButton(breadcrumbBar->upButton())); + + QVERIFY(getSelectedFileInfo().isDir()); + QCOMPARE(fileNameTextField->text(), tempSubFile1Url.fileName()); + QCOMPARE(dialogHelper.dialog->selectedFile(), tempSubDirUrl); + + // Change the selected file from the outside + dialogHelper.dialog->close(); + dialogHelper.dialog->setSelectedFile(tempFile11Url); + dialogHelper.openDialog(); + QTRY_VERIFY(dialogHelper.isQuickDialogOpen()); + + QVERIFY(getSelectedFileInfo().isFile()); + QCOMPARE(fileNameTextField->text(), tempFile11Url.fileName()); + QCOMPARE(dialogHelper.dialog->selectedFile(), tempFile11Url); +} + QTEST_MAIN(tst_QQuickFileDialogImpl) #include "tst_qquickfiledialogimpl.moc" diff --git a/tests/auto/quickwidgets/qquickwidget/data/tapHandler.qml b/tests/auto/quickwidgets/qquickwidget/data/tapHandler.qml new file mode 100644 index 000000000..fe3d1925e --- /dev/null +++ b/tests/auto/quickwidgets/qquickwidget/data/tapHandler.qml @@ -0,0 +1,11 @@ +import QtQuick + +Rectangle { + width: 100 + height: 100 + color: th.pressed ? "steelblue" : "beige" + + TapHandler { + id: th + } +} diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp index fde6945ed..6d097409b 100644 --- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp +++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -128,6 +129,8 @@ private slots: void synthMouseFromTouch(); void touchTapMouseArea(); void touchTapButton(); + void touchTapHandler_data(); + void touchTapHandler(); void touchMultipleWidgets(); void tabKey(); void resizeOverlay(); @@ -138,6 +141,7 @@ private slots: #endif void focusPreserved(); void accessibilityHandlesViewChange(); + void cleanupRhi(); private: QPointingDevice *device = QTest::createTouchDevice(); @@ -681,6 +685,44 @@ void tst_qquickwidget::touchTapButton() QTRY_VERIFY(rootItem->property("wasClicked").toBool()); } +void tst_qquickwidget::touchTapHandler_data() +{ + QTest::addColumn("guiSynthMouse"); // AA_SynthesizeMouseForUnhandledTouchEvents + QTest::addColumn("gesturePolicy"); + + // QTest::newRow("nosynth: passive grab") << false << QQuickTapHandler::DragThreshold; // still failing + QTest::newRow("nosynth: exclusive grab") << false << QQuickTapHandler::ReleaseWithinBounds; + QTest::newRow("allowsynth: passive grab") << true << QQuickTapHandler::DragThreshold; // QTBUG-113558 + QTest::newRow("allowsynth: exclusive grab") << true << QQuickTapHandler::ReleaseWithinBounds; +} + +void tst_qquickwidget::touchTapHandler() +{ + QFETCH(bool, guiSynthMouse); + QFETCH(QQuickTapHandler::GesturePolicy, gesturePolicy); + + QCoreApplication::setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, guiSynthMouse); + QQuickWidget quick; + QVERIFY(quick.testAttribute(Qt::WA_AcceptTouchEvents)); + quick.setSource(testFileUrl("tapHandler.qml")); + quick.show(); + QVERIFY(QTest::qWaitForWindowExposed(&quick)); + + QQuickItem *rootItem = quick.rootObject(); + QVERIFY(rootItem); + QQuickTapHandler *th = rootItem->findChild(); + QVERIFY(th); + th->setGesturePolicy(gesturePolicy); + QSignalSpy tappedSpy(th, &QQuickTapHandler::tapped); + + const QPoint p(50, 50); + QTest::touchEvent(&quick, device).press(0, p, &quick); + QTRY_COMPARE(th->isPressed(), true); + QTest::touchEvent(&quick, device).release(0, p, &quick); + QTRY_COMPARE(tappedSpy.size(), 1); + QCOMPARE(th->isPressed(), false); +} + void tst_qquickwidget::touchMultipleWidgets() { QWidget window; @@ -1027,6 +1069,27 @@ void tst_qquickwidget::accessibilityHandlesViewChange() (void)iface->child(0); } +class CreateDestroyWidget : public QWidget +{ +public: + using QWidget::create; + using QWidget::destroy; +}; + +void tst_qquickwidget::cleanupRhi() +{ +#ifdef Q_OS_ANDROID + QSKIP("This test crashes on Android (QTBUG-121133)"); +#endif + CreateDestroyWidget topLevel; + QQuickWidget quickWidget(&topLevel); + quickWidget.setSource(testFileUrl("rectangle.qml")); + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + + topLevel.destroy(); + topLevel.create(); +} QTEST_MAIN(tst_qquickwidget) diff --git a/tests/manual/quickcontrols/imagine/musicplayer/qtquickcontrols2.conf b/tests/manual/quickcontrols/imagine/musicplayer/qtquickcontrols2.conf index 33eab6a56..df765ea7d 100644 --- a/tests/manual/quickcontrols/imagine/musicplayer/qtquickcontrols2.conf +++ b/tests/manual/quickcontrols/imagine/musicplayer/qtquickcontrols2.conf @@ -3,8 +3,6 @@ Style=Imagine [Imagine] Path=:/imagine-assets - -[Imagine\Palette] -Text=#6b7b89 -ButtonText=#6b7b89 -WindowText=#6b7b89 +Palette\Text=#6b7b89 +Palette\ButtonText=#6b7b89 +Palette\WindowText=#6b7b89 diff --git a/tests/manual/quickcontrols/material/pages/ButtonPage.qml b/tests/manual/quickcontrols/material/pages/ButtonPage.qml index 3f861e7a7..22ee0894a 100644 --- a/tests/manual/quickcontrols/material/pages/ButtonPage.qml +++ b/tests/manual/quickcontrols/material/pages/ButtonPage.qml @@ -12,6 +12,12 @@ Page { property var backgroundColor header: RowLayout { + CheckBox { + id: textCheckBox + text: "Text" + checked: true + } + CheckBox { id: iconCheckBox text: "Icon" @@ -88,7 +94,7 @@ Page { model: 13 Button { - text: modelData + text: textCheckBox.checked ? modelData : "" flat: flatCheckBox.checked icon.source: iconCheckBox.checked ? "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png" : "" diff --git a/tools/qmllint/main.cpp b/tools/qmllint/main.cpp index b244868a1..531f056a2 100644 --- a/tools/qmllint/main.cpp +++ b/tools/qmllint/main.cpp @@ -30,6 +30,35 @@ using namespace Qt::StringLiterals; constexpr int JSON_LOGGING_FORMAT_REVISION = 3; +bool argumentsFromCommandLineAndFile(QStringList& allArguments, const QStringList &arguments) +{ + allArguments.reserve(arguments.size()); + for (const QString &argument : arguments) { + // "@file" doesn't start with a '-' so we can't use QCommandLineParser for it + if (argument.startsWith(u'@')) { + QString optionsFile = argument; + optionsFile.remove(0, 1); + if (optionsFile.isEmpty()) { + qWarning().nospace() << "The @ option requires an input file"; + return false; + } + QFile f(optionsFile); + if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning().nospace() << "Cannot open options file specified with @"; + return false; + } + while (!f.atEnd()) { + QString line = QString::fromLocal8Bit(f.readLine().trimmed()); + if (!line.isEmpty()) + allArguments << line; + } + } else { + allArguments << argument; + } + } + return true; +} + int main(int argv, char *argc[]) { QHashSeed::setDeterministicGlobalSeed(); @@ -189,11 +218,16 @@ All warnings can be set to three levels: parser.addPositionalArgument(QLatin1String("files"), QLatin1String("list of qml or js files to verify")); - if (!parser.parse(app.arguments())) { - if (parser.unknownOptionNames().isEmpty()) { - qWarning().noquote() << parser.errorText(); - return 1; - } + + QStringList arguments; + if (!argumentsFromCommandLineAndFile(arguments, app.arguments())) { + // argumentsFromCommandLine already printed any necessary warnings. + return 1; + } + + if (!parser.parse(arguments)) { + qWarning().noquote() << parser.errorText(); + return 1; } // Since we can't use QCommandLineParser::process(), we need to handle version and help manually