aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/CMakeLists.txt2
-rw-r--r--tests/auto/cmake/CMakeLists.txt4
-rw-r--r--tests/auto/cmake/empty_qmldir/CMakeLists.txt5
-rw-r--r--tests/auto/core/CMakeLists.txt4
-rw-r--r--tests/auto/qml/CMakeLists.txt11
-rw-r--r--tests/auto/qml/bindingdependencyapi/dummy_imports.qml7
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp4
-rw-r--r--tests/auto/qml/parserstress/CMakeLists.txt6
-rw-r--r--tests/auto/qml/parserstress/dummy_imports.qml7
-rw-r--r--tests/auto/qml/qjsengine/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qjsengine/dummy_imports.qml7
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp38
-rw-r--r--tests/auto/qml/qjsmanagedvalue/CMakeLists.txt5
-rw-r--r--tests/auto/qml/qjsmanagedvalue/dummy_imports.qml4
-rw-r--r--tests/auto/qml/qjsvalue/CMakeLists.txt5
-rw-r--r--tests/auto/qml/qjsvalue/dummy_imports.qml4
-rw-r--r--tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp17
-rw-r--r--tests/auto/qml/qmlcppcodegen/CMakeLists.txt2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/blockComments.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/conversions2.qml8
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/deadStoreLoop.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h78
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/fallbacklookups.qml34
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/functionLookup.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/functionTakingVar.qml11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/infinities.qml9
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/isnan.qml9
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/moveRegVoid.qml20
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/objectInVar.qml15
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/typedArray.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp151
-rw-r--r--tests/auto/qml/qmldiskcache/dummy_imports.qml7
-rw-r--r--tests/auto/qml/qmlformat/BLACKLIST4
-rw-r--r--tests/auto/qml/qmllint/data/Things/qmldir2
-rw-r--r--tests/auto/qml/qmllint/data/callJSValueProp.qml6
-rw-r--r--tests/auto/qml/qmllint/data/callVarProp.qml7
-rw-r--r--tests/auto/qml/qmllint/data/defaultImport.qml (renamed from tests/auto/qml/qmllint/data/optionalImport.qml)0
-rw-r--r--tests/auto/qml/qmllint/data/incompleteQmltypes3.qml6
-rw-r--r--tests/auto/qml/qmllint/data/multilineStringTortureQuote.qml10
-rw-r--r--tests/auto/qml/qmllint/data/multilineStringTortureTick.qml10
-rw-r--r--tests/auto/qml/qmllint/data/qmodelIndex.qml6
-rw-r--r--tests/auto/qml/qmllint/data/shadowedMethod.qml8
-rw-r--r--tests/auto/qml/qmllint/data/shadowedSignal.qml6
-rw-r--r--tests/auto/qml/qmllint/data/shadowedSignalWithId.qml6
-rw-r--r--tests/auto/qml/qmllint/data/shadowedSlot.qml6
-rw-r--r--tests/auto/qml/qmllint/tst_qmllint.cpp1177
-rw-r--r--tests/auto/qml/qmltc/BLACKLIST2
-rw-r--r--tests/auto/qml/qmltc/data/CMakeLists.txt8
-rw-r--r--tests/auto/qml/qmltc/data/cpptypes/deferredpropertytypes.cpp50
-rw-r--r--tests/auto/qml/qmltc/data/cpptypes/deferredpropertytypes.h136
-rw-r--r--tests/auto/qml/qmltc/data/cpptypes/typewithproperties.h5
-rw-r--r--tests/auto/qml/qmltc/data/deferredProperties.qml16
-rw-r--r--tests/auto/qml/qmltc/data/deferredProperties_attached.qml6
-rw-r--r--tests/auto/qml/qmltc/data/deferredProperties_complex.qml9
-rw-r--r--tests/auto/qml/qmltc/data/deferredProperties_group.qml6
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.cpp97
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.h1
-rw-r--r--tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp1
-rw-r--r--tests/auto/qml/qmltc_qprocess/CMakeLists.txt5
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/SingletonThing.qml7
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/erroneousFile.qml4
-rw-r--r--tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp15
-rw-r--r--tests/auto/qml/qmltyperegistrar/CMakeLists.txt10
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp40
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h25
-rw-r--r--tests/auto/qml/qqmlapplicationengine/CMakeLists.txt3
-rw-r--r--tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp4
-rw-r--r--tests/auto/qml/qqmlcomponent/data/jsmodule/module.mjs3
-rw-r--r--tests/auto/qml/qqmlconsole/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qqmlengine/CMakeLists.txt3
-rw-r--r--tests/auto/qml/qqmlfileselector/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qqmlimport/data/absoluteImport.qml4
-rw-r--r--tests/auto/qml/qqmlimport/data/absoluteResourceImport.qml4
-rw-r--r--tests/auto/qml/qqmlimport/data/relativeResourceImport.qml4
-rw-r--r--tests/auto/qml/qqmlimport/tst_qqmlimport.cpp33
-rw-r--r--tests/auto/qml/qqmlincubator/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qqmlinfo/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qqmlitemmodels/data/modelindex.qml1
-rw-r--r--tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml1
-rw-r--r--tests/auto/qml/qqmllanguage/data/foreignExtended.qml7
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h14
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp88
-rw-r--r--tests/auto/qml/qqmllistreference/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qqmlmetaobject/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp15
-rw-r--r--tests/auto/qml/qqmlmetatype/CMakeLists.txt3
-rw-r--r--tests/auto/qml/qqmlnotifier/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qqmlpromise/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qqmlpropertymap/dummy_imports.qml7
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp15
-rw-r--r--tests/auto/qml/qqmlsqldatabase/dummy_imports.qml7
-rw-r--r--tests/auto/qml/qqmltimer/dummy_imports.qml9
-rw-r--r--tests/auto/qml/qqmltypeloader/dummy_imports.qml9
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp1
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/locale_read_singleton.qml21
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp5
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp4
-rw-r--r--tests/auto/qml/qtqmlmodules/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp1
-rw-r--r--tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml6
-rw-r--r--tests/auto/quick/CMakeLists.txt1
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp1
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp1
-rw-r--r--tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp61
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp5
-rw-r--r--tests/auto/quick/qquickanimators/tst_qquickanimators.cpp1
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp1
-rw-r--r--tests/auto/quick/qquickbehaviors/bindable.h2
-rw-r--r--tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp10
-rw-r--r--tests/auto/quick/qquickdrag/tst_qquickdrag.cpp1
-rw-r--r--tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp1
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp3
-rw-r--r--tests/auto/quick/qquickframebufferobject/BLACKLIST8
-rw-r--r--tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp9
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp23
-rw-r--r--tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp1
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp1
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp6
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/CMakeLists.txt36
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/data/test.qml63
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/rhiitem.cpp377
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/rhiitem.h100
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/rhiitem_p.h85
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/testrhiitem.cpp187
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/testrhiitem.h86
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/texture.frag18
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/texture.vert19
-rw-r--r--tests/auto/quick/qquickitemrhiintegration/tst_qquickitemrhiintegration.cpp102
-rw-r--r--tests/auto/quick/qquicklayouts/BLACKLIST9
-rw-r--r--tests/auto/quick/qquicklistview/data/qtbug48044.qml2
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp2
-rw-r--r--tests/auto/quick/qquickloader/data/noEngine.qml32
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp15
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp47
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp10
-rw-r--r--tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp1
-rw-r--r--tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp3
-rw-r--r--tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp1
-rw-r--r--tests/auto/quick/qquickscreen/tst_qquickscreen.cpp1
-rw-r--r--tests/auto/quick/qquickshape/tst_qquickshape.cpp45
-rw-r--r--tests/auto/quick/qquickstates/data/anchorRewind.qml31
-rw-r--r--tests/auto/quick/qquickstates/data/noStateOsciallation.qml22
-rw-r--r--tests/auto/quick/qquickstates/data/parentChangeInvolvingBindings.qml18
-rw-r--r--tests/auto/quick/qquickstates/tst_qquickstates.cpp134
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp262
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp45
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp16
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp4
-rw-r--r--tests/auto/quick/qquicktreeview/testmodel.cpp11
-rw-r--r--tests/auto/quick/qquicktreeview/testmodel.h3
-rw-r--r--tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp350
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp18
-rw-r--r--tests/auto/quickcontrols2/CMakeLists.txt6
-rw-r--r--tests/auto/quickcontrols2/controls/basic/CMakeLists.txt12
-rw-r--r--tests/auto/quickcontrols2/controls/basic/dummy.qml9
-rw-r--r--tests/auto/quickcontrols2/controls/basic/dummy_imports.qml12
-rw-r--r--tests/auto/quickcontrols2/controls/data/tst_button.qml4
-rw-r--r--tests/auto/quickcontrols2/controls/data/tst_checkbox.qml4
-rw-r--r--tests/auto/quickcontrols2/controls/data/tst_combobox.qml5
-rw-r--r--tests/auto/quickcontrols2/controls/data/tst_delaybutton.qml4
-rw-r--r--tests/auto/quickcontrols2/controls/data/tst_radiobutton.qml4
-rw-r--r--tests/auto/quickcontrols2/controls/data/tst_scrollbar.qml34
-rw-r--r--tests/auto/quickcontrols2/controls/data/tst_switch.qml4
-rw-r--r--tests/auto/quickcontrols2/controls/data/tst_toolbutton.qml4
-rw-r--r--tests/auto/quickcontrols2/controls/fusion/CMakeLists.txt12
-rw-r--r--tests/auto/quickcontrols2/controls/fusion/dummy.qml9
-rw-r--r--tests/auto/quickcontrols2/controls/fusion/dummy_imports.qml12
-rw-r--r--tests/auto/quickcontrols2/controls/imagine/CMakeLists.txt12
-rw-r--r--tests/auto/quickcontrols2/controls/imagine/dummy.qml9
-rw-r--r--tests/auto/quickcontrols2/controls/imagine/dummy_imports.qml12
-rw-r--r--tests/auto/quickcontrols2/controls/macos/CMakeLists.txt10
-rw-r--r--tests/auto/quickcontrols2/controls/material/CMakeLists.txt12
-rw-r--r--tests/auto/quickcontrols2/controls/material/dummy.qml9
-rw-r--r--tests/auto/quickcontrols2/controls/material/dummy_imports.qml12
-rw-r--r--tests/auto/quickcontrols2/controls/universal/CMakeLists.txt12
-rw-r--r--tests/auto/quickcontrols2/controls/universal/dummy.qml9
-rw-r--r--tests/auto/quickcontrols2/controls/universal/dummy_imports.qml12
-rw-r--r--tests/auto/quickcontrols2/controls/windows/CMakeLists.txt11
-rw-r--r--tests/auto/quickcontrols2/customization/dummy_imports.qml9
-rw-r--r--tests/auto/quickcontrols2/designer/CMakeLists.txt1
-rw-r--r--tests/auto/quickcontrols2/designer/dummy_imports.qml8
-rw-r--r--tests/auto/quickcontrols2/pressandhold/CMakeLists.txt1
-rw-r--r--tests/auto/quickcontrols2/pressandhold/tst_pressandhold.cpp21
-rw-r--r--tests/auto/quickcontrols2/qquickcontrol/data/fractionalFontSize.qml18
-rw-r--r--tests/auto/quickcontrols2/qquickcontrol/tst_qquickcontrol.cpp20
-rw-r--r--tests/auto/quickcontrols2/qquickdrawer/tst_qquickdrawer.cpp1
-rw-r--r--tests/auto/quickcontrols2/qquickheaderview/tst_qquickheaderview.cpp1
-rw-r--r--tests/auto/quickcontrols2/qquickiconimage/BLACKLIST15
-rw-r--r--tests/auto/quickcontrols2/qquickiconimage/tst_qquickiconimage.cpp12
-rw-r--r--tests/auto/quickcontrols2/qquickiconlabel/data/iconSourceContext.qml13
-rw-r--r--tests/auto/quickcontrols2/qquickiconlabel/data/sub/Actions.qml6
-rw-r--r--tests/auto/quickcontrols2/qquickiconlabel/tst_qquickiconlabel.cpp13
-rw-r--r--tests/auto/quickcontrols2/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp53
-rw-r--r--tests/auto/quickcontrols2/revisions/CMakeLists.txt1
-rw-r--r--tests/auto/quickcontrols2/snippets/CMakeLists.txt1
-rw-r--r--tests/auto/quickcontrols2/styleimportscompiletimeqmlonly/dummy_imports.qml8
-rw-r--r--tests/auto/quickdialogs/CMakeLists.txt2
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/BLACKLIST3
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/CMakeLists.txt1
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/dummy_imports.qml9
-rw-r--r--tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp1
-rw-r--r--tests/auto/quickdialogs/qquickfolderdialogimpl/dummy_imports.qml10
-rw-r--r--tests/auto/quickdialogs/qquickfontdialogimpl/dummy_imports.qml8
-rw-r--r--tests/auto/quickdialogs/qquickmessagedialogimpl/dummy_imports.qml8
-rw-r--r--tests/auto/quicktest/quicktestmainwithsetup/CMakeLists.txt5
207 files changed, 4403 insertions, 928 deletions
diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt
index f2d0ca547a..3ef1b6e735 100644
--- a/tests/auto/CMakeLists.txt
+++ b/tests/auto/CMakeLists.txt
@@ -23,7 +23,7 @@ endif()
if(TARGET Qt::QuickWidgets)
add_subdirectory(quickwidgets)
endif()
-if(TARGET Qt::QmlDomPrivate)
+if(TARGET Qt::QmlDomPrivate AND NOT CMAKE_CROSSCOMPILING)
add_subdirectory(qmldom)
add_subdirectory(qmlls)
endif()
diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt
index 1d75a0bdba..4ea17fb0eb 100644
--- a/tests/auto/cmake/CMakeLists.txt
+++ b/tests/auto/cmake/CMakeLists.txt
@@ -65,7 +65,9 @@ if(TARGET Qt::Qml)
_qt_internal_test_expect_pass(test_plugins)
endif()
_qt_internal_test_expect_pass(empty_qmldir)
- _qt_internal_test_expect_pass(qmlquery)
+ If(NOT ANDROID) # QML only project cannot run on Android with C++ enty point
+ _qt_internal_test_expect_pass(qmlquery)
+ endif()
endif()
if(TARGET Qt::Quick)
diff --git a/tests/auto/cmake/empty_qmldir/CMakeLists.txt b/tests/auto/cmake/empty_qmldir/CMakeLists.txt
index 432e6e99da..259adc2610 100644
--- a/tests/auto/cmake/empty_qmldir/CMakeLists.txt
+++ b/tests/auto/cmake/empty_qmldir/CMakeLists.txt
@@ -14,6 +14,11 @@ endif()
qt_add_executable(empty_qmldir_test main.cpp)
target_link_libraries(empty_qmldir_test PRIVATE Qt6::Test)
+if(ANDROID)
+ # Tests link to Gui by default beacuse it's needed for Android (QTBUG-83997) when
+ # using qt_internal_add_test() but not here where qt_add_executable() is used.
+ target_link_libraries(empty_qmldir_test PRIVATE Qt6::Gui)
+endif()
qt_add_qml_module(empty_qmldir_test
URI Third
diff --git a/tests/auto/core/CMakeLists.txt b/tests/auto/core/CMakeLists.txt
index 31413de9c4..a57498db91 100644
--- a/tests/auto/core/CMakeLists.txt
+++ b/tests/auto/core/CMakeLists.txt
@@ -14,3 +14,7 @@ qt_internal_add_test(tst_core
Qt::Qml
TESTDATA ${test_data}
)
+
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_core)
+endif()
diff --git a/tests/auto/qml/CMakeLists.txt b/tests/auto/qml/CMakeLists.txt
index 4c61f59736..fd587e93a6 100644
--- a/tests/auto/qml/CMakeLists.txt
+++ b/tests/auto/qml/CMakeLists.txt
@@ -32,7 +32,12 @@ add_subdirectory(qtqmlmodules)
add_subdirectory(qquickfolderlistmodel)
add_subdirectory(qqmlapplicationengine)
add_subdirectory(qqmlsettings)
-add_subdirectory(qmldiskcache)
+
+if(NOT INTEGRITY)
+# There's no mounted filesystem on INTEGRITY therefore skipping qmldiskcache
+ add_subdirectory(qmldiskcache)
+endif()
+
add_subdirectory(qqmlmetatype)
if(TARGET Qt::Quick)
add_subdirectory(qmltc_manual)
@@ -44,7 +49,9 @@ if(TARGET Qt::Quick)
(QT_BUILD_STANDALONE_TESTS OR QT6_IS_SHARED_LIBS_BUILD))
add_subdirectory(qmlbasicapp)
endif()
- add_subdirectory(qqmljsscope)
+ if(NOT CMAKE_CROSSCOMPILING)
+ add_subdirectory(qqmljsscope)
+ endif()
endif()
add_subdirectory(qmlsplitlib)
if(TARGET Qt::Widgets)
diff --git a/tests/auto/qml/bindingdependencyapi/dummy_imports.qml b/tests/auto/qml/bindingdependencyapi/dummy_imports.qml
index b9a196e188..63d33cbea6 100644
--- a/tests/auto/qml/bindingdependencyapi/dummy_imports.qml
+++ b/tests/auto/qml/bindingdependencyapi/dummy_imports.qml
@@ -1,8 +1,7 @@
// This file exists for the sole purpose for qmlimportscanner to find
// which modules it needs to extract for deployment.
-// Otherwise, it fails to find the imports that are expressed in C++
-// code in tst_parserstress.cpp
+// Otherwise, it fails to find the imports that are expressed in C++.
-import QtQuick 2.0
+import QtQuick
-QtObject { } // This is needed in order to keep importscanner happy
+QtObject { }
diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
index 69bb86ef09..2c7d2ed9f5 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -1075,7 +1075,7 @@ void tst_QQmlDebugJS::letConstLocals()
const auto value = m_client->response();
if (value.command == QStringLiteral("frame")) {
const auto scopes = value.body.toObject().value(QStringLiteral("scopes")).toArray();
- for (const QJsonValueRef scope : scopes) {
+ for (const auto scope : scopes) {
const auto scopeObject = scope.toObject();
const int type = scopeObject.value("type").toInt();
if (type == 1 || type == 4) {
@@ -1087,7 +1087,7 @@ void tst_QQmlDebugJS::letConstLocals()
} else if (value.command == QStringLiteral("scope")) {
const auto props = value.body.toObject().value(QStringLiteral("object")).toObject()
.value(QStringLiteral("properties")).toArray();
- for (const QJsonValueRef prop : props) {
+ for (const auto prop : props) {
const auto propObj = prop.toObject();
QString name = propObj.value(QStringLiteral("name")).toString();
QVERIFY(name.length() == 1);
diff --git a/tests/auto/qml/parserstress/CMakeLists.txt b/tests/auto/qml/parserstress/CMakeLists.txt
index 2d2f3df4c3..4505dab1da 100644
--- a/tests/auto/qml/parserstress/CMakeLists.txt
+++ b/tests/auto/qml/parserstress/CMakeLists.txt
@@ -18,8 +18,12 @@ qt_internal_add_test(tst_parserstress
Qt::Gui
Qt::GuiPrivate
Qt::QmlPrivate
- TESTDATA ${test_data}
+ TESTDATA ${test_data} "dummy_imports.qml"
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_parserstress)
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/parserstress/dummy_imports.qml b/tests/auto/qml/parserstress/dummy_imports.qml
index b9a196e188..63d33cbea6 100644
--- a/tests/auto/qml/parserstress/dummy_imports.qml
+++ b/tests/auto/qml/parserstress/dummy_imports.qml
@@ -1,8 +1,7 @@
// This file exists for the sole purpose for qmlimportscanner to find
// which modules it needs to extract for deployment.
-// Otherwise, it fails to find the imports that are expressed in C++
-// code in tst_parserstress.cpp
+// Otherwise, it fails to find the imports that are expressed in C++.
-import QtQuick 2.0
+import QtQuick
-QtObject { } // This is needed in order to keep importscanner happy
+QtObject { }
diff --git a/tests/auto/qml/qjsengine/CMakeLists.txt b/tests/auto/qml/qjsengine/CMakeLists.txt
index 6dc74b8858..3e8939a546 100644
--- a/tests/auto/qml/qjsengine/CMakeLists.txt
+++ b/tests/auto/qml/qjsengine/CMakeLists.txt
@@ -27,7 +27,7 @@ qt_internal_add_test(tst_qjsengine
Qt::QmlPrivate
LIBRARIES # special case
Threads::Threads # special case
- TESTDATA ${test_data}
+ TESTDATA ${test_data} "dummy_imports.qml"
)
# Resources:
@@ -61,6 +61,10 @@ qt_internal_add_resource(tst_qjsengine "qmake_immediate"
${qmake_immediate_resource_files}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qjsengine)
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qjsengine/dummy_imports.qml b/tests/auto/qml/qjsengine/dummy_imports.qml
index 8d86f3583b..afe2b33adf 100644
--- a/tests/auto/qml/qjsengine/dummy_imports.qml
+++ b/tests/auto/qml/qjsengine/dummy_imports.qml
@@ -1,8 +1,7 @@
// This file exists for the sole purpose for qmlimportscanner to find
// which modules it needs to extract for deployment.
-// Otherwise, it fails to find the imports that are expressed in C++
-// code in tst_parserstress.cpp
+// Otherwise, it fails to find the imports that are expressed in C++.
-import QtQml 2.0
+import QtQml
-QtObject { } // This is needed in order to keep importscanner happy
+QtObject { }
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index a92141a1e5..6ffc1da3a5 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -69,6 +69,8 @@ private slots:
void newArray_HooliganTask233836();
void toScriptValueBuiltin_data();
void toScriptValueBuiltin();
+ void toScriptValueQmlBuiltin_data();
+ void toScriptValueQmlBuiltin();
void toScriptValueQtQml_data();
void toScriptValueQtQml();
void toScriptValuenotroundtripped_data();
@@ -580,6 +582,36 @@ void tst_QJSEngine::toScriptValueBuiltin()
QCOMPARE(input, output);
}
+void tst_QJSEngine::toScriptValueQmlBuiltin_data()
+{
+ QTest::addColumn<QVariant>("input");
+
+ QTest::newRow("QList<QVariant>") << QVariant(QList<QVariant>{true, 5, 13.2f, 42.24, QString("world"), QUrl("htt://a.com"), QDateTime::currentDateTime(), QRegularExpression("a*b*c"), QByteArray("hello")});
+ QTest::newRow("QList<bool>") << QVariant::fromValue(QList<bool>{true, false, true, false});
+ QTest::newRow("QList<int>") << QVariant::fromValue(QList<int>{1, 2, 3, 4});
+ QTest::newRow("QList<float>") << QVariant::fromValue(QList<float>{1.1f, 2.2f, 3.3f, 4.4f});
+ QTest::newRow("QList<double>") << QVariant::fromValue(QList<double>{1.1, 2.2, 3.3, 4.4});
+ QTest::newRow("QList<QString>") << QVariant::fromValue(QList<QString>{"a", "b", "c", "d"});
+ QTest::newRow("QList<QUrl>") << QVariant::fromValue(QList<QUrl>{QUrl("htt://a.com"), QUrl("file:///tmp/b/"), QUrl("c.foo"), QUrl("/some/d")});
+ QTest::newRow("QList<QDateTime>") << QVariant::fromValue(QList<QDateTime>{QDateTime::currentDateTime(), QDateTime::fromMSecsSinceEpoch(300), QDateTime()});
+ QTest::newRow("QList<QRegularExpression>") << QVariant::fromValue(QList<QRegularExpression>{QRegularExpression("abcd"), QRegularExpression("a[b|c]d$"), QRegularExpression("a*b*d")});
+ QTest::newRow("QList<QByteArray>") << QVariant::fromValue(QList<QByteArray>{QByteArray("aaa"), QByteArray("bbb"), QByteArray("ccc")});
+}
+
+void tst_QJSEngine::toScriptValueQmlBuiltin()
+{
+ QFETCH(QVariant, input);
+
+ // We need the type registrations in QQmlEngine::init() for this.
+ QQmlEngine engine;
+
+ QJSValue outputJS = engine.toScriptValue(input);
+ QVariant output = engine.fromScriptValue<QVariant>(outputJS);
+
+ QVERIFY(output.convert(input.metaType()));
+ QCOMPARE(input, output);
+}
+
void tst_QJSEngine::toScriptValueQtQml_data()
{
QTest::addColumn<QVariant>("input");
@@ -592,10 +624,6 @@ void tst_QJSEngine::toScriptValueQtQml_data()
QTest::newRow("std::vector<QString>") << QVariant::fromValue(std::vector<QString>{"a", "b", "c", "d"});
QTest::newRow("std::vector<QUrl>") << QVariant::fromValue(std::vector<QUrl>{QUrl("htt://a.com"), QUrl("file:///tmp/b/"), QUrl("c.foo"), QUrl("/some/d")});
- QTest::newRow("QList<int>") << QVariant::fromValue(QList<int>{1, 2, 3, 4});
- QTest::newRow("QList<bool>") << QVariant::fromValue(QList<bool>{true, false, true, false});
- QTest::newRow("QStringList") << QVariant::fromValue(QStringList{"a", "b", "c", "d"});
- QTest::newRow("QList<QUrl>") << QVariant::fromValue(QList<QUrl>{QUrl("htt://a.com"), QUrl("file:///tmp/b/"), QUrl("c.foo"), QUrl("/some/d")});
QTest::newRow("QList<QPoint>") << QVariant::fromValue(QList<QPointF>() << QPointF(42.24, 24.42) << QPointF(42.24, 24.42));
static const QStandardItemModel model(4, 4);
@@ -5325,7 +5353,7 @@ void tst_QJSEngine::typedArraySet()
QJSEngine engine;
const auto value = engine.evaluate(
"(function() {"
- " var length = 0xffffffe;"
+ " var length = 0xfffffe0;"
" var offset = 0xfffffff0;"
" var e1;"
" var e2;"
diff --git a/tests/auto/qml/qjsmanagedvalue/CMakeLists.txt b/tests/auto/qml/qjsmanagedvalue/CMakeLists.txt
index 3e466d8e2e..2449b9a320 100644
--- a/tests/auto/qml/qjsmanagedvalue/CMakeLists.txt
+++ b/tests/auto/qml/qjsmanagedvalue/CMakeLists.txt
@@ -10,7 +10,12 @@ qt_internal_add_test(tst_qjsmanagedvalue
PUBLIC_LIBRARIES
Qt::Qml
Qt::QmlPrivate
+ TESTDATA "dummy_imports.qml"
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qjsmanagedvalue)
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qjsmanagedvalue/dummy_imports.qml b/tests/auto/qml/qjsmanagedvalue/dummy_imports.qml
index 1cc20b8aba..afe2b33adf 100644
--- a/tests/auto/qml/qjsmanagedvalue/dummy_imports.qml
+++ b/tests/auto/qml/qjsmanagedvalue/dummy_imports.qml
@@ -1,7 +1,7 @@
// This file exists for the sole purpose for qmlimportscanner to find
// which modules it needs to extract for deployment.
-// Otherwise, it fails to find the imports that are expressed in C++
+// Otherwise, it fails to find the imports that are expressed in C++.
import QtQml
-QtObject { } // This is needed in order to keep importscanner happy
+QtObject { }
diff --git a/tests/auto/qml/qjsvalue/CMakeLists.txt b/tests/auto/qml/qjsvalue/CMakeLists.txt
index bb00f3221a..b8ee79713c 100644
--- a/tests/auto/qml/qjsvalue/CMakeLists.txt
+++ b/tests/auto/qml/qjsvalue/CMakeLists.txt
@@ -22,7 +22,12 @@ qt_internal_add_test(tst_qjsvalue
Qt::Widgets
LIBRARIES # special case
Threads::Threads # special case
+ TESTDATA "dummy_imports.qml"
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qjsvalue)
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qjsvalue/dummy_imports.qml b/tests/auto/qml/qjsvalue/dummy_imports.qml
index 1cc20b8aba..afe2b33adf 100644
--- a/tests/auto/qml/qjsvalue/dummy_imports.qml
+++ b/tests/auto/qml/qjsvalue/dummy_imports.qml
@@ -1,7 +1,7 @@
// This file exists for the sole purpose for qmlimportscanner to find
// which modules it needs to extract for deployment.
-// Otherwise, it fails to find the imports that are expressed in C++
+// Otherwise, it fails to find the imports that are expressed in C++.
import QtQml
-QtObject { } // This is needed in order to keep importscanner happy
+QtObject { }
diff --git a/tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp b/tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp
index 2fd7ef634b..a6c6e4accd 100644
--- a/tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp
+++ b/tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp
@@ -44,6 +44,9 @@ private slots:
void tst_basicapp::loadComponent()
{
QQmlEngine engine;
+#ifdef Q_OS_ANDROID
+ engine.addImportPath(":/");
+#endif
QQmlComponent c(&engine, QStringLiteral("qrc:/BasicApp/main.qml"));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer o(c.create());
@@ -83,6 +86,9 @@ void tst_basicapp::resourceFiles()
void tst_basicapp::fileSystemFiles()
{
+#ifdef Q_OS_ANDROID
+ QSKIP("This test is not valid for Android, because the files can exist only as resources.");
+#endif
const QString basedir = QCoreApplication::applicationDirPath();
QVERIFY(QFile::exists(basedir + QStringLiteral("/BasicApp/main.qml")));
QVERIFY(QFile::exists(basedir + QStringLiteral("/BasicApp/qmldir")));
@@ -99,8 +105,13 @@ void tst_basicapp::fileSystemFiles()
void tst_basicapp::qmldirContents()
{
+#ifdef Q_OS_ANDROID
+ const QString basedir = QStringLiteral(":"); // Use qrc resource path on Android
+#else
+ const QString basedir = QCoreApplication::applicationDirPath();
+#endif
{
- QFile qmldir(QCoreApplication::applicationDirPath() + "/BasicApp/qmldir");
+ QFile qmldir(basedir + "/BasicApp/qmldir");
QVERIFY(qmldir.open(QIODevice::ReadOnly));
const QByteArray contents = qmldir.readAll();
QVERIFY(contents.contains("module BasicApp"));
@@ -115,7 +126,7 @@ void tst_basicapp::qmldirContents()
}
{
- QFile qmldir(QCoreApplication::applicationDirPath() + "/TimeExample/qmldir");
+ QFile qmldir(basedir + "/TimeExample/qmldir");
QVERIFY(qmldir.open(QIODevice::ReadOnly));
const QByteArray contents = qmldir.readAll();
QVERIFY(contents.contains("module TimeExample"));
@@ -132,7 +143,7 @@ void tst_basicapp::qmldirContents()
}
{
- QFile qmldir(QCoreApplication::applicationDirPath() + "/BasicExtension/qmldir");
+ QFile qmldir(basedir + "/BasicExtension/qmldir");
QVERIFY(qmldir.open(QIODevice::ReadOnly));
const QByteArray contents = qmldir.readAll();
QVERIFY(contents.contains("More 1.0 More.ui.qml"));
diff --git a/tests/auto/qml/qmlcppcodegen/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/CMakeLists.txt
index 4c4cf0b1e5..946fa38e44 100644
--- a/tests/auto/qml/qmlcppcodegen/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/CMakeLists.txt
@@ -4,7 +4,7 @@ qt_internal_add_test(tst_qmlcppcodegen
SOURCES
tst_qmlcppcodegen.cpp
LIBRARIES
- Qt::Qml
+ Qt::QmlPrivate
Qt::Gui
codegen_test_module
codegen_test_moduleplugin
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
index 053c3bccc2..bdfe81a1ac 100644
--- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
@@ -1,6 +1,7 @@
set(cpp_sources
birthdayparty.cpp birthdayparty.h
cppbaseclass.h
+ dynamicmeta.h
objectwithmethod.h
person.cpp person.h
theme.cpp theme.h
@@ -35,6 +36,7 @@ set(qml_files
asCast.qml
attachedBaseEnum.qml
bindToValueType.qml
+ blockComments.qml
callContextPropertyLookupResult.qml
childobject.qml
colorAsVariant.qml
@@ -49,6 +51,7 @@ set(qml_files
curlygrouped.qml
cycleHead.qml
deadShoeSize.qml
+ deadStoreLoop.qml
dialog.qml
dynamicscene.qml
enumInvalid.qml
@@ -59,19 +62,24 @@ set(qml_files
excessiveParameters.qml
extendedTypes.qml
failures.qml
+ fallbacklookups.qml
fileDialog.qml
+ functionLookup.qml
funcWithParams.qml
functionReturningVoid.qml
+ functionTakingVar.qml
globals.qml
idAccess.qml
immediateQuit.qml
imports/QmlBench/Globals.qml
importsFromImportPath.qml
+ infinities.qml
invisibleBase.qml
intEnumCompare.qml
intOverflow.qml
interactive.qml
interceptor.qml
+ isnan.qml
jsMathObject.qml
jsimport.qml
jsmoduleimport.qml
@@ -82,12 +90,14 @@ set(qml_files
math.qml
methods.qml
modulePrefix.qml
+ moveRegVoid.qml
noBindingLoop.qml
noQQmlData.qml
nonNotifyable.qml
noscope.qml
notEqualsInt.qml
nullAccess.qml
+ objectInVar.qml
outOfBounds.qml
overriddenMember.qml
ownProperty.qml
@@ -110,6 +120,7 @@ set(qml_files
text.qml
themerbad.qml
themergood.qml
+ typedArray.qml
undefinedResets.qml
unknownAttached.qml
unknownParameter.qml
diff --git a/tests/auto/qml/qmlcppcodegen/data/blockComments.qml b/tests/auto/qml/qmlcppcodegen/data/blockComments.qml
new file mode 100644
index 0000000000..da4bb2fd25
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/blockComments.qml
@@ -0,0 +1,10 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property real implicitHeight: {
+ return /*+ (control.implicitHeaderHeight > 0
+ ? control.implicitHeaderHeight + control.spacing
+ : 0)*/ 8;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/conversions2.qml b/tests/auto/qml/qmlcppcodegen/data/conversions2.qml
index e7bde6c3e6..c3a9414ae2 100644
--- a/tests/auto/qml/qmlcppcodegen/data/conversions2.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/conversions2.qml
@@ -5,6 +5,10 @@ Item {
id: spy
visible: false
+ Rectangle {
+ id: rect
+ }
+
TestUtil {
id: util
}
@@ -15,6 +19,10 @@ Item {
readonly property alias valid:spy.qtest_valid
readonly property alias signalArguments:spy.qtest_signalArguments
+ function clearRectGradient() {
+ rect.gradient = null;
+ }
+
function clear() {
qtest_count = 0
qtest_expectedCount = 0
diff --git a/tests/auto/qml/qmlcppcodegen/data/deadStoreLoop.qml b/tests/auto/qml/qmlcppcodegen/data/deadStoreLoop.qml
new file mode 100644
index 0000000000..f493e4b942
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/deadStoreLoop.qml
@@ -0,0 +1,13 @@
+import QtQuick
+import QtQuick.Controls.Basic
+
+Item {
+ Menu {
+ id: m
+ }
+ function c() {
+ while (m.count > 0) {
+ m.removeItem(m.itemAt(0))
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h b/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h
new file mode 100644
index 0000000000..3f02e460e7
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h
@@ -0,0 +1,78 @@
+#ifndef DYNAMICMETA_H
+#define DYNAMICMETA_H
+
+#include <private/qobject_p.h>
+#include <QtQmlIntegration/qqmlintegration.h>
+
+struct FreeDeleter {
+ void operator()(QMetaObject *meta) { free(meta); }
+};
+
+template<typename T>
+class MetaObjectData : public QDynamicMetaObjectData
+{
+ Q_DISABLE_COPY_MOVE(MetaObjectData)
+public:
+ MetaObjectData() = default;
+ ~MetaObjectData() = default;
+
+ QMetaObject *toDynamicMetaObject(QObject *) override
+ {
+ return const_cast<QMetaObject *>(&T::staticMetaObject);
+ }
+ int metaCall(QObject *o, QMetaObject::Call call, int idx, void **argv) override
+ {
+ return o->qt_metacall(call, idx, argv);
+ }
+};
+
+class DynamicMeta : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int foo READ foo WRITE setFoo NOTIFY fooChanged FINAL)
+ QML_ELEMENT
+public:
+
+ DynamicMeta(QObject *parent = nullptr)
+ : QObject(parent)
+ {
+ // deletes itself
+ QObjectPrivate::get(this)->metaObject = new MetaObjectData<DynamicMeta>;
+ }
+
+ int foo() const { return m_foo; }
+ void setFoo(int newFoo)
+ {
+ if (m_foo != newFoo) {
+ m_foo = newFoo;
+ emit fooChanged();
+ }
+ }
+
+ Q_INVOKABLE int bar(int baz) { return baz + 12; }
+
+Q_SIGNALS:
+ void fooChanged();
+
+private:
+ int m_foo = 0;
+};
+
+class DynamicMetaSingleton : public DynamicMeta
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+ Q_PROPERTY(DynamicMetaSingleton *itself READ itself CONSTANT FINAL)
+public:
+ DynamicMetaSingleton(QObject *parent = nullptr) : DynamicMeta(parent)
+ {
+ QObjectPrivate *d = QObjectPrivate::get(this);
+ delete d->metaObject;
+ d->metaObject = new MetaObjectData<DynamicMetaSingleton>;
+ }
+
+ DynamicMetaSingleton *itself() { return this; }
+};
+
+#endif // DYNAMICMETA_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/fallbacklookups.qml b/tests/auto/qml/qmlcppcodegen/data/fallbacklookups.qml
new file mode 100644
index 0000000000..4b58cd344d
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/fallbacklookups.qml
@@ -0,0 +1,34 @@
+import TestTypes
+import QtQml
+
+DynamicMeta {
+ id: self
+
+ function getSingleton(): QtObject {
+ return DynamicMetaSingleton.itself
+ }
+
+ function withContext(): int {
+ foo = 93;
+ objectName = "aa" + foo;
+ return bar(4);
+ }
+
+ function withId(): int {
+ self.foo = 94;
+ self.objectName = "bb" + foo;
+ return self.bar(5);
+ }
+
+ function withSingleton(): int {
+ DynamicMetaSingleton.foo = 95;
+ DynamicMetaSingleton.objectName = "cc" + DynamicMetaSingleton.foo;
+ return DynamicMetaSingleton.bar(6);
+ }
+
+ function withProperty(): int {
+ DynamicMetaSingleton.itself.foo = 96;
+ DynamicMetaSingleton.itself.objectName = "dd" + DynamicMetaSingleton.itself.foo;
+ return DynamicMetaSingleton.itself.bar(7);
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/functionLookup.qml b/tests/auto/qml/qmlcppcodegen/data/functionLookup.qml
new file mode 100644
index 0000000000..211f524088
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/functionLookup.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ function foo() { return "a" + 99 }
+ property var bar: foo
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/functionTakingVar.qml b/tests/auto/qml/qmlcppcodegen/data/functionTakingVar.qml
new file mode 100644
index 0000000000..1765bfcab9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/functionTakingVar.qml
@@ -0,0 +1,11 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property var c;
+
+ function a(b: var) {
+ c = b;
+ }
+
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/infinities.qml b/tests/auto/qml/qmlcppcodegen/data/infinities.qml
new file mode 100644
index 0000000000..5813d7a3ac
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/infinities.qml
@@ -0,0 +1,9 @@
+import QtQml
+
+QtObject {
+ property real positiveInfinity: Infinity
+ property real negativeInfinity: -Infinity
+ property real positiveZero: 0.0
+ property real negativeZero: -0.0
+ property real naN: NaN
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/isnan.qml b/tests/auto/qml/qmlcppcodegen/data/isnan.qml
new file mode 100644
index 0000000000..dfc64e8002
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/isnan.qml
@@ -0,0 +1,9 @@
+import QtQml
+
+QtObject {
+ property real good: 10.1
+ property real bad: "f" / 10
+
+ property bool a: isNaN(good)
+ property bool b: isNaN(bad)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/moveRegVoid.qml b/tests/auto/qml/qmlcppcodegen/data/moveRegVoid.qml
new file mode 100644
index 0000000000..f1e78babba
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/moveRegVoid.qml
@@ -0,0 +1,20 @@
+import QtQuick
+
+Rectangle {
+ id: root
+ property bool translucency: false
+
+ gradient: Gradient {
+ id: grad
+ }
+
+ onTranslucencyChanged: {
+ if (translucency) {
+ root.color = "transparent";
+ root.gradient = null;
+ } else {
+ root.color = "white";
+ root.gradient = grad;
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/objectInVar.qml b/tests/auto/qml/qmlcppcodegen/data/objectInVar.qml
new file mode 100644
index 0000000000..9177ff2089
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/objectInVar.qml
@@ -0,0 +1,15 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: self
+
+ property var thing: self
+
+ function doThing() : bool {
+ if (self.thing)
+ return true;
+ else
+ return false;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/typedArray.qml b/tests/auto/qml/qmlcppcodegen/data/typedArray.qml
new file mode 100644
index 0000000000..0072357ae3
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/typedArray.qml
@@ -0,0 +1,7 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property list<bool> values1: []
+ property list<int> values2: []
+}
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index 99376491fd..74794eb7fc 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -23,6 +23,8 @@
#include <data/cppbaseclass.h>
#include <data/objectwithmethod.h>
+#include <QtQml/private/qqmlengine_p.h>
+
#include <QtTest>
#include <QtQml>
#include <QtGui/qcolor.h>
@@ -117,6 +119,13 @@ private slots:
void revisions();
void invisibleBase();
void notEqualsInt();
+ void infinities();
+ void blockComments();
+ void functionLookup();
+ void objectInVar();
+ void functionTakingVar();
+ void testIsnan();
+ void fallbackLookups();
};
void tst_QmlCppCodegen::simpleBinding()
@@ -646,6 +655,8 @@ void tst_QmlCppCodegen::interestingFiles_data()
QTest::addRow("dynamicscene") << u"dynamicscene.qml"_qs << true;
QTest::addRow("curlygrouped") << u"curlygrouped.qml"_qs << true;
QTest::addRow("cycleHead") << u"cycleHead.qml"_qs << false;
+ QTest::addRow("deadStoreLoop") << u"deadStoreLoop.qml"_qs << true;
+ QTest::addRow("moveRegVoid") << u"moveRegVoid.qml"_qs << true;
}
void tst_QmlCppCodegen::interestingFiles()
@@ -1753,6 +1764,146 @@ void tst_QmlCppCodegen::notEqualsInt()
QCOMPARE(t->property("text").toString(), u"Bar"_qs);
}
+void tst_QmlCppCodegen::infinities()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/TestTypes/infinities.qml"_qs));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+
+ QCOMPARE(o->property("positiveInfinity").toDouble(), std::numeric_limits<double>::infinity());
+ QCOMPARE(o->property("negativeInfinity").toDouble(), -std::numeric_limits<double>::infinity());
+
+ const double positiveZero = o->property("positiveZero").toDouble();
+ QCOMPARE(positiveZero, 0.0);
+ QVERIFY(!std::signbit(positiveZero));
+
+ const double negativeZero = o->property("negativeZero").toDouble();
+ QCOMPARE(negativeZero, -0.0);
+ QVERIFY(std::signbit(negativeZero));
+
+ QVERIFY(qIsNaN(o->property("naN").toDouble()));
+}
+
+void tst_QmlCppCodegen::blockComments()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/TestTypes/blockComments.qml"_qs));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("implicitHeight").toDouble(), 8.0);
+}
+
+void tst_QmlCppCodegen::functionLookup()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/TestTypes/functionLookup.qml"_qs));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ const QVariant foo = o->property("bar");
+ QCOMPARE(foo.metaType(), QMetaType::fromType<QJSValue>());
+ const QJSManagedValue method(engine.toScriptValue(foo), &engine);
+ QVERIFY(method.isFunction());
+ const QJSValue result = method.call();
+ QVERIFY(result.isString());
+ QCOMPARE(result.toString(), QStringLiteral("a99"));
+}
+
+void tst_QmlCppCodegen::objectInVar()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/TestTypes/objectInVar.qml"_qs));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(qvariant_cast<QObject*>(o->property("thing")), o.data());
+
+ bool result = false;
+ QVERIFY(QMetaObject::invokeMethod(o.data(), "doThing", Q_RETURN_ARG(bool, result)));
+ QVERIFY(result);
+
+ o->setProperty("thing", QVariant::fromValue<std::nullptr_t>(nullptr));
+ QVERIFY(QMetaObject::invokeMethod(o.data(), "doThing", Q_RETURN_ARG(bool, result)));
+ QVERIFY(!result);
+}
+
+void tst_QmlCppCodegen::functionTakingVar()
+{
+ QQmlEngine engine;
+ const QUrl document(u"qrc:/TestTypes/functionTakingVar.qml"_qs);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+
+ QVERIFY(!o->property("c").isValid());
+
+ int value = 11;
+ QQmlEnginePrivate *e = QQmlEnginePrivate::get(&engine);
+ void *args[] = { nullptr, reinterpret_cast<void *>(std::addressof(value)) };
+ QMetaType types[] = { QMetaType::fromType<void>(), QMetaType::fromType<std::decay_t<int>>() };
+ e->executeRuntimeFunction(document, 0, o.data(), 1, args, types);
+
+ QCOMPARE(o->property("c"), QVariant::fromValue<int>(11));
+}
+
+void tst_QmlCppCodegen::testIsnan()
+{
+ QQmlEngine engine;
+ const QUrl document(u"qrc:/TestTypes/isnan.qml"_qs);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+
+ QCOMPARE(o->property("good").toDouble(), 10.1);
+ QVERIFY(qIsNaN(o->property("bad").toDouble()));
+
+ const QVariant a = o->property("a");
+ QCOMPARE(a.metaType(), QMetaType::fromType<bool>());
+ QVERIFY(!a.toBool());
+
+ const QVariant b = o->property("b");
+ QCOMPARE(b.metaType(), QMetaType::fromType<bool>());
+ QVERIFY(b.toBool());
+}
+
+void tst_QmlCppCodegen::fallbackLookups()
+{
+ QQmlEngine engine;
+ const QUrl document(u"qrc:/TestTypes/fallbacklookups.qml"_qs);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+
+ QCOMPARE(o->objectName(), QString());
+ int result = 0;
+
+ QMetaObject::invokeMethod(o.data(), "withContext", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 16);
+ QCOMPARE(o->objectName(), QStringLiteral("aa93"));
+
+ QMetaObject::invokeMethod(o.data(), "withId", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 17);
+ QCOMPARE(o->objectName(), QStringLiteral("bb94"));
+
+ QObject *singleton = nullptr;
+ QMetaObject::invokeMethod(o.data(), "getSingleton", Q_RETURN_ARG(QObject*, singleton));
+ QVERIFY(singleton);
+
+ QMetaObject::invokeMethod(o.data(), "withSingleton", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 18);
+ QCOMPARE(singleton->objectName(), QStringLiteral("cc95"));
+
+ QMetaObject::invokeMethod(o.data(), "withProperty", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 19);
+ QCOMPARE(singleton->objectName(), QStringLiteral("dd96"));
+}
+
void tst_QmlCppCodegen::runInterpreted()
{
if (qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER"))
diff --git a/tests/auto/qml/qmldiskcache/dummy_imports.qml b/tests/auto/qml/qmldiskcache/dummy_imports.qml
index b9a196e188..63d33cbea6 100644
--- a/tests/auto/qml/qmldiskcache/dummy_imports.qml
+++ b/tests/auto/qml/qmldiskcache/dummy_imports.qml
@@ -1,8 +1,7 @@
// This file exists for the sole purpose for qmlimportscanner to find
// which modules it needs to extract for deployment.
-// Otherwise, it fails to find the imports that are expressed in C++
-// code in tst_parserstress.cpp
+// Otherwise, it fails to find the imports that are expressed in C++.
-import QtQuick 2.0
+import QtQuick
-QtObject { } // This is needed in order to keep importscanner happy
+QtObject { }
diff --git a/tests/auto/qml/qmlformat/BLACKLIST b/tests/auto/qml/qmlformat/BLACKLIST
index 4f2b3f7272..8b904fd665 100644
--- a/tests/auto/qml/qmlformat/BLACKLIST
+++ b/tests/auto/qml/qmlformat/BLACKLIST
@@ -1,3 +1,3 @@
-# QTBUG-09404
+# QTBUG-98494
[testExample]
-*
+windows-10 gcc
diff --git a/tests/auto/qml/qmllint/data/Things/qmldir b/tests/auto/qml/qmllint/data/Things/qmldir
index 8902de116b..e1d493a480 100644
--- a/tests/auto/qml/qmllint/data/Things/qmldir
+++ b/tests/auto/qml/qmllint/data/Things/qmldir
@@ -3,4 +3,4 @@ Something 1.0 SomethingElse.qml
typeinfo plugins.qmltypes
depends QtQuick 2.0
import QtQml 2.0
-optional import QtQuick.LocalStorage auto
+default import QtQuick.LocalStorage auto
diff --git a/tests/auto/qml/qmllint/data/callJSValueProp.qml b/tests/auto/qml/qmllint/data/callJSValueProp.qml
new file mode 100644
index 0000000000..357c810383
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/callJSValueProp.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ function foo() {}
+ Component.onCompleted: Qt.callLater(foo);
+}
diff --git a/tests/auto/qml/qmllint/data/callVarProp.qml b/tests/auto/qml/qmllint/data/callVarProp.qml
new file mode 100644
index 0000000000..ad69e2a679
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/callVarProp.qml
@@ -0,0 +1,7 @@
+import QtQml
+
+QtObject {
+ property var foo: () => {}
+
+ Component.onCompleted: foo()
+}
diff --git a/tests/auto/qml/qmllint/data/optionalImport.qml b/tests/auto/qml/qmllint/data/defaultImport.qml
index 2be7cd444a..2be7cd444a 100644
--- a/tests/auto/qml/qmllint/data/optionalImport.qml
+++ b/tests/auto/qml/qmllint/data/defaultImport.qml
diff --git a/tests/auto/qml/qmllint/data/incompleteQmltypes3.qml b/tests/auto/qml/qmllint/data/incompleteQmltypes3.qml
new file mode 100644
index 0000000000..142134d49e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/incompleteQmltypes3.qml
@@ -0,0 +1,6 @@
+import Things 1.0
+
+SomethingEntirelyStrange {
+ id: self
+ property var a: palette
+}
diff --git a/tests/auto/qml/qmllint/data/multilineStringTortureQuote.qml b/tests/auto/qml/qmllint/data/multilineStringTortureQuote.qml
new file mode 100644
index 0000000000..ca8924f3f3
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multilineStringTortureQuote.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ property string quote: "
+ quote: \" \\\" \\\\\"
+ ticks: ` \` \\\` \\\`
+ singleTicks: ' \' \\' \\\'
+ expression: \${expr} \${expr} \\\${expr} \\\${expr}
+ "
+}
diff --git a/tests/auto/qml/qmllint/data/multilineStringTortureTick.qml b/tests/auto/qml/qmllint/data/multilineStringTortureTick.qml
new file mode 100644
index 0000000000..40484603d0
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multilineStringTortureTick.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ property string quote: '
+ quote: " \" \\" \\\"
+ ticks: \` \` \\\` \\\`
+ singleTicks: \' \\\' \\\\\'
+ expression: \${expr} \${expr} \\\${expr} \\\${expr}
+ '
+}
diff --git a/tests/auto/qml/qmllint/data/qmodelIndex.qml b/tests/auto/qml/qmllint/data/qmodelIndex.qml
new file mode 100644
index 0000000000..e0df84b68b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qmodelIndex.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property ItemSelectionModel itemSelectionModel;
+ function row() { return itemSelectionModel.currentIndex.row; }
+}
diff --git a/tests/auto/qml/qmllint/data/shadowedMethod.qml b/tests/auto/qml/qmllint/data/shadowedMethod.qml
new file mode 100644
index 0000000000..72f18aaec7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/shadowedMethod.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+QtObject {
+ function foo() {}
+ property bool foo: false
+
+ Component.onCompleted: foo()
+}
diff --git a/tests/auto/qml/qmllint/data/shadowedSignal.qml b/tests/auto/qml/qmllint/data/shadowedSignal.qml
new file mode 100644
index 0000000000..e4bb003495
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/shadowedSignal.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+MouseArea {
+ id: mouseArea
+ Component.onCompleted: pressed()
+}
diff --git a/tests/auto/qml/qmllint/data/shadowedSignalWithId.qml b/tests/auto/qml/qmllint/data/shadowedSignalWithId.qml
new file mode 100644
index 0000000000..ed7cc9f6c4
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/shadowedSignalWithId.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+MouseArea {
+ id: mouseArea
+ Component.onCompleted: mouseArea.pressed()
+}
diff --git a/tests/auto/qml/qmllint/data/shadowedSlot.qml b/tests/auto/qml/qmllint/data/shadowedSlot.qml
new file mode 100644
index 0000000000..cb09645746
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/shadowedSlot.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+ObjectModel {
+ property bool move: false
+ Component.onCompleted: move()
+}
diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp
index 2469228dc1..32065c0246 100644
--- a/tests/auto/qml/qmllint/tst_qmllint.cpp
+++ b/tests/auto/qml/qmllint/tst_qmllint.cpp
@@ -40,6 +40,28 @@ class TestQmllint: public QQmlDataTest
public:
TestQmllint();
+ struct Message
+ {
+ QString text = QString();
+ quint32 line = 0, column = 0;
+ QtMsgType severity = QtWarningMsg;
+ };
+
+ struct Result
+ {
+ enum Flag { ExitsNormally = 0x1, NoMessages = 0x2 };
+
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ static Result clean() { return Result { {}, {}, {}, { NoMessages, ExitsNormally } }; }
+
+ QList<Message> expectedMessages = {};
+ QList<Message> badMessages = {};
+ QList<Message> expectedReplacements = {};
+
+ Flags flags = {};
+ };
+
private Q_SLOTS:
void initTestCase() override;
@@ -96,20 +118,37 @@ private:
QString runQmllint(const QString &fileToLint, std::function<void(QProcess &)> handleResult,
const QStringList &extraArgs = QStringList(), bool ignoreSettings = true,
- bool addImportDirs = true);
+ bool addImportDirs = true, bool absolutePath = true);
QString runQmllint(const QString &fileToLint, bool shouldSucceed,
const QStringList &extraArgs = QStringList(), bool ignoreSettings = true,
- bool addImportDirs = true);
+ bool addImportDirs = true, bool absolutePath = true);
void callQmllint(const QString &fileToLint, bool shouldSucceed, QJsonArray *warnings = nullptr,
QStringList importDirs = {}, QStringList qmltypesFiles = {},
QStringList resources = {},
DefaultImportOption defaultImports = UseDefaultImports,
QMap<QString, QQmlJSLogger::Option> *options = nullptr);
- void searchWarnings(const QJsonArray &warnings, const QString &string, const QString &filename,
+ void searchWarnings(const QJsonArray &warnings, const QString &string,
+ QtMsgType type = QtWarningMsg, quint32 line = 0, quint32 column = 0,
ContainOption shouldContain = StringContained,
ReplacementOption searchReplacements = NoReplacementSearch);
+ template<typename ExpectedMessageFailureHandler, typename BadMessageFailureHandler>
+ void checkResult(const QJsonArray &warnings, const Result &result,
+ ExpectedMessageFailureHandler onExpectedMessageFailures,
+ BadMessageFailureHandler onBadMessageFailures);
+
+ void checkResult(const QJsonArray &warnings, const Result &result)
+ {
+ checkResult(
+ warnings, result, [] {}, [] {});
+ }
+
+ void runTest(const QString &testFile, const Result &result, QStringList importDirs = {},
+ QStringList qmltypesFiles = {}, QStringList resources = {},
+ DefaultImportOption defaultImports = UseDefaultImports,
+ QMap<QString, QQmlJSLogger::Option> *options = nullptr);
+
QString m_qmllintPath;
QString m_qmljsrootgenPath;
QString m_qmltyperegistrarPath;
@@ -118,6 +157,8 @@ private:
QQmlJSLinter m_linter;
};
+Q_DECLARE_METATYPE(TestQmllint::Result)
+
TestQmllint::TestQmllint()
: QQmlDataTest(QT_QMLTEST_DATADIR),
m_defaultImportPaths({ QLibraryInfo::path(QLibraryInfo::QmlImportsPath), dataDirectory() }),
@@ -184,14 +225,14 @@ void TestQmllint::testUnqualified_data()
// access injected name from signal
QTest::newRow("SignalHandler1")
<< QStringLiteral("SignalHandler.qml")
- << QStringLiteral("onDoubleClicked: function(mouse) {") << 5 << 21;
+ << QStringLiteral("onDoubleClicked: function(mouse) {") << 5 << 21;
QTest::newRow("SignalHandler2")
<< QStringLiteral("SignalHandler.qml")
- << QStringLiteral("onPositionChanged: function(mouse) {") << 10 << 21;
+ << QStringLiteral("onPositionChanged: function(mouse) {") << 10 << 21;
QTest::newRow("SignalHandlerShort1") << QStringLiteral("SignalHandler.qml")
- << QStringLiteral("onClicked: (mouse) => ") << 8 << 29;
+ << QStringLiteral("onClicked: (mouse) => ") << 8 << 29;
QTest::newRow("SignalHandlerShort2")
- << QStringLiteral("SignalHandler.qml") << QStringLiteral("onPressAndHold: (mouse) => ")
+ << QStringLiteral("SignalHandler.qml") << QStringLiteral("onPressAndHold: (mouse) => ")
<< 12 << 34;
// access catch identifier outside catch block
QTest::newRow("CatchStatement") << QStringLiteral("CatchStatement.qml") << QStringLiteral("err") << 6 << 21;
@@ -205,56 +246,38 @@ void TestQmllint::testUnqualified_data()
void TestQmllint::testUnknownCausesFail()
{
- {
- QJsonArray warnings;
- callQmllint("unknownElement.qml", false, &warnings);
- searchWarnings(
- warnings,
- QStringLiteral(
- "Warning: %1:4:5: Unknown was not found. Did you add all import paths?")
- .arg(testFile("unknownElement.qml")),
- "unknownElement.qml");
- }
- {
- QJsonArray warnings;
- callQmllint("TypeWithUnknownPropertyType.qml", false, &warnings);
- searchWarnings(
- warnings,
- QStringLiteral(
- "Warning: %1:4:5: Something was not found. Did you add all import paths?")
- .arg(testFile("TypeWithUnknownPropertyType.qml")),
- "TypeWithUnknownPropertyType.qml");
- }
+ runTest("unknownElement.qml",
+ Result { { Message {
+ QStringLiteral("Unknown was not found. Did you add all import paths?"), 4, 5,
+ QtWarningMsg } } });
+ runTest("TypeWithUnknownPropertyType.qml",
+ Result { { Message {
+ QStringLiteral("Something was not found. Did you add all import paths?"), 4, 5,
+ QtWarningMsg } } });
}
void TestQmllint::directoryPassedAsQmlTypesFile()
{
- QJsonArray warnings;
- callQmllint("unknownElement.qml", false, &warnings, {}, { dataDirectory() });
- searchWarnings(warnings,
- QStringLiteral("QML types file cannot be a directory: ") + dataDirectory(),
- "unknownElement.qml");
+ runTest("unknownElement.qml",
+ Result { { Message { QStringLiteral("QML types file cannot be a directory: ")
+ + dataDirectory() } } },
+ {}, { dataDirectory() });
}
void TestQmllint::oldQmltypes()
{
- QJsonArray warnings;
- callQmllint("oldQmltypes.qml", false, &warnings);
- searchWarnings(warnings, QStringLiteral("typeinfo not declared in qmldir file"),
- "oldQmltypes.qml");
- searchWarnings(warnings,
- QStringLiteral("QQuickItem was not found. Did you add all import paths?"),
- "oldQmltypes.qml", StringNotContained);
- searchWarnings(warnings, QStringLiteral("Found deprecated dependency specifications"),
- "oldQmltypes.qml");
-
- // Checking for both lines separately so that we don't have to mess with the line endings.b
- searchWarnings(warnings,
- QStringLiteral("Meta object revision and export version differ."),
- "oldQmltypes.qml");
- searchWarnings(warnings,
- QStringLiteral("Revision 0 corresponds to version 0.0; it should be 1.0."),
- "oldQmltypes.qml");
+ runTest("oldQmltypes.qml",
+ Result { {
+ Message { QStringLiteral("typeinfo not declared in qmldir file") },
+ Message {
+ QStringLiteral("Found deprecated dependency specifications") },
+ Message { QStringLiteral(
+ "Meta object revision and export version differ.") },
+ Message { QStringLiteral(
+ "Revision 0 corresponds to version 0.0; it should be 1.0.") },
+ },
+ { Message { QStringLiteral(
+ "QQuickItem was not found. Did you add all import paths?") } } });
}
void TestQmllint::qmltypes_data()
@@ -366,509 +389,595 @@ void TestQmllint::resources()
void TestQmllint::dirtyQmlCode_data()
{
QTest::addColumn<QString>("filename");
- QTest::addColumn<QString>("warningMessage");
- QTest::addColumn<QString>("notContained");
- QTest::addColumn<QString>("replacement");
- QTest::addColumn<bool>("exitsNormally");
+ QTest::addColumn<Result>("result");
QTest::newRow("Invalid_syntax_QML")
- << QStringLiteral("failure1.qml") << QStringLiteral("%1:4:8: Expected token `:'")
- << QString() << QString() << false;
- QTest::newRow("Invalid_syntax_JS")
- << QStringLiteral("failure1.js") << QStringLiteral("%1:4:12: Expected token `;'")
- << QString() << QString() << false;
+ << QStringLiteral("failure1.qml")
+ << Result { { Message { QStringLiteral("Expected token `:'"), 4, 8, QtCriticalMsg } } };
+ QTest::newRow("Invalid_syntax_JS") << QStringLiteral("failure1.js")
+ << Result { { Message { QStringLiteral("Expected token `;'"),
+ 4, 12, QtCriticalMsg } } };
QTest::newRow("AutomatchedSignalHandler")
<< QStringLiteral("AutomatchedSignalHandler.qml")
- << QString("Warning: %1:12:36: Unqualified access") << QString() << QString() << false;
+ << Result { { Message { QStringLiteral("Unqualified access"), 12, 36 } } };
QTest::newRow("AutomatchedSignalHandler2")
<< QStringLiteral("AutomatchedSignalHandler.qml")
- << QString("Info: Implicitly defining onClicked as signal handler") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Implicitly defining onClicked as signal handler"), 0, 0,
+ QtInfoMsg } } };
QTest::newRow("MemberNotFound")
<< QStringLiteral("memberNotFound.qml")
- << QString("Warning: %1:6:31: Property \"foo\" not found on type \"QtObject\"")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Property \"foo\" not found on type \"QtObject\""), 6,
+ 31 } } };
QTest::newRow("UnknownJavascriptMethd")
<< QStringLiteral("unknownJavascriptMethod.qml")
- << QString("Warning: %1:5:25: Property \"foo2\" not found on type \"Methods\"")
- << QString() << QString() << false;
- QTest::newRow("badAlias") << QStringLiteral("badAlias.qml")
- << QString("Warning: %1:3:1: Cannot resolve alias \"wrong\"")
- << QString() << QString() << false;
- QTest::newRow("badAliasProperty1") << QStringLiteral("badAliasProperty.qml")
- << QString("Warning: %1:3:1: Cannot resolve alias \"wrong\"")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Property \"foo2\" not found on type \"Methods\""), 5,
+ 25 } } };
+ QTest::newRow("badAlias")
+ << QStringLiteral("badAlias.qml")
+ << Result { { Message { QStringLiteral("Cannot resolve alias \"wrong\""), 3, 1 } } };
+ QTest::newRow("badAliasProperty1")
+ << QStringLiteral("badAliasProperty.qml")
+ << Result { { Message { QStringLiteral("Cannot resolve alias \"wrong\""), 3, 1 } } };
QTest::newRow("badAliasExpression")
<< QStringLiteral("badAliasExpression.qml")
- << QString("Warning: %1:5:26: Invalid alias expression. Only IDs and field member "
- "expressions can be aliased")
- << QString() << QString() << false;
- QTest::newRow("aliasCycle1") << QStringLiteral(
- "aliasCycle.qml") << QString("Warning: %1:3:1: Alias \"b\" is part of an alias cycle")
- << QString() << QString() << false;
- QTest::newRow("aliasCycle2") << QStringLiteral(
- "aliasCycle.qml") << QString("Warning: %1:3:1: Alias \"a\" is part of an alias cycle")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Invalid alias expression. Only IDs and field member "
+ "expressions can be aliased"),
+ 5, 26 } } };
+ QTest::newRow("aliasCycle1") << QStringLiteral("aliasCycle.qml")
+ << Result { { Message {
+ QStringLiteral("Alias \"b\" is part of an alias cycle"),
+ 3, 1 } } };
+ QTest::newRow("aliasCycle2") << QStringLiteral("aliasCycle.qml")
+ << Result { { Message {
+ QStringLiteral("Alias \"a\" is part of an alias cycle"),
+ 3, 1 } } };
QTest::newRow("badParent")
<< QStringLiteral("badParent.qml")
- << QString("Warning: %1:5:34: Property \"rrr\" not found on type \"Item\"") << QString()
- << QString() << false;
+ << Result { { Message { QStringLiteral("Property \"rrr\" not found on type \"Item\""),
+ 5, 34 } } };
QTest::newRow("parentIsComponent")
<< QStringLiteral("parentIsComponent.qml")
- << QString("Warning: %1:7:39: Property \"progress\" not found on type \"QQuickItem\"")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Property \"progress\" not found on type \"QQuickItem\""), 7,
+ 39 } } };
QTest::newRow("badTypeAssertion")
<< QStringLiteral("badTypeAssertion.qml")
- << QString("Warning: %1:5:39: Property \"rrr\" not found on type \"QQuickItem\"")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Property \"rrr\" not found on type \"QQuickItem\""), 5,
+ 39 } } };
QTest::newRow("incompleteQmltypes")
<< QStringLiteral("incompleteQmltypes.qml")
- << QString("Warning: %1:5:26: Type \"QPalette\" of property \"palette\" not found")
- << QString() << QString() << false;
- QTest::newRow("incompleteQmltypes2") << QStringLiteral("incompleteQmltypes2.qml")
- << QString("Warning: %1:5:35: Property \"weDontKnowIt\" "
- "not found on type \"CustomPalette\"")
- << QString() << QString() << false;
- QTest::newRow("inheritanceCylce") << QStringLiteral("Cycle1.qml")
- << QString("Warning: %1: Cycle2 is part of an inheritance "
- "cycle: Cycle2 -> Cycle3 -> Cycle1 -> Cycle2")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Type \"QPalette\" of property \"palette\" not found"), 5,
+ 26 } } };
+ QTest::newRow("incompleteQmltypes2")
+ << QStringLiteral("incompleteQmltypes2.qml")
+ << Result { { Message { QStringLiteral("Property \"weDontKnowIt\" "
+ "not found on type \"CustomPalette\""),
+ 5, 35 } } };
+ QTest::newRow("incompleteQmltypes3")
+ << QStringLiteral("incompleteQmltypes3.qml")
+ << Result { { Message {
+ QStringLiteral("Type \"QPalette\" of property \"palette\" not found"), 5,
+ 21 } } };
+ QTest::newRow("inheritanceCycle")
+ << QStringLiteral("Cycle1.qml")
+ << Result { { Message {
+ QStringLiteral("Cycle2 is part of an inheritance cycle: Cycle2 -> Cycle3 "
+ "-> Cycle1 -> Cycle2"),
+ 2, 1 } } };
QTest::newRow("badQmldirImportAndDepend")
<< QStringLiteral("qmldirImportAndDepend/bad.qml")
- << QString("Warning: %1:3:1: Item was not found. Did you add all import paths?")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Item was not found. Did you add all import paths?"), 3,
+ 1 } } };
QTest::newRow("javascriptMethodsInModule")
<< QStringLiteral("javascriptMethodsInModuleBad.qml")
- << QString("Warning: %1:5:21: Property \"unknownFunc\" not found on type \"Foo\"")
- << QString() << QString() << false;
- QTest::newRow("badEnumFromQtQml") << QStringLiteral("badEnumFromQtQml.qml")
- << QString("Warning: %1:4:30: Property \"Linear123\" not "
- "found on type \"QQmlEasingEnums\"")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Property \"unknownFunc\" not found on type \"Foo\""), 5,
+ 21 } } };
+ QTest::newRow("badEnumFromQtQml")
+ << QStringLiteral("badEnumFromQtQml.qml")
+ << Result { { Message { QStringLiteral("Property \"Linear123\" not "
+ "found on type \"QQmlEasingEnums\""),
+ 4, 30 } } };
QTest::newRow("anchors3")
<< QStringLiteral("anchors3.qml")
- << QString("Cannot assign binding of type QQuickItem to QQuickAnchorLine") << QString()
- << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Cannot assign binding of type QQuickItem to QQuickAnchorLine") } } };
QTest::newRow("nanchors1") << QStringLiteral("nanchors1.qml")
- << QString("unknown grouped property scope nanchors.") << QString()
- << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "unknown grouped property scope nanchors.") } } };
QTest::newRow("nanchors2") << QStringLiteral("nanchors2.qml")
- << QString("unknown grouped property scope nanchors.") << QString()
- << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "unknown grouped property scope nanchors.") } } };
QTest::newRow("nanchors3") << QStringLiteral("nanchors3.qml")
- << QString("unknown grouped property scope nanchors.") << QString()
- << QString() << false;
- QTest::newRow("badAliasObject") << QStringLiteral("badAliasObject.qml")
- << QString("Warning: %1:8:40: Property \"wrongwrongwrong\" not "
- "found on type \"QtObject\"")
- << QString() << QString() << false;
- QTest::newRow("badScript")
- << QStringLiteral("badScript.qml")
- << QString("Warning: %1:5:21: Property \"stuff\" not found on type \"Empty\"")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "unknown grouped property scope nanchors.") } } };
+ QTest::newRow("badAliasObject")
+ << QStringLiteral("badAliasObject.qml")
+ << Result { { Message { QStringLiteral("Property \"wrongwrongwrong\" not "
+ "found on type \"QtObject\""),
+ 8, 40 } } };
+ QTest::newRow("badScript") << QStringLiteral("badScript.qml")
+ << Result { { Message {
+ QStringLiteral(
+ "Property \"stuff\" not found on type \"Empty\""),
+ 5, 21 } } };
QTest::newRow("badScriptOnAttachedProperty")
<< QStringLiteral("badScript.attached.qml")
- << QString("Warning: %1:3:26: Unqualified access") << QString() << QString() << false;
- QTest::newRow("brokenNamespace") << QStringLiteral("brokenNamespace.qml")
- << QString("Warning: %1:4:19: Type not found in namespace")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral("Unqualified access"), 3, 26 } } };
+ QTest::newRow("brokenNamespace")
+ << QStringLiteral("brokenNamespace.qml")
+ << Result { { Message { QStringLiteral("Type not found in namespace"), 4, 19 } } };
QTest::newRow("segFault (bad)")
<< QStringLiteral("SegFault.bad.qml")
- << QStringLiteral("Property \"foobar\" not found on type \"QQuickScreenAttached\"")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Property \"foobar\" not found on type \"QQuickScreenAttached\"") } } };
QTest::newRow("VariableUsedBeforeDeclaration")
<< QStringLiteral("useBeforeDeclaration.qml")
- << QStringLiteral("%1:5:9: Variable \"argq\" is used here before its declaration. "
- "The declaration is at 6:13.")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Variable \"argq\" is used here before its declaration. "
+ "The declaration is at 6:13."),
+ 5, 9 } } };
QTest::newRow("SignalParameterMismatch")
<< QStringLiteral("namedSignalParameters.qml")
- << QStringLiteral("Parameter 1 to signal handler for \"onSig\" is called \"argarg\". "
- "The signal has a parameter of the same name in position 2.")
- << QStringLiteral("onSig2") << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Parameter 1 to signal handler for \"onSig\" is called \"argarg\". "
+ "The signal has a parameter of the same name in position 2.") } },
+ { Message { QStringLiteral("onSig2") } } };
QTest::newRow("TooManySignalParameters")
<< QStringLiteral("tooManySignalParameters.qml")
- << QStringLiteral("Signal handler for \"onSig\" has more formal parameters "
- "than the signal it handles.")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Signal handler for \"onSig\" has more formal parameters "
+ "than the signal it handles.") } } };
QTest::newRow("OnAssignment") << QStringLiteral("onAssignment.qml")
- << QStringLiteral("Property \"loops\" not found on type \"bool\"")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Property \"loops\" not found on type \"bool\"") } } };
QTest::newRow("BadAttached") << QStringLiteral("badAttached.qml")
- << QStringLiteral("unknown attached property scope WrongAttached.")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "unknown attached property scope WrongAttached.") } } };
QTest::newRow("BadBinding") << QStringLiteral("badBinding.qml")
- << QStringLiteral(
+ << Result { { Message { QStringLiteral(
"Binding assigned to \"doesNotExist\", but no property "
- "\"doesNotExist\" exists in the current element.")
- << QString() << QString() << false;
+ "\"doesNotExist\" exists in the current element.") } } };
QTest::newRow("bad template literal (simple)")
<< QStringLiteral("badTemplateStringSimple.qml")
- << QStringLiteral("Cannot assign binding of type string to int") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign binding of type string to int") } } };
QTest::newRow("bad template literal (substitution)")
<< QStringLiteral("badTemplateStringSubstitution.qml")
- << QStringLiteral("Cannot assign binding of type QString to int") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign binding of type QString to int") } } };
QTest::newRow("bad constant number to string")
<< QStringLiteral("numberToStringProperty.qml")
- << QStringLiteral("Cannot assign a numeric constant to a string property") << QString()
- << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Cannot assign a numeric constant to a string property") } } };
QTest::newRow("bad unary minus to string")
<< QStringLiteral("unaryMinusToStringProperty.qml")
- << QStringLiteral("Cannot assign a numeric constant to a string property") << QString()
- << QString() << false;
- QTest::newRow("bad tranlsation binding (qsTr)")
- << QStringLiteral("bad_qsTr.qml") << QStringLiteral("") << QString() << QString()
- << false;
+ << Result { { Message { QStringLiteral(
+ "Cannot assign a numeric constant to a string property") } } };
+ QTest::newRow("bad tranlsation binding (qsTr)") << QStringLiteral("bad_qsTr.qml") << Result {};
QTest::newRow("bad string binding (QT_TR_NOOP)")
<< QStringLiteral("bad_QT_TR_NOOP.qml")
- << QStringLiteral("Cannot assign binding of type string to int") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign binding of type string to int") } } };
QTest::newRow("BadScriptBindingOnGroup")
<< QStringLiteral("badScriptBinding.group.qml")
- << QStringLiteral("Warning: %1:3:10: Binding assigned to \"bogusProperty\", but no "
- "property \"bogusProperty\" exists in the current element.")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Binding assigned to \"bogusProperty\", but no "
+ "property \"bogusProperty\" exists in the current element."),
+ 3, 10 } } };
QTest::newRow("BadScriptBindingOnAttachedType")
<< QStringLiteral("badScriptBinding.attached.qml")
- << QStringLiteral("Warning: %1:5:12: Binding assigned to \"bogusProperty\", but no "
- "property \"bogusProperty\" exists in the current element.")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Binding assigned to \"bogusProperty\", but no "
+ "property \"bogusProperty\" exists in the current element."),
+ 5, 12 } } };
QTest::newRow("BadScriptBindingOnAttachedSignalHandler")
<< QStringLiteral("badScriptBinding.attachedSignalHandler.qml")
- << QStringLiteral(
- "Warning: %1:3:10: no matching signal found for handler \"onBogusSignal\"")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("no matching signal found for handler \"onBogusSignal\""), 3,
+ 10 } } };
QTest::newRow("BadPropertyType")
<< QStringLiteral("badPropertyType.qml")
- << QStringLiteral("No type found for property \"bad\". This may be due to a missing "
- "import statement or incomplete qmltypes files.")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "No type found for property \"bad\". This may be due to a missing "
+ "import statement or incomplete qmltypes files.") } } };
QTest::newRow("Deprecation (Property, with reason)")
<< QStringLiteral("deprecatedPropertyReason.qml")
- << QStringLiteral("Property \"deprecated\" is deprecated (Reason: Test)") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Property \"deprecated\" is deprecated (Reason: Test)") } } };
QTest::newRow("Deprecation (Property, no reason)")
<< QStringLiteral("deprecatedProperty.qml")
- << QStringLiteral("Property \"deprecated\" is deprecated") << QString() << QString()
- << false;
+ << Result { { Message { QStringLiteral("Property \"deprecated\" is deprecated") } } };
QTest::newRow("Deprecation (Property binding, with reason)")
<< QStringLiteral("deprecatedPropertyBindingReason.qml")
- << QStringLiteral("Binding on deprecated property \"deprecatedReason\" (Reason: Test)")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Binding on deprecated property \"deprecatedReason\" (Reason: Test)") } } };
QTest::newRow("Deprecation (Property binding, no reason)")
<< QStringLiteral("deprecatedPropertyBinding.qml")
- << QStringLiteral("Binding on deprecated property \"deprecated\"") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Binding on deprecated property \"deprecated\"") } } };
QTest::newRow("Deprecation (Type, with reason)")
<< QStringLiteral("deprecatedTypeReason.qml")
- << QStringLiteral("Type \"TypeDeprecatedReason\" is deprecated (Reason: Test)")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Type \"TypeDeprecatedReason\" is deprecated (Reason: Test)") } } };
QTest::newRow("Deprecation (Type, no reason)")
<< QStringLiteral("deprecatedType.qml")
- << QStringLiteral("Type \"TypeDeprecated\" is deprecated") << QString() << QString()
- << false;
+ << Result { { Message { QStringLiteral("Type \"TypeDeprecated\" is deprecated") } } };
QTest::newRow("MissingDefaultProperty")
<< QStringLiteral("defaultPropertyWithoutKeyword.qml")
- << QStringLiteral("Cannot assign to non-existent default property") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign to non-existent default property") } } };
QTest::newRow("MissingDefaultPropertyDefinedInTheSameType")
<< QStringLiteral("defaultPropertyWithinTheSameType.qml")
- << QStringLiteral("Cannot assign to non-existent default property") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign to non-existent default property") } } };
QTest::newRow("DoubleAssignToDefaultProperty")
<< QStringLiteral("defaultPropertyWithDoubleAssignment.qml")
- << QStringLiteral("Cannot assign multiple objects to a default non-list property")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Cannot assign multiple objects to a default non-list property") } } };
QTest::newRow("DefaultPropertyWithWrongType(string)")
<< QStringLiteral("defaultPropertyWithWrongType.qml")
- << QStringLiteral("Cannot assign to default property of incompatible type")
- << QStringLiteral("Cannot assign to non-existent default property") << QString()
- << false;
+ << Result { { Message { QStringLiteral(
+ "Cannot assign to default property of incompatible type") } },
+ { Message { QStringLiteral(
+ "Cannot assign to non-existent default property") } } };
QTest::newRow("MultiDefaultPropertyWithWrongType")
<< QStringLiteral("multiDefaultPropertyWithWrongType.qml")
- << QStringLiteral("Cannot assign to default property of incompatible type")
- << QStringLiteral("Cannot assign to non-existent default property") << QString()
- << false;
+ << Result { { Message { QStringLiteral(
+ "Cannot assign to default property of incompatible type") } },
+ { Message { QStringLiteral(
+ "Cannot assign to non-existent default property") } } };
QTest::newRow("InvalidImport")
<< QStringLiteral("invalidImport.qml")
- << QStringLiteral("Failed to import FooBar. Are your import paths set up properly?")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Failed to import FooBar. Are your import paths set up properly?") } } };
QTest::newRow("Unused Import (simple)")
- << QStringLiteral("unused_simple.qml") << QStringLiteral("Unused import at %1:1:1")
- << QString() << QString() << true;
+ << QStringLiteral("unused_simple.qml")
+ << Result { { Message { QStringLiteral("Unused import at"), 1, 1, QtInfoMsg } },
+ {},
+ {},
+ Result::ExitsNormally };
QTest::newRow("Unused Import (prefix)")
- << QStringLiteral("unused_prefix.qml") << QStringLiteral("Unused import at %1:1:1")
- << QString() << QString() << true;
- QTest::newRow("TypePropertAccess") << QStringLiteral("typePropertyAccess.qml") << QString()
- << QString() << QString() << false;
+ << QStringLiteral("unused_prefix.qml")
+ << Result { { Message { QStringLiteral("Unused import at"), 1, 1, QtInfoMsg } },
+ {},
+ {},
+ Result::ExitsNormally };
+ QTest::newRow("TypePropertAccess") << QStringLiteral("typePropertyAccess.qml") << Result {};
QTest::newRow("badAttachedProperty")
<< QStringLiteral("badAttachedProperty.qml")
- << QString("Property \"progress\" not found on type \"TestType\"") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Property \"progress\" not found on type \"TestType\"") } } };
QTest::newRow("badAttachedPropertyNested")
<< QStringLiteral("badAttachedPropertyNested.qml")
- << QString("12:41: Property \"progress\" not found on type \"QObject\"")
- << QString("6:37: Property \"progress\" not found on type \"QObject\"") << QString()
- << false;
+ << Result { { Message { QStringLiteral(
+ "Property \"progress\" not found on type \"QObject\""),
+ 12, 41 } },
+ { Message { QString("Property \"progress\" not found on type \"QObject\""),
+ 6, 37 } } };
QTest::newRow("badAttachedPropertyTypeString")
<< QStringLiteral("badAttachedPropertyTypeString.qml")
- << QString("Cannot assign binding of type string to int") << QString() << QString()
- << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign binding of type string to int") } } };
QTest::newRow("badAttachedPropertyTypeQtObject")
<< QStringLiteral("badAttachedPropertyTypeQtObject.qml")
- << QString("Property \"count\" of type \"int\" is assigned an incompatible type "
- "\"QtObject\"")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Property \"count\" of type \"int\" is assigned an incompatible type "
+ "\"QtObject\"") } } };
// should succeed, but it does not:
- QTest::newRow("attachedPropertyAccess") << QStringLiteral("goodAttachedPropertyAccess.qml")
- << QString() << QString() << QString() << true;
+ QTest::newRow("attachedPropertyAccess")
+ << QStringLiteral("goodAttachedPropertyAccess.qml") << Result::clean();
// should succeed, but it does not:
- QTest::newRow("attachedPropertyNested") << QStringLiteral("goodAttachedPropertyNested.qml")
- << QString() << QString() << QString() << true;
+ QTest::newRow("attachedPropertyNested")
+ << QStringLiteral("goodAttachedPropertyNested.qml") << Result::clean();
QTest::newRow("deprecatedFunction")
<< QStringLiteral("deprecatedFunction.qml")
- << QStringLiteral("Method \"deprecated(foobar)\" is deprecated (Reason: No particular "
- "reason.)")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Method \"deprecated(foobar)\" is deprecated (Reason: No particular "
+ "reason.)") } } };
QTest::newRow("deprecatedFunctionInherited")
<< QStringLiteral("deprecatedFunctionInherited.qml")
- << QStringLiteral("Method \"deprecatedInherited(c, d)\" is deprecated (Reason: This "
- "deprecation should be visible!)")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Method \"deprecatedInherited(c, d)\" is deprecated (Reason: This "
+ "deprecation should be visible!)") } } };
QTest::newRow("duplicated id")
- << QStringLiteral("duplicateId.qml")
- << QStringLiteral("Found a duplicated id. id root was first declared ")
- << QString() << QString() << false;
+ << QStringLiteral("duplicateId.qml")
+ << Result { { Message {
+ QStringLiteral("Found a duplicated id. id root was first declared ") } } };
QTest::newRow("string as id") << QStringLiteral("stringAsId.qml")
- << QStringLiteral("ids do not need quotation marks") << QString()
- << QString() << false;
- QTest::newRow("stringIdUsedInWarning") << QStringLiteral("stringIdUsedInWarning.qml")
- << QStringLiteral("i is a member of a parent element")
- << QString() << QStringLiteral("stringy.") << false;
+ << Result { { Message { QStringLiteral(
+ "ids do not need quotation marks") } } };
+ QTest::newRow("stringIdUsedInWarning")
+ << QStringLiteral("stringIdUsedInWarning.qml")
+ << Result { { Message {
+ QStringLiteral("i is a member of a parent element"),
+ } },
+ {},
+ { Message { QStringLiteral("stringy.") } } };
QTest::newRow("Invalid id (expression)")
- << QStringLiteral("invalidId1.qml") << QStringLiteral("Failed to parse id") << QString()
- << QString() << false;
+ << QStringLiteral("invalidId1.qml")
+ << Result { { Message { QStringLiteral("Failed to parse id") } } };
QTest::newRow("multilineString")
<< QStringLiteral("multilineString.qml")
- << QStringLiteral("String contains unescaped line terminator which is deprecated. Use "
- "a template literal instead.")
- << QString() << QString() << true;
+ << Result { { Message { QStringLiteral("String contains unescaped line terminator "
+ "which is deprecated."),
+ 0, 0, QtInfoMsg } },
+ {},
+ {},
+ Result::ExitsNormally };
+ QTest::newRow("multilineStringTortureQuote")
+ << QStringLiteral("multilineStringTortureQuote.qml")
+ << Result { { Message { QStringLiteral("String contains unescaped line terminator which is deprecated."), 0, 0, QtInfoMsg }}, {}, {Message {R"(`
+ quote: " \\" \\\\"
+ ticks: \` \` \\\` \\\`
+ singleTicks: ' \' \\' \\\'
+ expression: \${expr} \${expr} \\\${expr} \\\${expr}
+ `)"}}, Result::ExitsNormally };
+ QTest::newRow("multilineStringTortureTick")
+ << QStringLiteral("multilineStringTortureTick.qml")
+ << Result { { Message { QStringLiteral("String contains unescaped line terminator which is deprecated."), 0, 0, QtInfoMsg } }, {}, {Message {
+ R"(`
+ quote: " \" \\" \\\"
+ ticks: \` \` \\\` \\\`
+ singleTicks: ' \\' \\\\'
+ expression: \${expr} \${expr} \\\${expr} \\\${expr}
+ `)"
+}}, Result::ExitsNormally};
QTest::newRow("unresolvedType")
<< QStringLiteral("unresolvedType.qml")
- << QStringLiteral("UnresolvedType was not found. Did you add all import paths?")
- << QStringLiteral("incompatible type") << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "UnresolvedType was not found. Did you add all import paths?") } },
+ { Message { QStringLiteral("incompatible type") } } };
QTest::newRow("invalidInterceptor")
<< QStringLiteral("invalidInterceptor.qml")
- << QStringLiteral("On-binding for property \"angle\" has wrong type \"Item\"")
- << QString() << QString() << false;
- QTest::newRow("2Interceptors") << QStringLiteral("2interceptors.qml")
- << QStringLiteral("Duplicate interceptor on property \"x\"")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "On-binding for property \"angle\" has wrong type \"Item\"") } } };
+ QTest::newRow("2Interceptors")
+ << QStringLiteral("2interceptors.qml")
+ << Result { { Message { QStringLiteral("Duplicate interceptor on property \"x\"") } } };
QTest::newRow("ValueSource+2Interceptors")
<< QStringLiteral("valueSourceBetween2interceptors.qml")
- << QStringLiteral("Duplicate interceptor on property \"x\"") << QString() << QString()
- << false;
+ << Result { { Message { QStringLiteral("Duplicate interceptor on property \"x\"") } } };
QTest::newRow("2ValueSources") << QStringLiteral("2valueSources.qml")
- << QStringLiteral("Duplicate value source on property \"x\"")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Duplicate value source on property \"x\"") } } };
QTest::newRow("ValueSource+Value")
<< QStringLiteral("valueSource_Value.qml")
- << QStringLiteral("Cannot combine value source and binding on property \"obj\"")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Cannot combine value source and binding on property \"obj\"") } } };
QTest::newRow("ValueSource+ListValue")
<< QStringLiteral("valueSource_listValue.qml")
- << QStringLiteral("Cannot combine value source and binding on property \"objs\"")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Cannot combine value source and binding on property \"objs\"") } } };
QTest::newRow("NonExistentListProperty")
<< QStringLiteral("nonExistentListProperty.qml")
- << QStringLiteral("Property \"objs\" is invalid or does not exist") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Property \"objs\" is invalid or does not exist") } } };
QTest::newRow("QtQuick.Window 2.0")
<< QStringLiteral("qtquickWindow20.qml")
- << QStringLiteral("Property \"window\" not found on type \"QQuickWindow\"") << QString()
- << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Property \"window\" not found on type \"QQuickWindow\"") } } };
QTest::newRow("unresolvedAttachedType")
<< QStringLiteral("unresolvedAttachedType.qml")
- << QStringLiteral("unknown attached property scope UnresolvedAttachedType.")
- << QStringLiteral("Property \"property\" is invalid or does not exist") << QString()
- << false;
+ << Result { { Message { QStringLiteral(
+ "unknown attached property scope UnresolvedAttachedType.") } },
+ { Message { QStringLiteral(
+ "Property \"property\" is invalid or does not exist") } } };
QTest::newRow("nestedInlineComponents")
<< QStringLiteral("nestedInlineComponents.qml")
- << QStringLiteral("Nested inline components are not supported") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Nested inline components are not supported") } } };
QTest::newRow("WithStatement") << QStringLiteral("WithStatement.qml")
- << QStringLiteral("with statements are strongly discouraged")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "with statements are strongly discouraged") } } };
QTest::newRow("BindingTypeMismatch")
<< QStringLiteral("bindingTypeMismatch.qml")
- << QStringLiteral("Cannot assign binding of type QString to int") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign binding of type QString to int") } } };
QTest::newRow("BindingTypeMismatchFunction")
<< QStringLiteral("bindingTypeMismatchFunction.qml")
- << QStringLiteral("Cannot assign binding of type QString to int") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign binding of type QString to int") } } };
QTest::newRow("BadLiteralBinding")
<< QStringLiteral("badLiteralBinding.qml")
- << QStringLiteral("Cannot assign binding of type string to int") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign binding of type string to int") } } };
QTest::newRow("BadLiteralBindingDate")
<< QStringLiteral("badLiteralBindingDate.qml")
- << QStringLiteral("Cannot assign binding of type QString to QDateTime") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign binding of type QString to QDateTime") } } };
QTest::newRow("BadModulePrefix")
<< QStringLiteral("badModulePrefix.qml")
- << QStringLiteral("Cannot load singleton as property of object") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot load singleton as property of object") } } };
QTest::newRow("BadModulePrefix2")
<< QStringLiteral("badModulePrefix2.qml")
- << QStringLiteral("Cannot use non-reference type QRectF as base "
- "of namespaced attached type")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral("Cannot use non-reference type QRectF as base "
+ "of namespaced attached type") } } };
QTest::newRow("AssignToReadOnlyProperty")
<< QStringLiteral("assignToReadOnlyProperty.qml")
- << QStringLiteral("Cannot assign to read-only property activeFocus") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign to read-only property activeFocus") } } };
QTest::newRow("AssignToReadOnlyProperty")
<< QStringLiteral("assignToReadOnlyProperty2.qml")
- << QStringLiteral("Cannot assign to read-only property activeFocus") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign to read-only property activeFocus") } } };
QTest::newRow("DeferredPropertyID")
<< QStringLiteral("deferredPropertyID.qml")
- << QStringLiteral(
+ << Result { { Message { QStringLiteral(
"Cannot defer property assignment to "
"\"contentData\". Assigning an id to an object or one of its sub-objects "
- "bound to a deferred property will make the assignment immediate.")
- << QString() << QString() << false;
+ "bound to a deferred property will make the assignment immediate.") } } };
QTest::newRow("DeferredPropertyNestedID")
<< QStringLiteral("deferredPropertyNestedID.qml")
- << QStringLiteral(
+ << Result { { Message { QStringLiteral(
"Cannot defer property assignment to "
"\"contentData\". Assigning an id to an object or one of its sub-objects "
- "bound to a deferred property will make the assignment immediate.")
- << QString() << QString() << false;
+ "bound to a deferred property will make the assignment immediate.") } } };
QTest::newRow("cachedDependency")
- << QStringLiteral("cachedDependency.qml") << QStringLiteral("Unused import at %1:1:1")
- << QStringLiteral("Cannot assign binding of type QQuickItem to QObject") << QString()
- << true;
+ << QStringLiteral("cachedDependency.qml")
+ << Result { { Message { QStringLiteral("Unused import at"), 1, 1, QtInfoMsg } },
+ { Message { QStringLiteral(
+ "Cannot assign binding of type QQuickItem to QObject") } },
+ {},
+ Result::ExitsNormally };
QTest::newRow("cycle in import")
<< QStringLiteral("cycleHead.qml")
- << QStringLiteral("MenuItem is part of an inheritance cycle: MenuItem -> MenuItem")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "MenuItem is part of an inheritance cycle: MenuItem -> MenuItem") } } };
QTest::newRow("badGeneralizedGroup1")
<< QStringLiteral("badGeneralizedGroup1.qml")
- << QStringLiteral("Binding assigned to \"aaaa\", "
- "but no property \"aaaa\" exists in the current element")
- << QString() << QString() << false;
- QTest::newRow("badGeneralizedGroup2") << QStringLiteral("badGeneralizedGroup2.qml")
- << QStringLiteral("unknown grouped property scope aself")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Binding assigned to \"aaaa\", "
+ "but no property \"aaaa\" exists in the current element") } } };
+ QTest::newRow("badGeneralizedGroup2")
+ << QStringLiteral("badGeneralizedGroup2.qml")
+ << Result { { Message { QStringLiteral("unknown grouped property scope aself") } } };
QTest::newRow("missingQmltypes")
<< QStringLiteral("missingQmltypes.qml")
- << QStringLiteral("QML types file does not exist") << QString() << QString() << false;
- QTest::newRow("enumInvalid") << QStringLiteral(
- "enumInvalid.qml") << QStringLiteral("Property \"red\" not found on type \"QtObject\"")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral("QML types file does not exist") } } };
+ QTest::newRow("enumInvalid")
+ << QStringLiteral("enumInvalid.qml")
+ << Result { { Message {
+ QStringLiteral("Property \"red\" not found on type \"QtObject\"") } } };
QTest::newRow("inaccessibleId")
<< QStringLiteral("inaccessibleId.qml")
- << QStringLiteral("Property \"objectName\" not found on type \"int\"") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Property \"objectName\" not found on type \"int\"") } } };
QTest::newRow("inaccessibleId2")
<< QStringLiteral("inaccessibleId2.qml")
- << QStringLiteral("Property \"objectName\" not found on type \"int\"") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Property \"objectName\" not found on type \"int\"") } } };
QTest::newRow("unknownTypeCustomParser")
<< QStringLiteral("unknownTypeCustomParser.qml")
- << QStringLiteral("TypeDoesNotExist was not found.") << QString() << QString() << false;
+ << Result { { Message { QStringLiteral("TypeDoesNotExist was not found.") } } };
QTest::newRow("nonNullStored")
<< QStringLiteral("nonNullStored.qml")
- << QStringLiteral("Property \"objectName\" not found on type \"Foozle\"")
- << QStringLiteral("Unqualified access")
- << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Property \"objectName\" not found on type \"Foozle\"") } },
+ { Message { QStringLiteral("Unqualified access") } } };
QTest::newRow("cppPropertyChangeHandlers-wrong-parameters-size-bindable")
<< QStringLiteral("badCppPropertyChangeHandlers1.qml")
- << QStringLiteral("Signal handler for \"onAChanged\" has more formal parameters than "
- "the signal it handles")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Signal handler for \"onAChanged\" has more formal parameters than "
+ "the signal it handles") } } };
QTest::newRow("cppPropertyChangeHandlers-wrong-parameters-size-notify")
<< QStringLiteral("badCppPropertyChangeHandlers2.qml")
- << QStringLiteral("Signal handler for \"onBChanged\" has more formal parameters than "
- "the signal it handles")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Signal handler for \"onBChanged\" has more formal parameters than "
+ "the signal it handles") } } };
QTest::newRow("cppPropertyChangeHandlers-no-property")
<< QStringLiteral("badCppPropertyChangeHandlers3.qml")
- << QStringLiteral("no matching signal found for handler \"onXChanged\"") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("no matching signal found for handler \"onXChanged\"") } } };
QTest::newRow("cppPropertyChangeHandlers-not-a-signal")
<< QStringLiteral("badCppPropertyChangeHandlers4.qml")
- << QStringLiteral("no matching signal found for handler \"onWannabeSignal\"")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "no matching signal found for handler \"onWannabeSignal\"") } } };
QTest::newRow("didYouMean(binding)")
<< QStringLiteral("didYouMeanBinding.qml")
- << QStringLiteral("Binding assigned to \"witdh\", but no property \"witdh\" exists in "
- "the current element.")
- << QString() << QStringLiteral("width") << false;
+ << Result {
+ { Message { QStringLiteral(
+ "Binding assigned to \"witdh\", but no property \"witdh\" exists in "
+ "the current element.") } },
+ {},
+ { Message { QStringLiteral("width") } }
+ };
QTest::newRow("didYouMean(unqualified)")
- << QStringLiteral("didYouMeanUnqualified.qml") << QStringLiteral("Unqualified access")
- << QString() << QStringLiteral("height") << false;
+ << QStringLiteral("didYouMeanUnqualified.qml")
+ << Result { { Message { QStringLiteral("Unqualified access") } },
+ {},
+ { Message { QStringLiteral("height") } } };
QTest::newRow("didYouMean(unqualifiedCall)")
<< QStringLiteral("didYouMeanUnqualifiedCall.qml")
- << QStringLiteral("Unqualified access") << QString() << QStringLiteral("func") << false;
+ << Result { { Message { QStringLiteral("Unqualified access") } },
+ {},
+ { Message { QStringLiteral("func") } } };
QTest::newRow("didYouMean(property)")
<< QStringLiteral("didYouMeanProperty.qml")
- << QStringLiteral("Property \"hoight\" not found on type \"Rectangle\"") << QString()
- << QStringLiteral("height") << false;
+ << Result { { Message { QStringLiteral(
+ "Property \"hoight\" not found on type \"Rectangle\"") },
+ {},
+ { Message { QStringLiteral("height") } } } };
QTest::newRow("didYouMean(propertyCall)")
<< QStringLiteral("didYouMeanPropertyCall.qml")
- << QStringLiteral("Property \"lgg\" not found on type \"Console\"") << QString()
- << QStringLiteral("log") << false;
+ << Result {
+ { Message { QStringLiteral("Property \"lgg\" not found on type \"Console\"") },
+ {},
+ { Message { QStringLiteral("log") } } }
+ };
QTest::newRow("didYouMean(component)")
<< QStringLiteral("didYouMeanComponent.qml")
- << QStringLiteral("Itym was not found. Did you add all import paths?") << QString()
- << QStringLiteral("Item") << false;
+ << Result { { Message { QStringLiteral(
+ "Itym was not found. Did you add all import paths?") },
+ {},
+ { Message { QStringLiteral("Item") } } } };
QTest::newRow("nullBinding")
<< QStringLiteral("nullBinding.qml")
- << QStringLiteral("Cannot assign binding of type $internal$.std::nullptr_t to double")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Cannot assign binding of type $internal$.std::nullptr_t to double") } } };
QTest::newRow("nullBindingFunction")
<< QStringLiteral("nullBindingFunction.qml")
- << QStringLiteral("Cannot assign binding of type std::nullptr_t to double") << QString()
- << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Cannot assign binding of type std::nullptr_t to double") } } };
QTest::newRow("missingRequiredAlias")
<< QStringLiteral("missingRequiredAlias.qml")
- << QStringLiteral("Component is missing required property requiredAlias from "
- "RequiredWithRootLevelAlias")
- << QString() << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Component is missing required property requiredAlias from "
+ "RequiredWithRootLevelAlias") } } };
QTest::newRow("missingSingletonPragma")
<< QStringLiteral("missingSingletonPragma.qml")
- << QStringLiteral("Type MissingPragma declared as singleton in qmldir but missing "
- "pragma Singleton")
- << QString() << QString() << false;
+ << Result { { Message { QStringLiteral(
+ "Type MissingPragma declared as singleton in qmldir but missing "
+ "pragma Singleton") } } };
QTest::newRow("missingSingletonQmldir")
<< QStringLiteral("missingSingletonQmldir.qml")
- << QStringLiteral(
+ << Result { { Message { QStringLiteral(
"Type MissingQmldirSingleton not declared as singleton in qmldir but using "
- "pragma Singleton")
- << QString() << QString() << false;
+ "pragma Singleton") } } };
QTest::newRow("jsVarDeclarationsWriteConst")
<< QStringLiteral("jsVarDeclarationsWriteConst.qml")
- << QStringLiteral("Cannot assign to read-only property constProp") << QString()
- << QString() << false;
+ << Result { { Message {
+ QStringLiteral("Cannot assign to read-only property constProp") } } };
+ QTest::newRow("shadowedSignal")
+ << QStringLiteral("shadowedSignal.qml")
+ << Result { { Message {
+ QStringLiteral("Signal \"pressed\" is shadowed by a property.") } } };
+ QTest::newRow("shadowedSignalWithId")
+ << QStringLiteral("shadowedSignalWithId.qml")
+ << Result { { Message {
+ QStringLiteral("Signal \"pressed\" is shadowed by a property") } } };
+ QTest::newRow("shadowedSlot") << QStringLiteral("shadowedSlot.qml")
+ << Result { { Message { QStringLiteral(
+ "Slot \"move\" is shadowed by a property") } } };
+ QTest::newRow("shadowedMethod") << QStringLiteral("shadowedMethod.qml")
+ << Result { { Message { QStringLiteral(
+ "Method \"foo\" is shadowed by a property.") } } };
+ QTest::newRow("callVarProp")
+ << QStringLiteral("callVarProp.qml")
+ << Result { { Message { QStringLiteral(
+ "Property \"foo\" is a variant property. It may or may not be a "
+ "method. Use a regular function instead.") } } };
+ QTest::newRow("callJSValue")
+ << QStringLiteral("callJSValueProp.qml")
+ << Result { { Message { QStringLiteral(
+ "Property \"callLater\" is a QJSValue property. It may or may not be "
+ "a method. Use a regular Q_INVOKABLE instead.") } } };
}
void TestQmllint::dirtyQmlCode()
{
QFETCH(QString, filename);
- QFETCH(QString, warningMessage);
- QFETCH(QString, notContained);
- QFETCH(QString, replacement);
- QFETCH(bool, exitsNormally);
-
- if (warningMessage.contains(QLatin1String("%1")))
- warningMessage = warningMessage.arg(testFile(filename));
+ QFETCH(Result, result);
QJsonArray warnings;
@@ -881,28 +990,21 @@ void TestQmllint::dirtyQmlCode()
QEXPECT_FAIL("bad tranlsation binding (qsTr)", "We currently do not check translation binding",
Abort);
- callQmllint(filename, exitsNormally, &warnings);
-
- if (!warningMessage.isEmpty()) {
- // output.contains() expect fails:
- QEXPECT_FAIL("BadLiteralBindingDate",
- "We're currently not able to verify any non-trivial QString conversion that "
- "requires QQmlStringConverters",
- Abort);
-
- searchWarnings(warnings, warningMessage, filename);
- }
-
- if (!notContained.isEmpty()) {
- // !output.contains() expect fails:
- QEXPECT_FAIL("badAttachedPropertyNested", "We cannot discern between types and instances",
- Abort);
-
- searchWarnings(warnings, notContained, filename, StringNotContained);
- }
+ callQmllint(filename, result.flags.testFlag(Result::ExitsNormally), &warnings);
- if (!replacement.isEmpty())
- searchWarnings(warnings, replacement, filename, StringContained, DoReplacementSearch);
+ checkResult(
+ warnings, result,
+ [] {
+ QEXPECT_FAIL("BadLiteralBindingDate",
+ "We're currently not able to verify any non-trivial QString "
+ "conversion that "
+ "requires QQmlStringConverters",
+ Abort);
+ },
+ [] {
+ QEXPECT_FAIL("badAttachedPropertyNested",
+ "We cannot discern between types and instances", Abort);
+ });
}
void TestQmllint::cleanQmlCode_data()
@@ -938,7 +1040,7 @@ void TestQmllint::cleanQmlCode_data()
QTest::newRow("enumFromQtQml") << QStringLiteral("enumFromQtQml.qml");
QTest::newRow("anchors1") << QStringLiteral("anchors1.qml");
QTest::newRow("anchors2") << QStringLiteral("anchors2.qml");
- QTest::newRow("optionalImport") << QStringLiteral("optionalImport.qml");
+ QTest::newRow("defaultImport") << QStringLiteral("defaultImport.qml");
QTest::newRow("goodAliasObject") << QStringLiteral("goodAliasObject.qml");
QTest::newRow("jsmoduleimport") << QStringLiteral("jsmoduleimport.qml");
QTest::newRow("overridescript") << QStringLiteral("overridescript.qml");
@@ -1021,6 +1123,7 @@ void TestQmllint::cleanQmlCode_data()
QTest::newRow("unexportedCppBase") << QStringLiteral("unexportedCppBase.qml");
QTest::newRow("requiredWithRootLevelAlias") << QStringLiteral("RequiredWithRootLevelAlias.qml");
QTest::newRow("jsVarDeclarations") << QStringLiteral("jsVarDeclarations.qml");
+ QTest::newRow("qmodelIndex") << QStringLiteral("qmodelIndex.qml");
}
void TestQmllint::cleanQmlCode()
@@ -1029,45 +1132,49 @@ void TestQmllint::cleanQmlCode()
QJsonArray warnings;
- callQmllint(filename, true, &warnings);
- QVERIFY2(warnings.isEmpty(), qPrintable(QJsonDocument(warnings).toJson()));
+ runTest(filename, Result::clean());
}
void TestQmllint::compilerWarnings_data()
{
QTest::addColumn<QString>("filename");
- QTest::addColumn<bool>("shouldSucceed");
- QTest::addColumn<QString>("warning");
+ QTest::addColumn<Result>("result");
QTest::addColumn<bool>("enableCompilerWarnings");
- QTest::newRow("listIndices") << QStringLiteral("listIndices.qml") << true << QString() << true;
+ QTest::newRow("listIndices") << QStringLiteral("listIndices.qml") << Result::clean() << true;
QTest::newRow("lazyAndDirect")
- << QStringLiteral("LazyAndDirect/Lazy.qml") << true << QString() << true;
- QTest::newRow("qQmlV4Function") << QStringLiteral("varargs.qml") << true << QString() << true;
- QTest::newRow("multiGrouped") << QStringLiteral("multiGrouped.qml") << true << QString()
- << true;
-
- QTest::newRow("shadowable") << QStringLiteral("shadowable.qml") << false
- << QStringLiteral("with type NotSoSimple can be shadowed") << true;
- QTest::newRow("tooFewParameters") << QStringLiteral("tooFewParams.qml") << false
- << QStringLiteral("No matching override found") << true;
+ << QStringLiteral("LazyAndDirect/Lazy.qml") << Result::clean() << true;
+ QTest::newRow("qQmlV4Function") << QStringLiteral("varargs.qml") << Result::clean() << true;
+ QTest::newRow("multiGrouped") << QStringLiteral("multiGrouped.qml") << Result::clean() << true;
+
+ QTest::newRow("shadowable") << QStringLiteral("shadowable.qml")
+ << Result { { Message { QStringLiteral(
+ "with type NotSoSimple can be shadowed") } } }
+ << true;
+ QTest::newRow("tooFewParameters")
+ << QStringLiteral("tooFewParams.qml")
+ << Result { { Message { QStringLiteral("No matching override found") } } } << true;
QTest::newRow("javascriptVariableArgs")
- << QStringLiteral("javascriptVariableArgs.qml") << false
- << QStringLiteral("Function expects 0 arguments, but 2 were provided") << true;
+ << QStringLiteral("javascriptVariableArgs.qml")
+ << Result { { Message {
+ QStringLiteral("Function expects 0 arguments, but 2 were provided") } } }
+ << true;
QTest::newRow("unknownTypeInRegister")
- << QStringLiteral("unknownTypeInRegister.qml") << false
- << QStringLiteral("Functions without type annotations won't be compiled") << true;
- QTest::newRow("pragmaStrict") << QStringLiteral("pragmaStrict.qml") << true
- << QStringLiteral(
- "Functions without type annotations won't be compiled")
- << false;
+ << QStringLiteral("unknownTypeInRegister.qml")
+ << Result { { Message {
+ QStringLiteral("Functions without type annotations won't be compiled") } } }
+ << true;
+ QTest::newRow("pragmaStrict")
+ << QStringLiteral("pragmaStrict.qml")
+ << Result { { { QStringLiteral(
+ "Functions without type annotations won't be compiled") } } }
+ << true;
}
void TestQmllint::compilerWarnings()
{
QFETCH(QString, filename);
- QFETCH(bool, shouldSucceed);
- QFETCH(QString, warning);
+ QFETCH(Result, result);
QFETCH(bool, enableCompilerWarnings);
QJsonArray warnings;
@@ -1077,49 +1184,48 @@ void TestQmllint::compilerWarnings()
if (enableCompilerWarnings)
options[u"compiler"_qs].setLevel(u"warning"_qs);
- callQmllint(filename, shouldSucceed, &warnings, {}, {}, {}, UseDefaultImports, &options);
-
- if (!warning.isEmpty())
- searchWarnings(warnings, warning, filename);
+ runTest(filename, result, {}, {}, {}, UseDefaultImports, &options);
}
void TestQmllint::controlsSanity_data()
{
QTest::addColumn<QString>("filename");
- QTest::addColumn<QString>("warning");
- QTest::newRow("functionDeclarations") << QStringLiteral("functionDeclarations.qml")
- << QStringLiteral("Declared function \"add\"");
- QTest::newRow("signalHandlers") << QStringLiteral("signalHandlers.qml")
- << QStringLiteral("Declared signal handler \"onCompleted\"");
+ QTest::addColumn<Result>("result");
+ QTest::newRow("functionDeclarations")
+ << QStringLiteral("functionDeclarations.qml")
+ << Result { { Message { QStringLiteral("Declared function \"add\"") } } };
+ QTest::newRow("signalHandlers")
+ << QStringLiteral("signalHandlers.qml")
+ << Result { { Message { QStringLiteral("Declared signal handler \"onCompleted\"") } } };
QTest::newRow("anchors") << QStringLiteral("anchors.qml")
- << QStringLiteral("Using anchors here");
+ << Result { { Message { QStringLiteral("Using anchors here") } } };
}
void TestQmllint::controlsSanity()
{
QFETCH(QString, filename);
- QFETCH(QString, warning);
+ QFETCH(Result, result);
QJsonArray warnings;
auto options = QQmlJSLogger::options();
options[u"controls-sanity"_qs].setLevel(u"warning"_qs);
- callQmllint(filename, false, &warnings, {}, {}, {}, UseDefaultImports, &options);
-
- if (!warning.isEmpty())
- searchWarnings(warnings, warning, filename);
+ runTest(filename, result, {}, {}, {}, UseDefaultImports, &options);
}
QString TestQmllint::runQmllint(const QString &fileToLint,
std::function<void(QProcess &)> handleResult,
const QStringList &extraArgs, bool ignoreSettings,
- bool addImportDirs)
+ bool addImportDirs, bool absolutePath)
{
auto qmlImportDir = QLibraryInfo::path(QLibraryInfo::QmlImportsPath);
QStringList args;
- args << (QFileInfo(fileToLint).isAbsolute() ? fileToLint : testFile(fileToLint));
+ QString absoluteFilePath =
+ QFileInfo(fileToLint).isAbsolute() ? fileToLint : testFile(fileToLint);
+
+ args << QFileInfo(absoluteFilePath).fileName();
if (addImportDirs) {
args << QStringLiteral("-I") << qmlImportDir
@@ -1127,13 +1233,17 @@ QString TestQmllint::runQmllint(const QString &fileToLint,
}
if (ignoreSettings)
- QStringLiteral("--ignore-settings");
+ args << QStringLiteral("--ignore-settings");
+
+ if (absolutePath)
+ args << QStringLiteral("--absolute-path");
args << extraArgs;
args << QStringLiteral("--silent");
QString errors;
auto verify = [&](bool isSilent) {
QProcess process;
+ process.setWorkingDirectory(QFileInfo(absoluteFilePath).absolutePath());
process.start(m_qmllintPath, args);
handleResult(process);
errors = process.readAllStandardError();
@@ -1175,7 +1285,7 @@ QString TestQmllint::runQmllint(const QString &fileToLint,
QString TestQmllint::runQmllint(const QString &fileToLint, bool shouldSucceed,
const QStringList &extraArgs, bool ignoreSettings,
- bool addImportDirs)
+ bool addImportDirs, bool absolutePath)
{
return runQmllint(
fileToLint,
@@ -1188,7 +1298,7 @@ QString TestQmllint::runQmllint(const QString &fileToLint, bool shouldSucceed,
else
QVERIFY(process.exitCode() != 0);
},
- extraArgs, ignoreSettings, addImportDirs);
+ extraArgs, ignoreSettings, addImportDirs, absolutePath);
}
void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJsonArray *warnings,
@@ -1214,44 +1324,112 @@ void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJs
QCOMPARE(success, shouldSucceed);
}
+void TestQmllint::runTest(const QString &testFile, const Result &result, QStringList importDirs,
+ QStringList qmltypesFiles, QStringList resources,
+ DefaultImportOption defaultImports,
+ QMap<QString, QQmlJSLogger::Option> *options)
+{
+ QJsonArray warnings;
+ callQmllint(testFile, result.flags.testFlag(Result::Flag::ExitsNormally), &warnings, importDirs,
+ qmltypesFiles, resources, defaultImports, options);
+ checkResult(warnings, result);
+}
+
+template<typename ExpectedMessageFailureHandler, typename BadMessageFailureHandler>
+void TestQmllint::checkResult(const QJsonArray &warnings, const Result &result,
+ ExpectedMessageFailureHandler onExpectedMessageFailures,
+ BadMessageFailureHandler onBadMessageFailures)
+{
+ if (result.flags.testFlag(Result::Flag::NoMessages))
+ QVERIFY2(warnings.isEmpty(), qPrintable(QJsonDocument(warnings).toJson()));
+
+ for (const Message &msg : result.expectedMessages) {
+ // output.contains() expect fails:
+ onExpectedMessageFailures();
+
+ searchWarnings(warnings, msg.text, msg.severity, msg.line, msg.column);
+ }
+
+ for (const Message &msg : result.badMessages) {
+ // !output.contains() expect fails:
+ onBadMessageFailures();
+
+ searchWarnings(warnings, msg.text, msg.severity, msg.line, msg.column, StringNotContained);
+ }
+
+ for (const Message &replacement : result.expectedReplacements) {
+ searchWarnings(warnings, replacement.text, replacement.severity, replacement.line,
+ replacement.column, StringContained, DoReplacementSearch);
+ }
+}
+
void TestQmllint::searchWarnings(const QJsonArray &warnings, const QString &substring,
- const QString &filename, ContainOption shouldContain,
- ReplacementOption searchReplacements)
+ QtMsgType type, quint32 line, quint32 column,
+ ContainOption shouldContain, ReplacementOption searchReplacements)
{
bool contains = false;
- auto toDisplayWarningType = [](const QString &warningType) {
- return warningType.first(1).toUpper() + warningType.mid(1);
+ auto typeStringToMsgType = [](const QString &type) -> QtMsgType {
+ if (type == u"debug")
+ return QtDebugMsg;
+ if (type == u"info")
+ return QtInfoMsg;
+ if (type == u"warning")
+ return QtWarningMsg;
+ if (type == u"critical")
+ return QtCriticalMsg;
+ if (type == u"fatal")
+ return QtFatalMsg;
+
+ Q_UNREACHABLE();
};
for (const QJsonValue &warning : warnings) {
- // We're currently recreating the output that the logger would write to the console,
- // so we can keep using our existing test data without modification.
- // In the future our test data should be replaced with a structured representation of the
- // warning it expects, possibly as a QQmlJS::DiagnosticMessage.
- const QString warningMessage =
- u"%1: %2:%3 %4"_qs
- .arg(toDisplayWarningType(warning[u"type"].toString()), testFile(filename))
- .arg(warning[u"line"].isUndefined()
- ? u""_qs
- : u"%1:%2:"_qs.arg(warning[u"line"].toInt())
- .arg(warning[u"column"].toInt()))
- .arg(warning[u"message"].toString());
+ QString warningMessage = warning[u"message"].toString();
+ quint32 warningLine = warning[u"line"].toInt();
+ quint32 warningColumn = warning[u"column"].toInt();
+ QtMsgType warningType = typeStringToMsgType(warning[u"type"].toString());
+
if (warningMessage.contains(substring)) {
+ if (warningType != type) {
+ continue;
+ }
+ if (line != 0 || column != 0) {
+ if (warningLine != line || warningColumn != column) {
+ continue;
+ }
+ }
+
contains = true;
break;
}
for (const QJsonValue &fix : warning[u"suggestions"].toArray()) {
- const QString jsonFixMessage = u"Info: "_qs + fix[u"message"].toString();
- if (jsonFixMessage.contains(substring)) {
+ const QString fixMessage = fix[u"message"].toString();
+ if (fixMessage.contains(substring)) {
contains = true;
break;
}
- if (searchReplacements == DoReplacementSearch
- && fix[u"replacement"].toString().contains(substring)) {
- contains = true;
- break;
+
+ if (searchReplacements == DoReplacementSearch) {
+ QString replacement = fix[u"replacement"].toString();
+#ifdef Q_OS_WIN
+ // Replacements can contain native line endings
+ // but we need them to be uniform in order for them to conform to our test data
+ replacement = replacement.replace(u"\r\n"_qs, u"\n"_qs);
+#endif
+
+ if (replacement.contains(substring)) {
+ quint32 fixLine = fix[u"line"].toInt();
+ quint32 fixColumn = fix[u"column"].toInt();
+ if (line != 0 || column != 0) {
+ if (fixLine != line || fixColumn != column) {
+ continue;
+ }
+ }
+ contains = true;
+ break;
+ }
}
}
}
@@ -1275,56 +1453,26 @@ void TestQmllint::searchWarnings(const QJsonArray &warnings, const QString &subs
void TestQmllint::requiredProperty()
{
- {
- QJsonArray warnings;
- callQmllint("requiredProperty.qml", true, &warnings);
- QVERIFY2(warnings.isEmpty(), qPrintable(QJsonDocument(warnings).toJson()));
- }
-
- {
- QJsonArray warnings;
- callQmllint("requiredMissingProperty.qml", false, &warnings);
- searchWarnings(
- warnings,
- QStringLiteral("Property \"foo\" was marked as required but does not exist."),
- "requiredMissingProperty.qml");
- }
-
- {
- QJsonArray warnings;
- callQmllint("requiredPropertyBindings.qml", true, &warnings);
- QVERIFY2(warnings.isEmpty(), qPrintable(QJsonDocument(warnings).toJson()));
- }
-
- {
- QJsonArray warnings;
- callQmllint("requiredPropertyBindingsNow.qml", false, &warnings);
-
- searchWarnings(
- warnings,
- QStringLiteral(
- "Component is missing required property required_now_string from Base"),
- "requiredPropertyBindingsNow.qml");
- searchWarnings(warnings,
- QStringLiteral("Component is missing required property "
- "required_defined_here_string from here"),
- "requiredPropertyBindingsNow.qml");
- }
-
- {
- QJsonArray warnings;
- callQmllint("requiredPropertyBindingsLater.qml", false, &warnings);
- searchWarnings(
- warnings,
- QStringLiteral("Component is missing required property required_later_string from "
- "Base (marked as required by Derived)"),
- "requiredPropertyBindingsLater.qml");
- searchWarnings(
- warnings,
- QStringLiteral("Component is missing required property required_even_later_string "
- "from Base (marked as required by here)"),
- "requiredPropertyBindingsLater.qml");
- }
+ runTest("requiredProperty.qml", Result::clean());
+
+ runTest("requiredMissingProperty.qml",
+ Result { { Message { QStringLiteral(
+ "Property \"foo\" was marked as required but does not exist.") } } });
+
+ runTest("requiredPropertyBindings.qml", Result::clean());
+ runTest("requiredPropertyBindingsNow.qml",
+ Result { { Message { QStringLiteral("Component is missing required property "
+ "required_now_string from Base") },
+ Message { QStringLiteral("Component is missing required property "
+ "required_defined_here_string from here") } } });
+ runTest("requiredPropertyBindingsLater.qml",
+ Result { { Message { QStringLiteral("Component is missing required property "
+ "required_later_string from "
+ "Base") },
+ Message { QStringLiteral("Property marked as required in Derived") },
+ Message { QStringLiteral("Component is missing required property "
+ "required_even_later_string "
+ "from Base (marked as required by here)") } } });
}
void TestQmllint::settingsFile()
@@ -1332,7 +1480,7 @@ void TestQmllint::settingsFile()
QVERIFY(runQmllint("settings/unqualifiedSilent/unqualified.qml", true, QStringList(), false)
.isEmpty());
QVERIFY(runQmllint("settings/unusedImportWarning/unused.qml", false, QStringList(), false)
- .contains(QStringLiteral("Info: %1:2:1: Unused import at %1:2:1")
+ .contains(QStringLiteral("Warning: %1:2:1: Unused import at %1:2:1")
.arg(testFile("settings/unusedImportWarning/unused.qml"))));
QVERIFY(runQmllint("settings/bare/bare.qml", false, {}, false, false)
.contains(QStringLiteral("Failed to find the following builtins: "
@@ -1344,10 +1492,8 @@ void TestQmllint::settingsFile()
void TestQmllint::additionalImplicitImport()
{
- QJsonArray warnings;
- callQmllint("additionalImplicitImport.qml", true, &warnings, {}, {},
- { testFile("implicitImportResource.qrc") });
- QVERIFY(warnings.isEmpty());
+ runTest("additionalImplicitImport.qml", Result::clean(), {}, {},
+ { testFile("implicitImportResource.qrc") });
}
void TestQmllint::attachedPropertyReuse()
@@ -1355,24 +1501,13 @@ void TestQmllint::attachedPropertyReuse()
auto options = QQmlJSLogger::options();
options[u"multiple-attached-objects"_qs].setLevel(u"warning"_qs);
- {
- QJsonArray warnings;
-
- callQmllint("attachedPropNotReused.qml", false, &warnings, {}, {}, {}, UseDefaultImports,
- &options);
+ runTest("attachedPropNotReused.qml",
+ Result { { Message { QStringLiteral("Using attached type QQuickKeyNavigationAttached "
+ "already initialized in a parent "
+ "scope") } } },
+ {}, {}, {}, UseDefaultImports, &options);
- searchWarnings(warnings,
- QStringLiteral("Using attached type QQuickKeyNavigationAttached "
- "already initialized in a parent "
- "scope"),
- "attachedPropNotReused.qml");
- }
- {
- QJsonArray warnings;
- callQmllint("attachedPropEnum.qml", true, &warnings, {}, {}, {}, UseDefaultImports,
- &options);
- QVERIFY2(warnings.isEmpty(), qPrintable(QJsonDocument(warnings).toJson()));
- }
+ runTest("attachedPropEnum.qml", Result::clean(), {}, {}, {}, UseDefaultImports, &options);
}
void TestQmllint::missingBuiltinsNoCrash()
@@ -1391,34 +1526,24 @@ void TestQmllint::missingBuiltinsNoCrash()
QVERIFY2(jsonOutput.size() == 1, QJsonDocument(jsonOutput).toJson());
warnings = jsonOutput.at(0)[u"warnings"_qs].toArray();
- searchWarnings(warnings,
- QStringLiteral("Failed to find the following builtins: "
- "builtins.qmltypes, jsroot.qmltypes"),
- "missingBuiltinsNoCrash.qml");
+ checkResult(warnings,
+ Result { { Message { QStringLiteral("Failed to find the following builtins: "
+ "builtins.qmltypes, jsroot.qmltypes") } } });
}
void TestQmllint::absolutePath()
{
- // We cannot use the normal linter here since we need to set a different parameter in the
- // constructor
- QQmlJSLinter linter(m_defaultImportPaths, true);
-
+ QString absPathOutput = runQmllint("memberNotFound.qml", false, {}, true, true, true);
+ QString relPathOutput = runQmllint("memberNotFound.qml", false, {}, true, true, false);
const QString absolutePath = QFileInfo(testFile("memberNotFound.qml")).absoluteFilePath();
- QJsonArray jsonOutput;
- bool success = linter.lintFile(absolutePath, nullptr, true, &jsonOutput, {}, {}, {}, {});
- QVERIFY(!success);
- QVERIFY2(jsonOutput.size() == 1, QJsonDocument(jsonOutput).toJson());
- QJsonArray warnings = jsonOutput.at(0)[u"warnings"_qs].toArray();
-
- searchWarnings(warnings, absolutePath, absolutePath);
+ QVERIFY(absPathOutput.contains(absolutePath));
+ QVERIFY(!relPathOutput.contains(absolutePath));
}
void TestQmllint::importMultipartUri()
{
- QJsonArray warnings;
- callQmllint("here.qml", true, &warnings, {}, { testFile("Elsewhere/qmldir") });
- QVERIFY(warnings.isEmpty());
+ runTest("here.qml", Result::clean(), {}, { testFile("Elsewhere/qmldir") });
}
QTEST_MAIN(TestQmllint)
diff --git a/tests/auto/qml/qmltc/BLACKLIST b/tests/auto/qml/qmltc/BLACKLIST
new file mode 100644
index 0000000000..f8422a806a
--- /dev/null
+++ b/tests/auto/qml/qmltc/BLACKLIST
@@ -0,0 +1,2 @@
+[listView]
+qnx ci
diff --git a/tests/auto/qml/qmltc/data/CMakeLists.txt b/tests/auto/qml/qmltc/data/CMakeLists.txt
index 816164022e..c58378aa3f 100644
--- a/tests/auto/qml/qmltc/data/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/data/CMakeLists.txt
@@ -8,6 +8,8 @@ set(cpp_sources
cpptypes/private/testprivateproperty_p.h
cpptypes/typewithproperties.h cpptypes/typewithproperties.cpp
+ # deferred:
+ cpptypes/deferredpropertytypes.h cpptypes/deferredpropertytypes.cpp
)
set(qml_sources
@@ -65,6 +67,10 @@ set(qml_sources
privatePropertySubclass.qml
calqlatrBits.qml
propertyChangeAndSignalHandlers.qml
+ deferredProperties.qml
+ deferredProperties_group.qml
+ deferredProperties_attached.qml
+ deferredProperties_complex.qml
# support types:
DefaultPropertySingleChild.qml
@@ -108,6 +114,8 @@ qt6_add_qml_module(qmltc_test_module
QML_FILES
${qml_sources}
${js_sources}
+ DEPENDENCIES
+ QtQuick
)
qt_internal_target_compile_qml_to_cpp(qmltc_test_module
NAMESPACE QmltcTest
diff --git a/tests/auto/qml/qmltc/data/cpptypes/deferredpropertytypes.cpp b/tests/auto/qml/qmltc/data/cpptypes/deferredpropertytypes.cpp
new file mode 100644
index 0000000000..4f66172cca
--- /dev/null
+++ b/tests/auto/qml/qmltc/data/cpptypes/deferredpropertytypes.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "deferredpropertytypes.h"
+
+QQuickItem *TypeWithDeferredProperty::deferredProperty() const
+{
+ return m_deferredProperty;
+}
+
+void TypeWithDeferredProperty::setDeferredProperty(QQuickItem *value)
+{
+ if (m_deferredProperty != value)
+ m_deferredProperty = value;
+}
+
+QBindable<QQuickItem *> TypeWithDeferredProperty::bindableDeferredProperty()
+{
+ return QBindable<QQuickItem *>(&m_deferredProperty);
+}
+
+TestTypeAttachedWithDeferred *DeferredAttached::qmlAttachedProperties(QObject *parent)
+{
+ return new TestTypeAttachedWithDeferred(parent);
+}
diff --git a/tests/auto/qml/qmltc/data/cpptypes/deferredpropertytypes.h b/tests/auto/qml/qmltc/data/cpptypes/deferredpropertytypes.h
new file mode 100644
index 0000000000..24d7d46aaa
--- /dev/null
+++ b/tests/auto/qml/qmltc/data/cpptypes/deferredpropertytypes.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEFERREDPROPERTYTYPES_H
+#define DEFERREDPROPERTYTYPES_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qproperty.h>
+#include <QtQml/qqmlregistration.h>
+#include <QtQuick/qquickitem.h>
+
+#include "testgroupedtype.h"
+#include "testattachedtype.h"
+
+// normal properties:
+
+class TypeWithDeferredProperty : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_CLASSINFO("DeferredPropertyNames", "deferredProperty")
+
+ Q_PROPERTY(QQuickItem *deferredProperty READ deferredProperty WRITE setDeferredProperty BINDABLE
+ bindableDeferredProperty)
+
+ QProperty<QQuickItem *> m_deferredProperty { nullptr };
+
+public:
+ TypeWithDeferredProperty(QObject *parent = nullptr) : QObject(parent) { }
+
+ QQuickItem *deferredProperty() const;
+ void setDeferredProperty(QQuickItem *);
+ QBindable<QQuickItem *> bindableDeferredProperty();
+};
+
+// group properties:
+
+class TestTypeGroupedWithDeferred : public TestTypeGrouped
+{
+ Q_OBJECT
+ Q_PROPERTY(int deferred READ getDeferred WRITE setDeferred BINDABLE bindableDeferred)
+ QML_ANONYMOUS
+ Q_CLASSINFO("DeferredPropertyNames", "deferred")
+
+ QProperty<int> m_deferred { 0 };
+
+public:
+ int getDeferred() const { return m_deferred; }
+ void setDeferred(int v) { m_deferred = v; }
+ QBindable<int> bindableDeferred() const { return QBindable<int>(&m_deferred); }
+};
+
+class TypeWithDeferredGroup : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(TestTypeGroupedWithDeferred *group READ getGroup)
+
+ TestTypeGroupedWithDeferred m_group;
+
+public:
+ TypeWithDeferredGroup(QObject *parent = nullptr) : QObject(parent) { }
+
+ TestTypeGroupedWithDeferred *getGroup() { return &m_group; }
+};
+
+// attached properties:
+
+class TestTypeAttachedWithDeferred : public TestTypeAttached
+{
+ Q_OBJECT
+ Q_PROPERTY(int deferred READ getDeferred WRITE setDeferred BINDABLE bindableDeferred)
+ QML_ANONYMOUS
+ Q_CLASSINFO("DeferredPropertyNames", "deferred")
+
+ QProperty<int> m_deferred { 0 };
+
+public:
+ TestTypeAttachedWithDeferred(QObject *parent) : TestTypeAttached(parent) { }
+
+ int getDeferred() const { return m_deferred; }
+ void setDeferred(int v) { m_deferred = v; }
+ QBindable<int> bindableDeferred() const { return QBindable<int>(&m_deferred); }
+};
+
+class DeferredAttached : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_ATTACHED(TestTypeAttachedWithDeferred)
+
+public:
+ DeferredAttached(QObject *parent = nullptr) : QObject(parent) { }
+
+ static TestTypeAttachedWithDeferred *qmlAttachedProperties(QObject *);
+};
+
+// special:
+
+class TypeWithDeferredComplexProperties : public TypeWithDeferredGroup
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_CLASSINFO("DeferredPropertyNames", "group,DeferredAttached")
+
+public:
+ TypeWithDeferredComplexProperties(QObject *parent = nullptr) : TypeWithDeferredGroup(parent) { }
+};
+
+#endif // DEFERREDPROPERTYTYPES_H
diff --git a/tests/auto/qml/qmltc/data/cpptypes/typewithproperties.h b/tests/auto/qml/qmltc/data/cpptypes/typewithproperties.h
index 51d7eca015..64625103f4 100644
--- a/tests/auto/qml/qmltc/data/cpptypes/typewithproperties.h
+++ b/tests/auto/qml/qmltc/data/cpptypes/typewithproperties.h
@@ -26,6 +26,9 @@
**
****************************************************************************/
+#ifndef TYPEWITHPROPERTIES_H
+#define TYPEWITHPROPERTIES_H
+
#include <QtCore/qobject.h>
#include <QtCore/qproperty.h>
#include <QtCore/qstring.h>
@@ -70,3 +73,5 @@ Q_SIGNALS:
void cWeirdSignal(QVariant);
void dSignal(QString, int);
};
+
+#endif // TYPEWITHPROPERTIES_H
diff --git a/tests/auto/qml/qmltc/data/deferredProperties.qml b/tests/auto/qml/qmltc/data/deferredProperties.qml
new file mode 100644
index 0000000000..7b977744e2
--- /dev/null
+++ b/tests/auto/qml/qmltc/data/deferredProperties.qml
@@ -0,0 +1,16 @@
+import QtQuick
+import QmltcTests 1.0
+TypeWithDeferredProperty {
+ id: root
+ property int width: 42
+
+ deferredProperty: Rectangle {
+ width: root.width * 2
+ implicitHeight: 4
+ height: implicitHeight
+ Rectangle {
+ width: root.width // + parent.width
+ height: parent.height
+ }
+ }
+}
diff --git a/tests/auto/qml/qmltc/data/deferredProperties_attached.qml b/tests/auto/qml/qmltc/data/deferredProperties_attached.qml
new file mode 100644
index 0000000000..875deb5778
--- /dev/null
+++ b/tests/auto/qml/qmltc/data/deferredProperties_attached.qml
@@ -0,0 +1,6 @@
+import QtQuick
+import QmltcTests 1.0
+QtObject {
+ DeferredAttached.attachedFormula: 43 + 10 - (5 * 2)
+ DeferredAttached.deferred: 42
+}
diff --git a/tests/auto/qml/qmltc/data/deferredProperties_complex.qml b/tests/auto/qml/qmltc/data/deferredProperties_complex.qml
new file mode 100644
index 0000000000..ce5429a095
--- /dev/null
+++ b/tests/auto/qml/qmltc/data/deferredProperties_complex.qml
@@ -0,0 +1,9 @@
+import QtQuick
+import QmltcTests 1.0
+TypeWithDeferredComplexProperties {
+ group.str: "still immediate"
+ group.deferred: -1
+
+ DeferredAttached.attachedFormula: Math.abs(10 * 2)
+ DeferredAttached.deferred: 100
+}
diff --git a/tests/auto/qml/qmltc/data/deferredProperties_group.qml b/tests/auto/qml/qmltc/data/deferredProperties_group.qml
new file mode 100644
index 0000000000..a162968c86
--- /dev/null
+++ b/tests/auto/qml/qmltc/data/deferredProperties_group.qml
@@ -0,0 +1,6 @@
+import QtQuick
+import QmltcTests 1.0
+TypeWithDeferredGroup {
+ group.str: "foo" + "bar"
+ group.deferred: 42
+}
diff --git a/tests/auto/qml/qmltc/tst_qmltc.cpp b/tests/auto/qml/qmltc/tst_qmltc.cpp
index e26aa06e78..ef92dd5c74 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.cpp
+++ b/tests/auto/qml/qmltc/tst_qmltc.cpp
@@ -40,6 +40,10 @@
#include "importnamespace.h"
#include "componenttype.h"
#include "componenttypes.h"
+#include "deferredproperties.h"
+#include "deferredproperties_group.h"
+#include "deferredproperties_attached.h"
+#include "deferredproperties_complex.h"
#include "signalhandlers.h"
#include "javascriptfunctions.h"
@@ -82,6 +86,8 @@
#include "calqlatrbits.h"
#include "propertychangeandsignalhandlers.h"
+#include "testprivateproperty.h"
+
// Qt:
#include <QtCore/qstring.h>
#include <QtCore/qbytearray.h>
@@ -94,6 +100,7 @@
#include <QtTest/qsignalspy.h>
+#include <QtCore/private/qobject_p.h>
#include <QtTest/private/qemulationdetector_p.h>
#ifndef QMLTC_TESTS_DISABLE_CACHE
@@ -128,6 +135,10 @@ void tst_qmltc::initTestCase()
QUrl("qrc:/QmltcTests/ObjectWithId.qml"),
QUrl("qrc:/QmltcTests/documentWithIds.qml"),
QUrl("qrc:/QmltcTests/importNamespace.qml"),
+ QUrl("qrc:/QmltcTests/deferredProperties.qml"),
+ QUrl("qrc:/QmltcTests/deferredProperties_group.qml"),
+ QUrl("qrc:/QmltcTests/deferredProperties_attached.qml"),
+ QUrl("qrc:/QmltcTests/deferredProperties_complex.qml"),
QUrl("qrc:/QmltcTests/signalHandlers.qml"),
QUrl("qrc:/QmltcTests/javaScriptFunctions.qml"),
@@ -581,6 +592,73 @@ void tst_qmltc::componentTypes()
}
}
+void tst_qmltc::deferredProperties()
+{
+ {
+ QQmlEngine e;
+ PREPEND_NAMESPACE(deferredProperties) created(&e);
+ QVERIFY(created.deferredProperty()
+ == nullptr); // binding is not applied since it is deferred
+
+ qmlExecuteDeferred(&created);
+
+ QQuickRectangle *rect = qobject_cast<QQuickRectangle *>(created.deferredProperty());
+ QVERIFY(rect);
+ QCOMPARE(rect->width(), created.width() * 2);
+ QCOMPARE(rect->implicitHeight(), 4);
+ QCOMPARE(rect->height(), rect->implicitHeight());
+
+ QQmlListReference children(rect, "data");
+ QCOMPARE(children.size(), 1);
+ QQuickRectangle *subRect = qobject_cast<QQuickRectangle *>(children.at(0));
+ QVERIFY(subRect);
+ QCOMPARE(subRect->width(), created.width());
+ QCOMPARE(subRect->height(), rect->height());
+ }
+ {
+ QQmlEngine e;
+ PREPEND_NAMESPACE(deferredProperties_group) created(&e);
+ QCOMPARE(created.getGroup()->getStr(), u"foobar"_qs);
+ QCOMPARE(created.getGroup()->getDeferred(), 0);
+ // Note: we can't easily evaluate a deferred binding for a
+ // `group.deferred` here, so just accept the fact the the value is not
+ // set at all as a successful test
+ }
+ {
+ QQmlEngine e;
+ PREPEND_NAMESPACE(deferredProperties_attached) created(&e);
+ TestTypeAttachedWithDeferred *attached = qobject_cast<TestTypeAttachedWithDeferred *>(
+ qmlAttachedPropertiesObject<DeferredAttached>(&created, false));
+ QVERIFY(attached);
+
+ QCOMPARE(attached->getAttachedFormula(), 43);
+ QCOMPARE(attached->getDeferred(), 0);
+ // Note: we can't easily evaluate a deferred binding for a
+ // `group.deferred` here, so just accept the fact the the value is not
+ // set at all as a successful test
+ }
+ {
+ QQmlEngine e;
+ PREPEND_NAMESPACE(deferredProperties_complex) created(&e);
+
+ // `group` binding is not deferred as per current behavior outside of
+ // PropertyChanges and friends. we defer `group.deferred` binding though
+ QCOMPARE(created.getGroup()->getStr(), u"still immediate"_qs);
+ QCOMPARE(created.getGroup()->getDeferred(), 0);
+
+ QVERIFY(!qmlAttachedPropertiesObject<DeferredAttached>(&created, false));
+
+ qmlExecuteDeferred(&created);
+
+ TestTypeAttachedWithDeferred *attached = qobject_cast<TestTypeAttachedWithDeferred *>(
+ qmlAttachedPropertiesObject<DeferredAttached>(&created, false));
+ QVERIFY(attached);
+
+ QCOMPARE(attached->getAttachedFormula(), 20);
+ QCOMPARE(attached->getDeferred(), 100);
+ }
+}
+
void tst_qmltc::signalHandlers()
{
QQmlEngine e;
@@ -1102,11 +1180,9 @@ void tst_qmltc::defaultAlias()
QSKIP("Not implemented - not supported");
}
-// TODO: this just doesn't work currently
void tst_qmltc::attachedProperty()
{
QQmlEngine e;
- QSKIP("Broken in many ways.");
PREPEND_NAMESPACE(attachedProperty) created(&e);
TestTypeAttached *attached = qobject_cast<TestTypeAttached *>(
@@ -1145,8 +1221,6 @@ void tst_qmltc::attachedProperty()
void tst_qmltc::groupedProperty()
{
QQmlEngine e;
- QSKIP("Property index is wrong due to not picking QtQml dependency when creating group "
- "property scope");
PREPEND_NAMESPACE(groupedProperty) created(&e);
TestTypeGrouped *grouped = created.getGroup();
@@ -1708,9 +1782,22 @@ void tst_qmltc::keyEvents()
void tst_qmltc::privateProperties()
{
- QSKIP("The same problem with poor QObject qmltypes is encountered here.");
QQmlEngine e;
PREPEND_NAMESPACE(privatePropertySubclass) created(&e);
+ QCOMPARE(created.dummy(), u"bar"_qs);
+ QCOMPARE(created.strAlias(), u"foobar"_qs);
+ QCOMPARE(created.smthAlias(), 42);
+
+ auto privateCreated = static_cast<PrivatePropertyTypePrivate *>(QObjectPrivate::get(&created));
+ QVERIFY(privateCreated);
+ QCOMPARE(privateCreated->foo(), u"Smth is: 42"_qs);
+
+ ValueTypeGroup vt = privateCreated->vt();
+ QCOMPARE(vt.count(), 11);
+
+ TestTypeGrouped *group = privateCreated->getGroup();
+ QCOMPARE(group->getCount(), 43);
+ QCOMPARE(group->getStr(), created.strAlias());
}
void tst_qmltc::calqlatrBits()
diff --git a/tests/auto/qml/qmltc/tst_qmltc.h b/tests/auto/qml/qmltc/tst_qmltc.h
index ffffc6d9b7..5ce8a189da 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.h
+++ b/tests/auto/qml/qmltc/tst_qmltc.h
@@ -53,6 +53,7 @@ private slots:
void ids();
void importNamespace();
void componentTypes();
+ void deferredProperties();
void signalHandlers();
void jsFunctions();
diff --git a/tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp b/tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp
index 8b0db1c50a..d8c08ee5be 100644
--- a/tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp
+++ b/tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp
@@ -49,6 +49,7 @@
#include <private/qquickitem_p.h>
#include <private/qv4qmlcontext_p.h>
#include <private/qqmlproperty_p.h>
+#include <private/qquickanchors_p.h>
#include <array>
#include <memory>
diff --git a/tests/auto/qml/qmltc_qprocess/CMakeLists.txt b/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
index 46f1d856d3..bd70d2fae7 100644
--- a/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
+++ b/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
@@ -12,7 +12,12 @@ qt6_add_qml_module(tst_qmltc_qprocess
QML_FILES
data/dummy.qml
data/inlineComponent.qml
+ data/SingletonThing.qml
+ data/erroneousFile.qml
)
+# special setup for singleton files:
+set_source_files_properties(SingletonThing.qml PROPERTIES QT_QML_SINGLETON_TYPE true)
+
add_dependencies(tst_qmltc_qprocess Qt::qmltc)
# fetch --resource arguments manually (mimics the logic of qmltc compilation
diff --git a/tests/auto/qml/qmltc_qprocess/data/SingletonThing.qml b/tests/auto/qml/qmltc_qprocess/data/SingletonThing.qml
new file mode 100644
index 0000000000..599b54eddd
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/SingletonThing.qml
@@ -0,0 +1,7 @@
+pragma Singleton
+import QtQml
+
+QtObject {
+ property int integerProperty: 42
+ property string stringProperty: "hello"
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/erroneousFile.qml b/tests/auto/qml/qmltc_qprocess/data/erroneousFile.qml
new file mode 100644
index 0000000000..a7316ed78b
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/erroneousFile.qml
@@ -0,0 +1,4 @@
+import QtQml
+QtObject {
+ property NonExistent type: QtObject {}
+}
diff --git a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
index 50abcc8332..09c77ce37a 100644
--- a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
+++ b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
@@ -68,6 +68,8 @@ private slots:
void noBuiltins();
void noQtQml();
void inlineComponent();
+ void singleton();
+ void warningsAsErrors();
};
#ifndef TST_QMLTC_QPROCESS_RESOURCES
@@ -200,5 +202,18 @@ void tst_qmltc_qprocess::inlineComponent()
QVERIFY(!errors.contains(u"Inline components are not supported"_qs));
}
+void tst_qmltc_qprocess::singleton()
+{
+ const auto errors = runQmltc(u"SingletonThing.qml"_qs, false);
+ QEXPECT_FAIL("", "qmltc does not support singletons at the moment", Continue);
+ QVERIFY(!errors.contains(u"Singleton types are not supported"_qs));
+}
+
+void tst_qmltc_qprocess::warningsAsErrors()
+{
+ const auto errors = runQmltc(u"erroneousFile.qml"_qs, false);
+ QVERIFY2(errors.contains(u"Error:"_qs), qPrintable(errors)); // Note: not a warning!
+}
+
QTEST_MAIN(tst_qmltc_qprocess)
#include "tst_qmltc_qprocess.moc"
diff --git a/tests/auto/qml/qmltyperegistrar/CMakeLists.txt b/tests/auto/qml/qmltyperegistrar/CMakeLists.txt
index c7326c30c4..ad22f51cd9 100644
--- a/tests/auto/qml/qmltyperegistrar/CMakeLists.txt
+++ b/tests/auto/qml/qmltyperegistrar/CMakeLists.txt
@@ -62,3 +62,13 @@ set_target_properties(tst_qmltyperegistrar PROPERTIES
# yet, so we have to call it directly to test that code path for now.
_qt_internal_qml_type_registration(tst_qmltyperegistrar MANUAL_MOC_JSON_FILES ${json_list})
add_subdirectory(foreign)
+
+qt_add_library(tst-qmltyperegistrar-with-dashes)
+target_link_libraries(tst-qmltyperegistrar-with-dashes PRIVATE Qt::Core Qt::Qml)
+qt_enable_autogen_tool(tst-qmltyperegistrar-with-dashes "moc" ON)
+qt_add_qml_module(tst-qmltyperegistrar-with-dashes
+ URI Module-With-Dashes
+ VERSION 1.0
+ SOURCES
+ foo.cpp foo.h
+)
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
index 5619c2aa0f..3fc746552e 100644
--- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
@@ -339,6 +339,46 @@ void tst_qmltyperegistrar::methodReturnType()
QVERIFY(qmltypesData.contains("type: \"QQmlComponent\""));
}
+void tst_qmltyperegistrar::addRemoveVersion_data()
+{
+ QTest::addColumn<QTypeRevision>("importVersion");
+ for (int i = 0; i < 20; ++i)
+ QTest::addRow("v1.%d.qml", i) << QTypeRevision::fromVersion(1, i);
+}
+
+void tst_qmltyperegistrar::addRemoveVersion()
+{
+ QFETCH(QTypeRevision, importVersion);
+
+ const bool creatable
+ = importVersion > QTypeRevision::fromVersion(1, 2)
+ && importVersion < QTypeRevision::fromVersion(1, 18);
+ const bool thingAccessible = importVersion > QTypeRevision::fromVersion(1, 3);
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine);
+ c.setData(QStringLiteral("import QmlTypeRegistrarTest %1.%2\n"
+ "Versioned {\n"
+ " property int thing: revisioned\n"
+ "}")
+ .arg(importVersion.majorVersion()).arg(importVersion.minorVersion()).toUtf8(),
+ QUrl(QTest::currentDataTag()));
+ if (!creatable) {
+ QVERIFY(c.isError());
+ return;
+ }
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ if (!thingAccessible) {
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(QStringLiteral("%1:3: ReferenceError: revisioned is not defined")
+ .arg(QTest::currentDataTag())));
+ }
+ QScopedPointer o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("thing").toInt(), thingAccessible ? 24 : 0);
+}
+
#ifdef QT_QUICK_LIB
void tst_qmltyperegistrar::foreignRevisionedProperty()
{
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
index d57053a051..385d3b6666 100644
--- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
@@ -469,6 +469,28 @@ public:
};
#endif
+class AddedInLateVersion : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(Versioned)
+ QML_ADDED_IN_VERSION(1, 8)
+ Q_PROPERTY(int revisioned READ revisioned CONSTANT REVISION(1, 4))
+ Q_PROPERTY(int insane READ revisioned CONSTANT REVISION 17)
+public:
+ AddedInLateVersion(QObject *parent = nullptr) : QObject(parent) {}
+ int revisioned() const { return 24; }
+};
+
+class RemovedInEarlyVersion : public AddedInLateVersion
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(Versioned)
+ QML_ADDED_IN_VERSION(1, 3)
+ QML_REMOVED_IN_VERSION(1, 8)
+public:
+ RemovedInEarlyVersion(QObject *parent = nullptr) : AddedInLateVersion(parent) {}
+};
+
class tst_qmltyperegistrar : public QObject
{
Q_OBJECT
@@ -508,6 +530,9 @@ private slots:
void foreignRevisionedProperty();
#endif
+ void addRemoveVersion_data();
+ void addRemoveVersion();
+
private:
QByteArray qmltypesData;
};
diff --git a/tests/auto/qml/qqmlapplicationengine/CMakeLists.txt b/tests/auto/qml/qqmlapplicationengine/CMakeLists.txt
index 7f05a759b6..d9fbf6517d 100644
--- a/tests/auto/qml/qqmlapplicationengine/CMakeLists.txt
+++ b/tests/auto/qml/qqmlapplicationengine/CMakeLists.txt
@@ -35,6 +35,9 @@ qt_internal_add_resource(tst_qqmlapplicationengine "tst_qqmlapplicationengine"
${tst_qqmlapplicationengine_resource_files}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmlapplicationengine)
+endif()
#### Keys ignored in scope 2:.:.:tst_qqmlapplicationengine.pro:<TRUE>:
# TRANSLATIONS = "data/i18n/qml_ja.ts"
diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
index 67c75ccce7..c948ad5b9c 100644
--- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
+++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
@@ -101,6 +101,10 @@ void tst_qqmlapplicationengine::basicLoading()
// will break.
void tst_qqmlapplicationengine::testNonResolvedPath()
{
+#if defined(Q_OS_INTEGRITY)
+ QSKIP("INTEGRITY stores QML files in resources, and the path to a resource cannot be relative in this case");
+#endif
+
#ifdef Q_OS_ANDROID
QSKIP("Android stores QML files in resources, and the path to a resource cannot be relative in this case");
#endif
diff --git a/tests/auto/qml/qqmlcomponent/data/jsmodule/module.mjs b/tests/auto/qml/qqmlcomponent/data/jsmodule/module.mjs
index 3dd3507d45..9175ba0a67 100644
--- a/tests/auto/qml/qqmlcomponent/data/jsmodule/module.mjs
+++ b/tests/auto/qml/qqmlcomponent/data/jsmodule/module.mjs
@@ -1,5 +1,6 @@
export function withProp(root) {
- const component = Qt.createComponent("data/jsmodule/Dynamic.qml");
+ const prefix = Qt.platform.os == "android" ? "qrc:" : "";
+ const component = Qt.createComponent(prefix + "data/jsmodule/Dynamic.qml");
const el = component.createObject(root, { value: 42 });
return el.value;
}
diff --git a/tests/auto/qml/qqmlconsole/CMakeLists.txt b/tests/auto/qml/qqmlconsole/CMakeLists.txt
index 171d1ad578..5096503c15 100644
--- a/tests/auto/qml/qqmlconsole/CMakeLists.txt
+++ b/tests/auto/qml/qqmlconsole/CMakeLists.txt
@@ -21,6 +21,10 @@ qt_internal_add_test(tst_qqmlconsole
TESTDATA ${test_data}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmlconsole)
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qqmlengine/CMakeLists.txt b/tests/auto/qml/qqmlengine/CMakeLists.txt
index 01e9999f79..43fec7cb90 100644
--- a/tests/auto/qml/qqmlengine/CMakeLists.txt
+++ b/tests/auto/qml/qqmlengine/CMakeLists.txt
@@ -36,6 +36,9 @@ qt_internal_add_resource(tst_qqmlengine "qmake_immediate"
${qmake_immediate_resource_files}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmlengine)
+endif()
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qqmlfileselector/CMakeLists.txt b/tests/auto/qml/qqmlfileselector/CMakeLists.txt
index d010280a9d..4d7c4f840b 100644
--- a/tests/auto/qml/qqmlfileselector/CMakeLists.txt
+++ b/tests/auto/qml/qqmlfileselector/CMakeLists.txt
@@ -22,6 +22,10 @@ qt_internal_add_test(tst_qqmlfileselector
TESTDATA ${test_data}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmlfileselector)
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qqmlimport/data/absoluteImport.qml b/tests/auto/qml/qqmlimport/data/absoluteImport.qml
new file mode 100644
index 0000000000..d182fe5b71
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/absoluteImport.qml
@@ -0,0 +1,4 @@
+import "/foo/bar/baz"
+
+QtObject {}
+
diff --git a/tests/auto/qml/qqmlimport/data/absoluteResourceImport.qml b/tests/auto/qml/qqmlimport/data/absoluteResourceImport.qml
new file mode 100644
index 0000000000..74b98664aa
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/absoluteResourceImport.qml
@@ -0,0 +1,4 @@
+import ":/absolute/resource/path"
+
+QtObject {}
+
diff --git a/tests/auto/qml/qqmlimport/data/relativeResourceImport.qml b/tests/auto/qml/qqmlimport/data/relativeResourceImport.qml
new file mode 100644
index 0000000000..6a7e2b7ea5
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/relativeResourceImport.qml
@@ -0,0 +1,4 @@
+import ":relative/resource/path"
+
+QtObject {}
+
diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
index f52b01cf04..a2662d5a67 100644
--- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
+++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
@@ -35,6 +35,7 @@
#include <private/qqmlimport_p.h>
#include <private/qqmlengine_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QQmlComponent>
class tst_QQmlImport : public QQmlDataTest
{
@@ -59,6 +60,8 @@ private slots:
void cleanup();
void envResourceImportPath();
void preferResourcePath();
+ void invalidFileImport_data();
+ void invalidFileImport();
};
void tst_QQmlImport::cleanup()
@@ -104,6 +107,36 @@ void tst_QQmlImport::preferResourcePath()
QCOMPARE(o->objectName(), "right");
}
+void tst_QQmlImport::invalidFileImport_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("import");
+ QTest::addRow("file absolute")
+ << QStringLiteral("absoluteImport.qml")
+ << QStringLiteral("/foo/bar/baz");
+ QTest::addRow("resource absolute")
+ << QStringLiteral("absoluteResourceImport.qml")
+ << QStringLiteral(":/absolute/resource/path");
+ QTest::addRow("resource relative")
+ << QStringLiteral("relativeResourceImport.qml")
+ << QStringLiteral(":relative/resource/path");
+}
+
+void tst_QQmlImport::invalidFileImport()
+{
+ QFETCH(QString, file);
+ QFETCH(QString, import);
+
+ QQmlEngine engine;
+
+ QQmlComponent component(&engine, testFileUrl(file));
+ QVERIFY(component.isError());
+ QVERIFY(component.errorString().contains(
+ QStringLiteral("\"%1\" is not a valid import URL. "
+ "You can pass relative paths or URLs with schema, "
+ "but not absolute paths or resource paths.").arg(import)));
+}
+
void tst_QQmlImport::testDesignerSupported()
{
QQuickView *window = new QQuickView();
diff --git a/tests/auto/qml/qqmlincubator/CMakeLists.txt b/tests/auto/qml/qqmlincubator/CMakeLists.txt
index 934199a66e..b2ade30c39 100644
--- a/tests/auto/qml/qqmlincubator/CMakeLists.txt
+++ b/tests/auto/qml/qqmlincubator/CMakeLists.txt
@@ -24,6 +24,10 @@ qt_internal_add_test(tst_qqmlincubator
TESTDATA ${test_data}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmlincubator)
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qqmlinfo/CMakeLists.txt b/tests/auto/qml/qqmlinfo/CMakeLists.txt
index 9ba8ca4c4c..3020b84c59 100644
--- a/tests/auto/qml/qqmlinfo/CMakeLists.txt
+++ b/tests/auto/qml/qqmlinfo/CMakeLists.txt
@@ -23,6 +23,10 @@ qt_internal_add_test(tst_qqmlinfo
TESTDATA ${test_data}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmlinfo)
+endif()
+
#### Keys ignored in scope 1:.:.:qqmlinfo.pro:<TRUE>:
# QML_IMPORT_MAJOR_VERSION = "1"
# QML_IMPORT_NAME = "org.qtproject.Test"
diff --git a/tests/auto/qml/qqmlitemmodels/data/modelindex.qml b/tests/auto/qml/qqmlitemmodels/data/modelindex.qml
index 0d6e3624cb..2756f04120 100644
--- a/tests/auto/qml/qqmlitemmodels/data/modelindex.qml
+++ b/tests/auto/qml/qqmlitemmodels/data/modelindex.qml
@@ -1,3 +1,4 @@
+import QtQml 2.0
import Test 1.0
ItemModelsTest {
diff --git a/tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml b/tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml
index 13037065a6..85987bdcac 100644
--- a/tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml
+++ b/tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml
@@ -1,3 +1,4 @@
+import QtQml 2.0
import Test 1.0
ItemModelsTest {
diff --git a/tests/auto/qml/qqmllanguage/data/foreignExtended.qml b/tests/auto/qml/qqmllanguage/data/foreignExtended.qml
index 4863e0d567..b01af6d229 100644
--- a/tests/auto/qml/qqmllanguage/data/foreignExtended.qml
+++ b/tests/auto/qml/qqmllanguage/data/foreignExtended.qml
@@ -5,12 +5,17 @@ QtObject {
property Foreign foreign: Foreign {
objectName: "foreign"
}
- property Extended extended: Extended {}
+ property Extended extended: Extended {
+ objectName: "extended"
+ property int changeCount: 0
+ onExtensionChanged: ++changeCount
+ }
property ForeignExtended foreignExtended: ForeignExtended {
objectName: "foreignExtended"
}
property int extendedBase: extended.base
+ property int extendedChangeCount: extended.changeCount
property int extendedInvokable: extended.invokable()
property int extendedSlot: extended.slot()
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index 57d3fe8860..b09840606b 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -1470,13 +1470,23 @@ public:
class Extension : public QObject
{
Q_OBJECT
- Q_PROPERTY(int extension READ extension CONSTANT)
+ Q_PROPERTY(int extension READ extension WRITE setExtension NOTIFY extensionChanged FINAL)
public:
Extension(QObject *parent = nullptr) : QObject(parent) {}
- int extension() const { return 42; }
+ int extension() const { return ext; }
+ void setExtension(int e) {
+ if (e != ext) {
+ ext = e;
+ emit extensionChanged();
+ }
+ }
Q_INVOKABLE int invokable() { return 123; }
+Q_SIGNALS:
+ void extensionChanged();
public slots:
int slot() { return 456; }
+private:
+ int ext = 42;
};
class Extended : public QObject
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 17d7ff6f7e..cf35ad0a6a 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -283,6 +283,7 @@ private slots:
void lazyDeferredSubObject();
void deferredProperties();
void executeDeferredPropertiesOnce();
+ void deferredProperties_extra();
void noChildEvents();
@@ -5134,6 +5135,82 @@ void tst_qqmllanguage::executeDeferredPropertiesOnce()
QCOMPARE(listProperty.at(&listProperty, 1)->property("wasCompleted"), QVariant(true));
}
+class GroupType : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int foo READ getFoo WRITE setFoo BINDABLE bindableFoo)
+ Q_PROPERTY(int bar READ getBar WRITE setBar BINDABLE bindableBar)
+ Q_CLASSINFO("DeferredPropertyNames", "bar")
+
+ QProperty<int> m_foo { 0 };
+ QProperty<int> m_bar { 0 };
+
+public:
+ int getFoo() const { return m_foo; }
+ void setFoo(int v) { m_foo = v; }
+ QBindable<int> bindableFoo() const { return QBindable<int>(&m_foo); }
+
+ int getBar() const { return m_bar; }
+ void setBar(int v) { m_bar = v; }
+ QBindable<int> bindableBar() const { return QBindable<int>(&m_bar); }
+};
+
+class ExtraDeferredProperties : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(GroupType *group READ getGroup)
+ Q_CLASSINFO("DeferredPropertyNames", "group,MyQmlObject")
+
+ GroupType m_group;
+
+public:
+ ExtraDeferredProperties(QObject *parent = nullptr) : QObject(parent) { }
+
+ GroupType *getGroup() { return &m_group; }
+};
+
+void tst_qqmllanguage::deferredProperties_extra()
+{
+ // Note: because ExtraDeferredProperties defers only a `group` property, the
+ // deferral does not actually work.
+ QTest::ignoreMessage(
+ QtMsgType::QtWarningMsg,
+ "Binding on group is not deferred as requested by the DeferredPropertyNames class info "
+ "because it constitutes a group property.");
+
+ qmlRegisterType<GroupType>("deferred.properties.extra", 1, 0, "GroupType");
+ qmlRegisterType<ExtraDeferredProperties>("deferred.properties.extra", 1, 0,
+ "ExtraDeferredProperties");
+ QQmlComponent component(&engine);
+ component.setData(R"(
+ import QtQuick
+ import Test 1.0
+ import deferred.properties.extra 1.0
+
+ ExtraDeferredProperties {
+ group.foo: 4
+ group.bar: 4
+ MyQmlObject.value: 1
+ }
+ )", QUrl());
+
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<ExtraDeferredProperties> object(
+ qobject_cast<ExtraDeferredProperties *>(component.create()));
+ QVERIFY(object);
+
+ QCOMPARE(object->getGroup()->getFoo(), 4); // not deferred (as group itself is not deferred)
+ QCOMPARE(object->getGroup()->getBar(), 0); // deferred, as per group's own deferred names
+ // but attached property is deferred:
+ QVERIFY(!qmlAttachedPropertiesObject<MyQmlObject>(object.get(), false));
+
+ qmlExecuteDeferred(object.get());
+
+ auto attached = qmlAttachedPropertiesObject<MyQmlObject>(object.get(), false);
+ QVERIFY(attached);
+ QCOMPARE(attached->property("value").toInt(), 1);
+}
+
void tst_qqmllanguage::noChildEvents()
{
QQmlComponent component(&engine);
@@ -5559,9 +5636,20 @@ void tst_qqmllanguage::extendedForeignTypes()
QScopedPointer<QObject> o(component.create());
QVERIFY(!o.isNull());
+ QObject *extended = o->property("extended").value<QObject *>();
+ QVERIFY(extended);
+ QSignalSpy extensionChangedSpy(extended, SIGNAL(extensionChanged()));
+
QCOMPARE(o->property("extendedBase").toInt(), 43);
QCOMPARE(o->property("extendedExtension").toInt(), 42);
QCOMPARE(o->property("foreignExtendedExtension").toInt(), 42);
+
+ QCOMPARE(extensionChangedSpy.count(), 0);
+ extended->setProperty("extension", 44);
+ QCOMPARE(extensionChangedSpy.count(), 1);
+ QCOMPARE(o->property("extendedChangeCount").toInt(), 1);
+ QCOMPARE(o->property("extendedExtension").toInt(), 44);
+
QCOMPARE(o->property("foreignObjectName").toString(), QLatin1String("foreign"));
QCOMPARE(o->property("foreignExtendedObjectName").toString(), QLatin1String("foreignExtended"));
QCOMPARE(o->property("extendedInvokable").toInt(), 123);
diff --git a/tests/auto/qml/qqmllistreference/CMakeLists.txt b/tests/auto/qml/qqmllistreference/CMakeLists.txt
index b620873c54..9d4b3cac7a 100644
--- a/tests/auto/qml/qqmllistreference/CMakeLists.txt
+++ b/tests/auto/qml/qqmllistreference/CMakeLists.txt
@@ -23,6 +23,10 @@ qt_internal_add_test(tst_qqmllistreference
TESTDATA ${test_data}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmllistreference)
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qqmlmetaobject/CMakeLists.txt b/tests/auto/qml/qqmlmetaobject/CMakeLists.txt
index a46b58f9ab..93edb03527 100644
--- a/tests/auto/qml/qqmlmetaobject/CMakeLists.txt
+++ b/tests/auto/qml/qqmlmetaobject/CMakeLists.txt
@@ -21,6 +21,10 @@ qt_internal_add_test(tst_qqmlmetaobject
TESTDATA ${test_data}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmlmetaobject)
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
index 81c6b0d2a1..fa54d440b8 100644
--- a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
+++ b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include <QtTest/QtTest>
+#include <QtCore/QScopedPointer>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlengine.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -188,8 +189,9 @@ void tst_QQmlMetaObject::property()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl(testFile));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj);
+ QObject *object = obj.get();
const QMetaObject *mo = object->metaObject();
QVERIFY(mo->superClass() != nullptr);
@@ -263,8 +265,6 @@ void tst_QQmlMetaObject::property()
QVERIFY(!prop.write(object, prop.read(object)));
QCOMPARE(changedSpy.count(), 0);
}
-
- delete object;
}
void tst_QQmlMetaObject::method_data()
@@ -359,8 +359,9 @@ void tst_QQmlMetaObject::method()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl(testFile));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj);
+ QObject *object = obj.get();
const QMetaObject *mo = object->metaObject();
QVERIFY(mo->superClass() != nullptr);
@@ -384,8 +385,6 @@ void tst_QQmlMetaObject::method()
QCOMPARE(QString::fromUtf8(method.typeName()), returnTypeName);
QCOMPARE(method.returnType(), returnType);
-
- delete object;
}
QTEST_MAIN(tst_QQmlMetaObject)
diff --git a/tests/auto/qml/qqmlmetatype/CMakeLists.txt b/tests/auto/qml/qqmlmetatype/CMakeLists.txt
index 86b1fa6afb..74146bb49b 100644
--- a/tests/auto/qml/qqmlmetatype/CMakeLists.txt
+++ b/tests/auto/qml/qqmlmetatype/CMakeLists.txt
@@ -46,6 +46,9 @@ qt_internal_add_resource(tst_qqmlmetatype "qmake_qmldirresource"
${qmake_qmldirresource_resource_files}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmlmetatype)
+endif()
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qqmlnotifier/CMakeLists.txt b/tests/auto/qml/qqmlnotifier/CMakeLists.txt
index dfd9d625bc..4056f06458 100644
--- a/tests/auto/qml/qqmlnotifier/CMakeLists.txt
+++ b/tests/auto/qml/qqmlnotifier/CMakeLists.txt
@@ -20,6 +20,10 @@ qt_internal_add_test(tst_qqmlnotifier
TESTDATA ${test_data}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmlnotifier)
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qqmlpromise/CMakeLists.txt b/tests/auto/qml/qqmlpromise/CMakeLists.txt
index 00c3dcf6b4..ac0ffebabe 100644
--- a/tests/auto/qml/qqmlpromise/CMakeLists.txt
+++ b/tests/auto/qml/qqmlpromise/CMakeLists.txt
@@ -24,6 +24,10 @@ qt_internal_add_test(tst_qqmlpromise
TESTDATA ${test_data}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmlpromise)
+endif()
+
#### Keys ignored in scope 1:.:.:qqmlpromise.pro:<TRUE>:
# DISTFILES = "data/then-fulfilled-non-callable.qml" "data/then-reject-non-callable.qml" "data/then-resolve-multiple-then.qml" "data/then-resolve-chaining.qml" "data/then-reject-chaining.qml" "data/promise-resolve-with-value.qml" "data/promise-resolve-with-promise.qml" "data/promise-reject-with-value.qml" "data/promise-executor-resolve.qml" "data/promise-get-length.qml" "data/promise-executor-reject.qml" "data/promise-reject-catch.qml" "data/promise-async-resolve-with-value.qml" "data/promise-async-reject-with-value.qml" "data/promise-all-resolve.qml" "data/promise-all-empty-input.qml" "data/promise-resolve-with-array.qml" "data/promise-all-reject-reject-is-last.qml" "data/promise-all-reject-reject-is-mid.qml" "data/promise-race-resolve-1st.qml" "data/promise-race-empty-input.qml" "data/promise-race-resolve-2nd.qml" "data/promise-race-resolve-1st-in-executor-function.qml" "data/promise-resolve-is-a-function.qml" "data/promise-resolve-function-length.qml" "data/promise-all-invoke-then-method.qml" "data/promise-resolve-with-empty.qml" "data/promise-executor-throw-exception.qml" "data/promise-executor-function-extensible.qml" "data/promise-all-noniterable-input.qml"
# OTHER_FILES = <EMPTY>
diff --git a/tests/auto/qml/qqmlpropertymap/dummy_imports.qml b/tests/auto/qml/qqmlpropertymap/dummy_imports.qml
index 4ae9d3f2cf..63d33cbea6 100644
--- a/tests/auto/qml/qqmlpropertymap/dummy_imports.qml
+++ b/tests/auto/qml/qqmlpropertymap/dummy_imports.qml
@@ -1,8 +1,7 @@
// This file exists for the sole purpose for qmlimportscanner to find
// which modules it needs to extract for deployment.
-// Otherwise, it fails to find the imports that are expressed in the
-// C++ code belonging to the test.
+// Otherwise, it fails to find the imports that are expressed in C++.
-import QtQuick 2.0
+import QtQuick
-QtObject { } // This is needed in order to keep importscanner happy
+QtObject { }
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index 8e4849e2d6..e97ab543d1 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -637,7 +637,10 @@ void tst_qqmlqt::openUrlExternally()
const QUrl htmlTestFile = testFileUrl("test.html");
QDesktopServices::setUrlHandler("test", &handler, "noteCall");
QDesktopServices::setUrlHandler(htmlTestFile.scheme(), &handler, "noteCall");
-
+ const auto unset = qScopeGuard([&] {
+ QDesktopServices::unsetUrlHandler(htmlTestFile.scheme());
+ QDesktopServices::unsetUrlHandler("test");
+ });
QQmlComponent component(&engine, testFileUrl("openUrlExternally.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
@@ -648,9 +651,6 @@ void tst_qqmlqt::openUrlExternally()
QCOMPARE(handler.called,2);
QCOMPARE(handler.last, htmlTestFile);
-
- QDesktopServices::unsetUrlHandler("test");
- QDesktopServices::unsetUrlHandler(htmlTestFile.scheme());
}
void tst_qqmlqt::openUrlExternally_pragmaLibrary()
@@ -660,6 +660,10 @@ void tst_qqmlqt::openUrlExternally_pragmaLibrary()
const QUrl htmlTestFile = testFileUrl("test.html");
QDesktopServices::setUrlHandler("test", &handler, "noteCall");
QDesktopServices::setUrlHandler(htmlTestFile.scheme(), &handler, "noteCall");
+ const auto unset = qScopeGuard([&] {
+ QDesktopServices::unsetUrlHandler(htmlTestFile.scheme());
+ QDesktopServices::unsetUrlHandler("test");
+ });
QQmlComponent component(&engine, testFileUrl("openUrlExternally_lib.qml"));
QScopedPointer<QObject> object(component.create());
@@ -671,9 +675,6 @@ void tst_qqmlqt::openUrlExternally_pragmaLibrary()
QCOMPARE(handler.called,2);
QCOMPARE(handler.last, htmlTestFile);
-
- QDesktopServices::unsetUrlHandler("test");
- QDesktopServices::unsetUrlHandler(htmlTestFile.scheme());
}
void tst_qqmlqt::md5()
diff --git a/tests/auto/qml/qqmlsqldatabase/dummy_imports.qml b/tests/auto/qml/qqmlsqldatabase/dummy_imports.qml
index 4ae9d3f2cf..63d33cbea6 100644
--- a/tests/auto/qml/qqmlsqldatabase/dummy_imports.qml
+++ b/tests/auto/qml/qqmlsqldatabase/dummy_imports.qml
@@ -1,8 +1,7 @@
// This file exists for the sole purpose for qmlimportscanner to find
// which modules it needs to extract for deployment.
-// Otherwise, it fails to find the imports that are expressed in the
-// C++ code belonging to the test.
+// Otherwise, it fails to find the imports that are expressed in C++.
-import QtQuick 2.0
+import QtQuick
-QtObject { } // This is needed in order to keep importscanner happy
+QtObject { }
diff --git a/tests/auto/qml/qqmltimer/dummy_imports.qml b/tests/auto/qml/qqmltimer/dummy_imports.qml
index f78e04d489..e189da6689 100644
--- a/tests/auto/qml/qqmltimer/dummy_imports.qml
+++ b/tests/auto/qml/qqmltimer/dummy_imports.qml
@@ -1,9 +1,8 @@
// This file exists for the sole purpose for qmlimportscanner to find
// which modules it needs to extract for deployment.
-// Otherwise, it fails to find the imports that are expressed in the
-// C++ code belonging to the test.
+// Otherwise, it fails to find the imports that are expressed in C++.
-import QtQml 2.0
-import QtQuick 2.0
+import QtQml
+import QtQuick
-QtObject { } // This is needed in order to keep importscanner happy
+QtObject { }
diff --git a/tests/auto/qml/qqmltypeloader/dummy_imports.qml b/tests/auto/qml/qqmltypeloader/dummy_imports.qml
index a4684b2007..e189da6689 100644
--- a/tests/auto/qml/qqmltypeloader/dummy_imports.qml
+++ b/tests/auto/qml/qqmltypeloader/dummy_imports.qml
@@ -1,9 +1,8 @@
// This file exists for the sole purpose for qmlimportscanner to find
// which modules it needs to extract for deployment.
-// Otherwise, it fails to find the imports that are expressed in the
-// C++ code belonging to the test.
+// Otherwise, it fails to find the imports that are expressed in C++.
-import QtQml 2.0
-import QtQuick 2.6
+import QtQml
+import QtQuick
-QtObject { } // This is needed in order to keep importscanner happy
+QtObject { }
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
index a030e56b20..2463af827a 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
@@ -42,6 +42,7 @@
#include <QtQml/private/qqmlirloader_p.h>
#include <QtQuickTestUtils/private/testhttpserver_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QQmlComponent>
class tst_QQMLTypeLoader : public QQmlDataTest
{
diff --git a/tests/auto/qml/qqmlvaluetypes/data/locale_read_singleton.qml b/tests/auto/qml/qqmlvaluetypes/data/locale_read_singleton.qml
new file mode 100644
index 0000000000..f56fe3f422
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypes/data/locale_read_singleton.qml
@@ -0,0 +1,21 @@
+import QtQuick
+
+Item {
+ property string amText: InputMethod.locale.amText
+ property string decimalPoint: InputMethod.locale.decimalPoint
+ property string exponential: InputMethod.locale.exponential
+ property int firstDayOfWeek: InputMethod.locale.firstDayOfWeek
+ property string groupSeparator: InputMethod.locale.groupSeparator
+ property int measurementSystem: InputMethod.locale.measurementSystem
+ property string name: InputMethod.locale.name
+ property string nativeCountryName: InputMethod.locale.nativeCountryName
+ property string nativeLanguageName: InputMethod.locale.nativeLanguageName
+ property string negativeSign: InputMethod.locale.negativeSign
+ property string percent: InputMethod.locale.percent
+ property string pmText: InputMethod.locale.pmText
+ property string positiveSign: InputMethod.locale.positiveSign
+ property int textDirection: InputMethod.locale.textDirection
+ property var uiLanguages: InputMethod.locale.uiLanguages
+ property var weekDays: InputMethod.locale.weekDays
+ property string zeroDigit: InputMethod.locale.zeroDigit
+}
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index 38e1e585ce..a61a632d24 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -295,8 +295,9 @@ void tst_qqmlvaluetypes::sizef()
void tst_qqmlvaluetypes::locale()
{
- {
- QQmlComponent component(&engine, testFileUrl("locale_read.qml"));
+ for (const QUrl &testFile :
+ { testFileUrl("locale_read.qml"), testFileUrl("locale_read_singleton.qml") }) {
+ QQmlComponent component(&engine, testFile);
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
diff --git a/tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt b/tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt
index 19450aaef7..ea244fcbe4 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt
+++ b/tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt
@@ -23,6 +23,10 @@ qt_internal_add_test(tst_qqmlxmlhttprequest
TESTDATA ${test_data}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qqmlxmlhttprequest)
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
index 3353d8d5e1..d1dcf3829a 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
+++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
@@ -1093,6 +1093,10 @@ static const QString testString = QStringLiteral("Test-String");
void tst_qqmlxmlhttprequest::doFileRequest(std::function<void(QObject *component, QTemporaryFile &writeFile)> verifyFunction)
{
+#if defined(Q_OS_INTEGRITY)
+ QSKIP("There's no mounted filesystem on INTEGRITY.");
+#endif
+
// Create test files
QTemporaryFile writeFile;
QTemporaryFile readFile;
diff --git a/tests/auto/qml/qtqmlmodules/CMakeLists.txt b/tests/auto/qml/qtqmlmodules/CMakeLists.txt
index 2bff111bc7..6ff0cc01ae 100644
--- a/tests/auto/qml/qtqmlmodules/CMakeLists.txt
+++ b/tests/auto/qml/qtqmlmodules/CMakeLists.txt
@@ -22,6 +22,10 @@ qt_internal_add_test(tst_qtqmlmodules
TESTDATA ${test_data}
)
+if(QT_BUILD_STANDALONE_TESTS)
+ qt_import_qml_plugins(tst_qtqmlmodules)
+endif()
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
index e51cca9be4..d3cf585bb9 100644
--- a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
+++ b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
@@ -30,6 +30,7 @@
#include <qtest.h>
#include <QQmlEngine>
#include <private/qv4identifiertable_p.h>
+#include <private/qv4engine_p.h>
class tst_qv4identifiertable : public QObject
{
diff --git a/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml b/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
index f7e708e7aa..163aaa66f7 100644
--- a/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
+++ b/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
@@ -40,8 +40,7 @@ Item {
when: imageOnDisk.ready && imageOnDiskSmall.ready
function test_endresult_disk() {
- if ((Qt.platform.pluginName === "offscreen")
- || (Qt.platform.pluginName === "minimal"))
+ if (Qt.platform.pluginName === "minimal")
skip("grabImage does not work on offscreen/minimal platforms");
var image = grabImage(root);
@@ -77,8 +76,7 @@ Item {
}
function test_endresult_cache(data) {
- if ((Qt.platform.pluginName === "offscreen")
- || (Qt.platform.pluginName === "minimal"))
+ if (Qt.platform.pluginName === "minimal")
skip("grabImage does not work on offscreen/minimal platforms");
imageInCache.cache = data.cache;
diff --git a/tests/auto/quick/CMakeLists.txt b/tests/auto/quick/CMakeLists.txt
index de701f909d..03b9829b68 100644
--- a/tests/auto/quick/CMakeLists.txt
+++ b/tests/auto/quick/CMakeLists.txt
@@ -80,6 +80,7 @@ if(QT_FEATURE_private_tests)
add_subdirectory(qquickshadereffect)
add_subdirectory(qquickanimatedsprite)
add_subdirectory(qquickspritesequence)
+ add_subdirectory(qquickitemrhiintegration)
if(QT_FEATURE_opengl)
add_subdirectory(qquickframebufferobject)
diff --git a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
index b26a055e60..99e429c369 100644
--- a/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp
@@ -38,6 +38,7 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlproperty.h>
+#include <QQmlComponent>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
index 6296eb4da8..2120c0041d 100644
--- a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp
@@ -37,6 +37,7 @@
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#include <QQmlComponent>
Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests")
diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
index 136703d517..8f2ba0021c 100644
--- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
+++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
@@ -48,6 +48,8 @@
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
+#include <QQmlComponent>
+
#define EXPECT(cond) \
do { \
if (!errorAt && !(cond)) { \
@@ -147,17 +149,17 @@ void tst_QQuickAccessible::commonTests()
qDebug() << "testing" << accessibleRoleFileName;
- QQuickView *view = new QQuickView();
+ auto view = std::make_unique<QQuickView>();
// view->setFixedSize(240,320);
view->setSource(testFileUrl(accessibleRoleFileName));
view->show();
// view->setFocus();
QVERIFY(view->rootObject() != nullptr);
- QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(view);
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(view.get());
QVERIFY(iface);
- delete view;
+ view.reset();
QTestAccessibility::clearEvents();
}
@@ -168,12 +170,11 @@ void tst_QQuickAccessible::quickAttachedProperties()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0\nItem {\n"
"}", QUrl());
- QObject *object = component.create();
+ auto object = std::unique_ptr<QObject>(component.create());
QVERIFY(object != nullptr);
- QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object);
+ QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object.get());
QCOMPARE(attachedObject, static_cast<QObject*>(nullptr));
- delete object;
}
// Attaching to non-item
@@ -202,11 +203,11 @@ void tst_QQuickAccessible::quickAttachedProperties()
component.setData("import QtQuick 2.0\nItem {\n"
"Accessible.role: Accessible.Button\n"
"}", QUrl());
- QObject *object = component.create();
+ auto object = std::unique_ptr<QObject>(component.create());
QVERIFY(object != nullptr);
const auto attachedObject = qobject_cast<QQuickAccessibleAttached*>(
- QQuickAccessibleAttached::attachedProperties(object));
+ QQuickAccessibleAttached::attachedProperties(object.get()));
QVERIFY(attachedObject);
if (attachedObject) {
QVariant p = attachedObject->property("role");
@@ -220,7 +221,6 @@ void tst_QQuickAccessible::quickAttachedProperties()
QVERIFY2(p.value<QString>().isEmpty(), QTest::toString(p));
QCOMPARE(attachedObject->wasNameExplicitlySet(), false);
}
- delete object;
}
// Attached property
@@ -232,11 +232,11 @@ void tst_QQuickAccessible::quickAttachedProperties()
"Accessible.name: \"Donald\"\n"
"Accessible.description: \"Duck\"\n"
"}", QUrl());
- QObject *object = component.create();
+ auto object = std::unique_ptr<QObject>(component.create());
QVERIFY(object != nullptr);
const auto attachedObject = qobject_cast<QQuickAccessibleAttached*>(
- QQuickAccessibleAttached::attachedProperties(object));
+ QQuickAccessibleAttached::attachedProperties(object.get()));
QVERIFY(attachedObject);
if (attachedObject) {
QVariant p = attachedObject->property("role");
@@ -250,7 +250,6 @@ void tst_QQuickAccessible::quickAttachedProperties()
QCOMPARE(p.toString(), QLatin1String("Duck"));
QCOMPARE(attachedObject->wasNameExplicitlySet(), true);
}
- delete object;
}
// Check overriding of attached role for Text
@@ -262,10 +261,10 @@ void tst_QQuickAccessible::quickAttachedProperties()
"Accessible.name: \"TextButton\"\n"
"Accessible.description: \"Text Button\"\n"
"}", QUrl());
- QObject *object = component.create();
+ auto object = std::unique_ptr<QObject>(component.create());
QVERIFY(object != nullptr);
- QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object);
+ QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object.get());
QVERIFY(attachedObject);
if (attachedObject) {
QVariant p = attachedObject->property("role");
@@ -278,7 +277,6 @@ void tst_QQuickAccessible::quickAttachedProperties()
QCOMPARE(p.isNull(), false);
QCOMPARE(p.toString(), QLatin1String("Text Button"));
}
- delete object;
}
// Check overriding of attached role for Text
{
@@ -294,10 +292,10 @@ void tst_QQuickAccessible::quickAttachedProperties()
"Accessible.description: \"Text Button\"\n"
"}\n"
"}", QUrl());
- QObject *object = component.create();
+ auto object = std::unique_ptr<QObject>(component.create());
QVERIFY(object != nullptr);
- QQuickListView *listview = qobject_cast<QQuickListView *>(object);
+ QQuickListView *listview = qobject_cast<QQuickListView *>(object.get());
QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
QQuickText *childItem = QQuickVisualTestUtils::findItem<QQuickText>(contentItem, "acc_text");
@@ -316,7 +314,6 @@ void tst_QQuickAccessible::quickAttachedProperties()
QCOMPARE(p.isNull(), false);
QCOMPARE(p.toString(), QLatin1String("Text Button"));
}
- delete object;
}
// Check that a name can be implicitly set.
{
@@ -328,11 +325,11 @@ void tst_QQuickAccessible::quickAttachedProperties()
Accessible.role: Accessible.Button
Accessible.description: "Text Button"
})", QUrl());
- QScopedPointer<QObject> object(component.create());
+ auto object = std::unique_ptr<QObject>(component.create());
QVERIFY(object);
const auto attachedObject = qobject_cast<QQuickAccessibleAttached*>(
- QQuickAccessibleAttached::attachedProperties(object.data()));
+ QQuickAccessibleAttached::attachedProperties(object.get()));
QVERIFY(attachedObject);
QVERIFY(!attachedObject->wasNameExplicitlySet());
@@ -353,12 +350,12 @@ void tst_QQuickAccessible::basicPropertiesTest()
QAccessibleInterface *app = QAccessible::queryAccessibleInterface(qApp);
QCOMPARE(app->childCount(), 0);
- QQuickView *window = new QQuickView();
+ auto window = std::make_unique<QQuickView>();
window->setSource(testFileUrl("text.qml"));
window->show();
QCOMPARE(app->childCount(), 1);
- QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window);
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window.get());
QVERIFY(iface);
QCOMPARE(iface->childCount(), 1);
@@ -392,6 +389,7 @@ void tst_QQuickAccessible::basicPropertiesTest()
QCOMPARE(item->indexOfChild(text2), 1);
QVERIFY(!text2->state().editable);
QVERIFY(text2->state().readOnly);
+ QVERIFY(text2->state().focusable);
QCOMPARE(iface->indexOfChild(text2), -1);
QCOMPARE(text2->indexOfChild(item), -1);
@@ -483,7 +481,7 @@ void tst_QQuickAccessible::basicPropertiesTest()
attached->setRole(QAccessible::StaticText);
QVERIFY(!text3->state().readOnly);
- delete window;
+ window.reset();
QTestAccessibility::clearEvents();
}
@@ -502,14 +500,15 @@ QAccessibleInterface *topLevelChildAt(QAccessibleInterface *iface, int x, int y)
void tst_QQuickAccessible::hitTest()
{
- QQuickView *window = new QQuickView;
+ auto window = std::make_unique<QQuickView>();
window->setSource(testFileUrl("hittest.qml"));
window->show();
- QAccessibleInterface *windowIface = QAccessible::queryAccessibleInterface(window);
+ QAccessibleInterface *windowIface = QAccessible::queryAccessibleInterface(window.get());
QVERIFY(windowIface);
QAccessibleInterface *rootItem = windowIface->child(0);
- QRect rootRect = rootItem->rect();
+ // on Android the main window is always shown fullscreen
+ QRect rootRect = QRect(window->x(), window->y(), window->width(), window->height());
// check the root item from app
QAccessibleInterface *appIface = QAccessible::queryAccessibleInterface(qApp);
@@ -555,13 +554,13 @@ void tst_QQuickAccessible::hitTest()
}
}
- delete window;
+ window.reset();
QTestAccessibility::clearEvents();
}
void tst_QQuickAccessible::checkableTest()
{
- QScopedPointer<QQuickView> window(new QQuickView());
+ auto window = std::make_unique<QQuickView>();
window->setSource(testFileUrl("checkbuttons.qml"));
window->show();
@@ -574,7 +573,7 @@ void tst_QQuickAccessible::checkableTest()
QAccessible::State activatedChange;
activatedChange.active = true;
- QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window.data());
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window.get());
QVERIFY(iface);
QAccessibleInterface *root = iface->child(0);
@@ -638,7 +637,7 @@ void tst_QQuickAccessible::checkableTest()
void tst_QQuickAccessible::ignoredTest()
{
- QScopedPointer<QQuickView> window(new QQuickView());
+ auto window = std::make_unique<QQuickView>();
window->setSource(testFileUrl("ignored.qml"));
window->show();
@@ -651,7 +650,7 @@ void tst_QQuickAccessible::ignoredTest()
QAccessible::State activatedChange;
activatedChange.active = true;
- QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window.data());
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window.get());
QVERIFY(iface);
QAccessibleInterface *rectangleA = iface->child(0);
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index e2bac5ee39..2820762114 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -1863,9 +1863,8 @@ void tst_qquickanimations::fastFlickingBug()
void tst_qquickanimations::opacityAnimationFromZero()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
// not easy to verify this in threaded render loop
// since it's difficult to capture the first frame when scene graph
diff --git a/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp b/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
index f1cfa05d38..72bb774a74 100644
--- a/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
+++ b/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
@@ -39,6 +39,7 @@
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#include <QQmlComponent>
using namespace QQuickViewTestUtils;
diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
index 133583e72c..020097b9ef 100644
--- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
+++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
@@ -37,6 +37,7 @@
#include <qpa/qplatformintegration.h>
#include <private/qguiapplication_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QFont>
class tst_qquickapplication : public QQmlDataTest
{
diff --git a/tests/auto/quick/qquickbehaviors/bindable.h b/tests/auto/quick/qquickbehaviors/bindable.h
index ebdf8711a3..9bc01c4568 100644
--- a/tests/auto/quick/qquickbehaviors/bindable.h
+++ b/tests/auto/quick/qquickbehaviors/bindable.h
@@ -31,6 +31,8 @@
#include <QObject>
#include <QQuickItem>
#include <qqmlregistration.h>
+#include <QBindable>
+#include <qproperty.h>
class TestBindable : public QQuickItem
{
diff --git a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
index e963082a1a..7ce44ee9dc 100644
--- a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
+++ b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
@@ -591,9 +591,8 @@ void tst_qquickborderimage::progressAndStatusChanges()
#if QT_CONFIG(opengl)
void tst_qquickborderimage::borderImageMesh()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QQuickView *window = new QQuickView;
@@ -625,9 +624,8 @@ void tst_qquickborderimage::multiFrame_data()
void tst_qquickborderimage::multiFrame()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QFETCH(QString, qmlfile);
QFETCH(bool, asynchronous);
diff --git a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
index 3e9069d522..348948f5f6 100644
--- a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
+++ b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
@@ -33,6 +33,7 @@
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlexpression.h>
+#include <QQmlComponent>
template <typename T> static T evaluate(QObject *scope, const QString &expression)
{
diff --git a/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp b/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
index de7e3f1629..b7a7010a57 100644
--- a/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
+++ b/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
@@ -31,6 +31,7 @@
#include <QtGui/qstylehints.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
+#include <QtQml/QQmlComponent>
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlexpression.h>
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 315b6d4fca..2e790dad08 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -1663,7 +1663,8 @@ void tst_qquickflickable::cancelOnMouseGrab()
QQuickItem *item = window->rootObject()->findChild<QQuickItem*>("row");
auto mouse = QPointingDevice::primaryPointingDevice();
auto mousePriv = QPointingDevicePrivate::get(const_cast<QPointingDevice *>(mouse));
- QMouseEvent fakeMouseEv(QEvent::MouseMove, QPoint(130, 100), Qt::NoButton, Qt::LeftButton, Qt::NoModifier, mouse);
+ QMouseEvent fakeMouseEv(QEvent::MouseMove, QPoint(130, 100), QPoint(130, 100),
+ Qt::NoButton, Qt::LeftButton, Qt::NoModifier, mouse);
mousePriv->setExclusiveGrabber(&fakeMouseEv, fakeMouseEv.points().first(), item);
QTRY_COMPARE(flickable->contentX(), 0.);
diff --git a/tests/auto/quick/qquickframebufferobject/BLACKLIST b/tests/auto/quick/qquickframebufferobject/BLACKLIST
deleted file mode 100644
index de1bb7ad6d..0000000000
--- a/tests/auto/quick/qquickframebufferobject/BLACKLIST
+++ /dev/null
@@ -1,8 +0,0 @@
-[testInvalidate)
-# QTBUG-65614
-b2qt
-qnx
-
-[testThatStuffWorks]
-b2qt
-qnx
diff --git a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
index 19eeb5c60d..b69c3f7b96 100644
--- a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
+++ b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
@@ -28,6 +28,7 @@
#include <qtest.h>
+#include <QGuiApplication>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
#include <qopenglcontext.h>
@@ -209,6 +210,10 @@ void tst_QQuickFramebufferObject::testThatStuffWorks()
view.requestActivate();
QVERIFY(QTest::qWaitForWindowExposed(&view));
+ if (QGuiApplication::platformName() == "offscreen" &&
+ view.rendererInterface()->graphicsApi() == QSGRendererInterface::Software)
+ QSKIP("offscreen software rendering doesn't work with FBOs");
+
QImage result = view.grabWindow();
QCOMPARE(frameInfo.renderCount, 1);
@@ -249,6 +254,10 @@ void tst_QQuickFramebufferObject::testInvalidate()
view.requestActivate();
QVERIFY(QTest::qWaitForWindowExposed(&view));
+ if (QGuiApplication::platformName() == "offscreen" &&
+ view.rendererInterface()->graphicsApi() == QSGRendererInterface::Software)
+ QSKIP("offscreen software rendering doesn't work with FBOs");
+
QCOMPARE(frameInfo.fboSize, QSize(200, 200));
frameInfo.createFBOCount = 0;
diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
index 36c4b60718..37b3100e78 100644
--- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp
+++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
@@ -340,9 +340,8 @@ void tst_qquickimage::smooth()
void tst_qquickimage::mirror()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QMap<QQuickImage::FillMode, QImage> screenshots;
QList<QQuickImage::FillMode> fillModes;
@@ -555,9 +554,8 @@ void tst_qquickimage::big()
void tst_qquickimage::tiling_QTBUG_6716()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QFETCH(QString, source);
@@ -935,8 +933,7 @@ void tst_qquickimage::sourceClipRect()
QCOMPARE(image->implicitWidth(), sourceClipRect.isNull() ? 300 : sourceClipRect.width());
QCOMPARE(image->implicitHeight(), sourceClipRect.isNull() ? 300 : sourceClipRect.height());
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QImage contents = toUnscaledImage(window->grabWindow());
if (contents.width() < sourceClipRect.width())
@@ -1164,9 +1161,8 @@ void tst_qquickimage::highDpiFillModesAndSizes()
void tst_qquickimage::hugeImages()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QQuickView view;
view.setSource(testFileUrl("hugeImages.qml"));
@@ -1223,9 +1219,8 @@ void tst_qquickimage::multiFrame_data()
void tst_qquickimage::multiFrame()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QFETCH(QString, qmlfile);
QFETCH(bool, asynchronous);
diff --git a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
index 1a479f7c0c..e0e2c9daac 100644
--- a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
+++ b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
@@ -34,6 +34,7 @@
#include <QWaitCondition>
#include <QThreadPool>
#include <private/qqmlengine_p.h>
+#include <QQmlComponent>
Q_DECLARE_METATYPE(QQuickImageProvider*);
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index e4fe6df888..490933b06f 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -28,6 +28,7 @@
#include <qtest.h>
+#include <QtQml/QQmlComponent>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickwindow.h>
#include <QtQuick/qquickview.h>
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index 91ec08e854..623eb26dda 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -38,6 +38,7 @@
#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuick/private/qquicktextinput_p.h>
#include <QtQuick/private/qquickitemchangelistener_p.h>
+#include <QtQuick/private/qquickanchors_p.h>
#include <QtGui/qstylehints.h>
#include <private/qquickitem_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -3675,9 +3676,8 @@ void tst_QQuickItem::childAt()
void tst_QQuickItem::grab()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabToImage not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabToImage not functional on minimal platforms");
QQuickView view;
view.setSource(testFileUrl("grabToImage.qml"));
diff --git a/tests/auto/quick/qquickitemrhiintegration/CMakeLists.txt b/tests/auto/quick/qquickitemrhiintegration/CMakeLists.txt
new file mode 100644
index 0000000000..0076d7f82b
--- /dev/null
+++ b/tests/auto/quick/qquickitemrhiintegration/CMakeLists.txt
@@ -0,0 +1,36 @@
+qt_internal_add_test(tst_qquickitemrhiintegration
+ SOURCES
+ tst_qquickitemrhiintegration.cpp
+ rhiitem.cpp rhiitem.h rhiitem_p.h
+ testrhiitem.cpp testrhiitem.h
+ PUBLIC_LIBRARIES
+ Qt::CorePrivate
+ Qt::Gui
+ Qt::GuiPrivate
+ Qt::QmlPrivate
+ Qt::QuickPrivate
+ Qt::QuickTestUtilsPrivate
+)
+
+qt_internal_extend_target(tst_qquickitemrhiintegration CONDITION ANDROID OR IOS
+ DEFINES
+ QT_QMLTEST_DATADIR=\\\":/data\\\"
+)
+
+qt_internal_extend_target(tst_qquickitemrhiintegration CONDITION NOT ANDROID AND NOT IOS
+ DEFINES
+ QT_QMLTEST_DATADIR=\\\"${CMAKE_CURRENT_SOURCE_DIR}/data\\\"
+)
+
+qt_internal_add_shaders(tst_qquickitemrhiintegration "shaders"
+ PREFIX
+ "/"
+ FILES
+ "texture.vert"
+ "texture.frag"
+)
+
+qt_add_qml_module(tst_qquickitemrhiintegration
+ URI Test
+ VERSION 1.0
+)
diff --git a/tests/auto/quick/qquickitemrhiintegration/data/test.qml b/tests/auto/quick/qquickitemrhiintegration/data/test.qml
new file mode 100644
index 0000000000..1262936761
--- /dev/null
+++ b/tests/auto/quick/qquickitemrhiintegration/data/test.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick
+import Test
+
+Item {
+ width: 640
+ height: 480
+
+ Text {
+ id: apiInfo
+ color: "black"
+ font.pixelSize: 16
+ property int api: GraphicsInfo.api
+ text: {
+ if (GraphicsInfo.api === GraphicsInfo.OpenGLRhi)
+ "OpenGL on QRhi";
+ else if (GraphicsInfo.api === GraphicsInfo.Direct3D11Rhi)
+ "D3D11 on QRhi";
+ else if (GraphicsInfo.api === GraphicsInfo.VulkanRhi)
+ "Vulkan on QRhi";
+ else if (GraphicsInfo.api === GraphicsInfo.MetalRhi)
+ "Metal on QRhi";
+ else if (GraphicsInfo.api === GraphicsInfo.Null)
+ "Null on QRhi";
+ else
+ "Unknown API";
+ }
+ }
+
+ TestRhiItem {
+ anchors.centerIn: parent
+ width: 400
+ height: 400
+ color: "red"
+ }
+}
diff --git a/tests/auto/quick/qquickitemrhiintegration/rhiitem.cpp b/tests/auto/quick/qquickitemrhiintegration/rhiitem.cpp
new file mode 100644
index 0000000000..5bfd3a850d
--- /dev/null
+++ b/tests/auto/quick/qquickitemrhiintegration/rhiitem.cpp
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rhiitem_p.h"
+
+RhiItemNode::RhiItemNode(RhiItem *item)
+ : m_item(item)
+{
+ m_window = m_item->window();
+ Q_ASSERT(m_window);
+ connect(m_window, &QQuickWindow::beforeRendering, this, &RhiItemNode::render);
+ connect(m_window, &QQuickWindow::screenChanged, this, [this]() {
+ if (m_window->effectiveDevicePixelRatio() != m_dpr)
+ m_item->update();
+ });
+}
+
+RhiItemNode::~RhiItemNode()
+{
+ delete m_renderer;
+ delete m_sgWrapperTexture;
+ releaseNativeTexture();
+}
+
+QSGTexture *RhiItemNode::texture() const
+{
+ return m_sgWrapperTexture;
+}
+
+void RhiItemNode::createNativeTexture()
+{
+ Q_ASSERT(!m_texture);
+ Q_ASSERT(!m_pixelSize.isEmpty());
+
+ m_texture = m_rhi->newTexture(QRhiTexture::RGBA8, m_pixelSize, 1, QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource);
+ if (!m_texture->create()) {
+ qWarning("Failed to create RhiItem texture of size %dx%d", m_pixelSize.width(), m_pixelSize.height());
+ delete m_texture;
+ m_texture = nullptr;
+ }
+}
+
+void RhiItemNode::releaseNativeTexture()
+{
+ if (m_texture) {
+ m_texture->deleteLater();
+ m_texture = nullptr;
+ }
+}
+
+void RhiItemNode::sync()
+{
+ if (!m_rhi) {
+ QSGRendererInterface *rif = m_window->rendererInterface();
+ m_rhi = static_cast<QRhi *>(rif->getResource(m_window, QSGRendererInterface::RhiResource));
+ if (!m_rhi) {
+ qWarning("No QRhi found for window %p, RhiItem will not be functional", m_window);
+ return;
+ }
+ }
+
+ QSize newSize(m_item->explicitTextureWidth(), m_item->explicitTextureHeight());
+ if (newSize.isEmpty()) {
+ m_dpr = m_window->effectiveDevicePixelRatio();
+ const int minTexSize = m_rhi->resourceLimit(QRhi::TextureSizeMin);
+ newSize = QSize(qMax<int>(minTexSize, m_item->width()),
+ qMax<int>(minTexSize, m_item->height())) * m_dpr;
+ }
+
+ bool needsNew = !m_sgWrapperTexture;
+ if (newSize != m_pixelSize) {
+ needsNew = true;
+ m_pixelSize = newSize;
+ }
+
+ if (needsNew) {
+ if (m_texture && m_sgWrapperTexture) {
+ m_texture->setPixelSize(m_pixelSize);
+ if (m_texture->create())
+ m_sgWrapperTexture->setTextureSize(m_pixelSize);
+ else
+ qWarning("Failed to recreate RhiItem texture of size %dx%d", m_pixelSize.width(), m_pixelSize.height());
+ } else {
+ delete m_sgWrapperTexture;
+ m_sgWrapperTexture = nullptr;
+ releaseNativeTexture();
+ createNativeTexture();
+ if (m_texture) {
+ m_sgWrapperTexture = new QSGPlainTexture;
+ m_sgWrapperTexture->setOwnsTexture(false);
+ m_sgWrapperTexture->setTexture(m_texture);
+ m_sgWrapperTexture->setTextureSize(m_pixelSize);
+ m_sgWrapperTexture->setHasAlphaChannel(m_item->alphaBlending());
+ setTexture(m_sgWrapperTexture);
+ }
+ }
+ RhiItemPrivate::get(m_item)->effectiveTextureSize = m_pixelSize;
+ emit m_item->effectiveTextureSizeChanged();
+ if (m_texture)
+ m_renderer->initialize(m_rhi, m_texture);
+ }
+
+ if (m_sgWrapperTexture && m_sgWrapperTexture->hasAlphaChannel() != m_item->alphaBlending()) {
+ m_sgWrapperTexture->setHasAlphaChannel(m_item->alphaBlending());
+ // hasAlphaChannel is mapped to QSGMaterial::Blending in setTexture() so that has to be called again
+ setTexture(m_sgWrapperTexture);
+ }
+
+ m_renderer->synchronize(m_item);
+}
+
+void RhiItemNode::render()
+{
+ // called before Qt Quick starts recording its main render pass
+
+ if (!m_rhi || !m_texture || !m_renderer)
+ return;
+
+ if (!m_renderPending)
+ return;
+
+ QSGRendererInterface *rif = m_window->rendererInterface();
+ QRhiCommandBuffer *cb = nullptr;
+ QRhiSwapChain *swapchain = static_cast<QRhiSwapChain *>(
+ rif->getResource(m_window, QSGRendererInterface::RhiSwapchainResource));
+ cb = swapchain ? swapchain->currentFrameCommandBuffer()
+ : static_cast<QRhiCommandBuffer *>(rif->getResource(m_window, QSGRendererInterface::RhiRedirectCommandBuffer));
+ if (!cb) {
+ qWarning("Neither swapchain nor redirected command buffer are available.");
+ return;
+ }
+
+ m_renderPending = false;
+ m_renderer->render(cb);
+
+ markDirty(QSGNode::DirtyMaterial);
+ emit textureChanged();
+}
+
+void RhiItemNode::scheduleUpdate()
+{
+ m_renderPending = true;
+ m_window->update(); // ensure getting to beforeRendering() at some point
+}
+
+void RhiItemNode::setMirrorVertically(bool b)
+{
+ if (m_rhi->isYUpInFramebuffer())
+ b = !b;
+
+ setTextureCoordinatesTransform(b ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform);
+}
+
+RhiItem::RhiItem(QQuickItem *parent)
+ : QQuickItem(*new RhiItemPrivate, parent)
+{
+ setFlag(ItemHasContents);
+}
+
+QSGNode *RhiItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
+{
+ Q_D(RhiItem);
+ RhiItemNode *n = static_cast<RhiItemNode *>(node);
+
+ // Changing to an empty size should not involve destroying and then later
+ // recreating the node, because we do not know how expensive the user's
+ // renderer setup is. Rather, keep the node if it already exist, and clamp
+ // all accesses to width and height. Hence the unusual !n condition here.
+ if (!n && (width() <= 0 || height() <= 0))
+ return nullptr;
+
+ if (!n) {
+ if (!d->node)
+ d->node = new RhiItemNode(this);
+ n = d->node;
+ }
+
+ if (!n->hasRenderer()) {
+ RhiItemRenderer *r = createRenderer();
+ if (r) {
+ r->data = n;
+ n->setRenderer(r);
+ } else {
+ qWarning("No RhiItemRenderer was created; the item will not render");
+ delete n;
+ d->node = nullptr;
+ return nullptr;
+ }
+ }
+
+ n->sync();
+
+ if (!n->isValid()) {
+ delete n;
+ d->node = nullptr;
+ return nullptr;
+ }
+
+ n->setMirrorVertically(d->mirrorVertically);
+ n->setFiltering(QSGTexture::Linear);
+ n->setRect(0, 0, qMax<int>(0, width()), qMax<int>(0, height()));
+
+ n->scheduleUpdate();
+
+ return n;
+}
+
+void RhiItem::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ QQuickItem::geometryChange(newGeometry, oldGeometry);
+ if (newGeometry.size() != oldGeometry.size())
+ update();
+}
+
+void RhiItem::releaseResources()
+{
+ // called on the gui thread if the item is removed from scene
+
+ Q_D(RhiItem);
+ d->node = nullptr;
+}
+
+void RhiItem::invalidateSceneGraph()
+{
+ // called on the render thread when the scenegraph is invalidated
+
+ Q_D(RhiItem);
+ d->node = nullptr;
+}
+
+bool RhiItem::isTextureProvider() const
+{
+ return true;
+}
+
+QSGTextureProvider *RhiItem::textureProvider() const
+{
+ if (QQuickItem::isTextureProvider()) // e.g. if Item::layer::enabled == true
+ return QQuickItem::textureProvider();
+
+ QQuickWindow *w = window();
+ if (!w || !w->isSceneGraphInitialized() || QThread::currentThread() != QQuickWindowPrivate::get(w)->context->thread()) {
+ qWarning("RhiItem::textureProvider: can only be queried on the rendering thread of an exposed window");
+ return nullptr;
+ }
+
+ Q_D(const RhiItem);
+ if (!d->node) // create a node to have a provider, the texture will be null but that's ok
+ d->node = new RhiItemNode(const_cast<RhiItem *>(this));
+
+ return d->node;
+}
+
+int RhiItem::explicitTextureWidth() const
+{
+ Q_D(const RhiItem);
+ return d->explicitTextureWidth;
+}
+
+void RhiItem::setExplicitTextureWidth(int w)
+{
+ Q_D(RhiItem);
+ if (d->explicitTextureWidth == w)
+ return;
+
+ d->explicitTextureWidth = w;
+ emit explicitTextureWidthChanged();
+ update();
+}
+
+int RhiItem::explicitTextureHeight() const
+{
+ Q_D(const RhiItem);
+ return d->explicitTextureHeight;
+}
+
+void RhiItem::setExplicitTextureHeight(int h)
+{
+ Q_D(RhiItem);
+ if (d->explicitTextureHeight == h)
+ return;
+
+ d->explicitTextureHeight = h;
+ emit explicitTextureHeightChanged();
+ update();
+}
+
+QSize RhiItem::effectiveTextureSize() const
+{
+ Q_D(const RhiItem);
+ return d->effectiveTextureSize;
+}
+
+bool RhiItem::alphaBlending() const
+{
+ Q_D(const RhiItem);
+ return d->blend;
+}
+
+void RhiItem::setAlphaBlending(bool enable)
+{
+ Q_D(RhiItem);
+ if (d->blend == enable)
+ return;
+
+ d->blend = enable;
+ emit alphaBlendingChanged();
+ update();
+}
+
+bool RhiItem::mirrorVertically() const
+{
+ Q_D(const RhiItem);
+ return d->mirrorVertically;
+}
+
+void RhiItem::setMirrorVertically(bool enable)
+{
+ Q_D(RhiItem);
+ if (d->mirrorVertically == enable)
+ return;
+
+ d->mirrorVertically = enable;
+ emit mirrorVerticallyChanged();
+ update();
+}
+
+void RhiItemRenderer::update()
+{
+ if (data)
+ static_cast<RhiItemNode *>(data)->scheduleUpdate();
+}
+
+RhiItemRenderer::~RhiItemRenderer()
+{
+}
+
+void RhiItemRenderer::initialize(QRhi *rhi, QRhiTexture *outputTexture)
+{
+ Q_UNUSED(rhi);
+ Q_UNUSED(outputTexture);
+}
+
+void RhiItemRenderer::synchronize(RhiItem *item)
+{
+ Q_UNUSED(item);
+}
+
+void RhiItemRenderer::render(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+}
diff --git a/tests/auto/quick/qquickitemrhiintegration/rhiitem.h b/tests/auto/quick/qquickitemrhiintegration/rhiitem.h
new file mode 100644
index 0000000000..32de7922a0
--- /dev/null
+++ b/tests/auto/quick/qquickitemrhiintegration/rhiitem.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RHIITEM_H
+#define RHIITEM_H
+
+#include <QQuickItem>
+#include <QtGui/private/qrhi_p.h>
+
+class RhiItem;
+class RhiItemPrivate;
+
+class RhiItemRenderer
+{
+public:
+ virtual ~RhiItemRenderer();
+ virtual void initialize(QRhi *rhi, QRhiTexture *outputTexture);
+ virtual void synchronize(RhiItem *item);
+ virtual void render(QRhiCommandBuffer *cb);
+
+ void update();
+
+private:
+ void *data;
+ friend class RhiItem;
+};
+
+class RhiItem : public QQuickItem
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(RhiItem)
+
+ Q_PROPERTY(int explicitTextureWidth READ explicitTextureWidth WRITE setExplicitTextureWidth NOTIFY explicitTextureWidthChanged)
+ Q_PROPERTY(int explicitTextureHeight READ explicitTextureHeight WRITE setExplicitTextureHeight NOTIFY explicitTextureHeightChanged)
+ Q_PROPERTY(QSize effectiveTextureSize READ effectiveTextureSize NOTIFY effectiveTextureSizeChanged)
+ Q_PROPERTY(bool alphaBlending READ alphaBlending WRITE setAlphaBlending NOTIFY alphaBlendingChanged)
+ Q_PROPERTY(bool mirrorVertically READ mirrorVertically WRITE setMirrorVertically NOTIFY mirrorVerticallyChanged)
+
+public:
+ RhiItem(QQuickItem *parent = nullptr);
+
+ virtual RhiItemRenderer *createRenderer() = 0;
+
+ int explicitTextureWidth() const;
+ void setExplicitTextureWidth(int w);
+ int explicitTextureHeight() const;
+ void setExplicitTextureHeight(int h);
+
+ QSize effectiveTextureSize() const;
+
+ bool alphaBlending() const;
+ void setAlphaBlending(bool enable);
+
+ bool mirrorVertically() const;
+ void setMirrorVertically(bool enable);
+
+protected:
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override;
+ void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
+ void releaseResources() override;
+ bool isTextureProvider() const override;
+ QSGTextureProvider *textureProvider() const override;
+
+Q_SIGNALS:
+ void explicitTextureWidthChanged();
+ void explicitTextureHeightChanged();
+ void effectiveTextureSizeChanged();
+ void alphaBlendingChanged();
+ void mirrorVerticallyChanged();
+
+private Q_SLOTS:
+ void invalidateSceneGraph();
+};
+
+#endif
diff --git a/tests/auto/quick/qquickitemrhiintegration/rhiitem_p.h b/tests/auto/quick/qquickitemrhiintegration/rhiitem_p.h
new file mode 100644
index 0000000000..00ffe9cb59
--- /dev/null
+++ b/tests/auto/quick/qquickitemrhiintegration/rhiitem_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RHIITEM_P_H
+#define RHIITEM_P_H
+
+#include "rhiitem.h"
+#include <QSGSimpleTextureNode>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qsgplaintexture_p.h>
+
+class RhiItemNode : public QSGTextureProvider, public QSGSimpleTextureNode
+{
+ Q_OBJECT
+
+public:
+ RhiItemNode(RhiItem *item);
+ ~RhiItemNode();
+
+ QSGTexture *texture() const override;
+
+ void sync();
+ bool isValid() const { return m_rhi && m_texture && m_sgWrapperTexture; }
+ void scheduleUpdate();
+ bool hasRenderer() const { return m_renderer; }
+ void setRenderer(RhiItemRenderer *r) { m_renderer = r; }
+ void setMirrorVertically(bool b);
+
+private slots:
+ void render();
+
+private:
+ void createNativeTexture();
+ void releaseNativeTexture();
+
+ RhiItem *m_item;
+ QQuickWindow *m_window;
+ QSize m_pixelSize;
+ qreal m_dpr = 0.0f;
+ QRhi *m_rhi = nullptr;
+ QRhiTexture *m_texture = nullptr;
+ QSGPlainTexture *m_sgWrapperTexture = nullptr;
+ bool m_renderPending = true;
+ RhiItemRenderer *m_renderer = nullptr;
+};
+
+class RhiItemPrivate : public QQuickItemPrivate
+{
+ Q_DECLARE_PUBLIC(RhiItem)
+public:
+ static RhiItemPrivate *get(RhiItem *item) { return item->d_func(); }
+ mutable RhiItemNode *node = nullptr;
+ int explicitTextureWidth = 0;
+ int explicitTextureHeight = 0;
+ bool blend = true;
+ bool mirrorVertically = false;
+ QSize effectiveTextureSize;
+};
+
+#endif
diff --git a/tests/auto/quick/qquickitemrhiintegration/testrhiitem.cpp b/tests/auto/quick/qquickitemrhiintegration/testrhiitem.cpp
new file mode 100644
index 0000000000..c5a83f3f65
--- /dev/null
+++ b/tests/auto/quick/qquickitemrhiintegration/testrhiitem.cpp
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "testrhiitem.h"
+#include <QFile>
+
+static const QSize TEX_SIZE(512, 512);
+
+void TestRenderer::initialize(QRhi *rhi, QRhiTexture *outputTexture)
+{
+ m_rhi = rhi;
+ m_output = outputTexture;
+
+ if (!m_ds) {
+ m_ds.reset(m_rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, m_output->pixelSize()));
+ m_ds->create();
+ } else if (m_ds->pixelSize() != m_output->pixelSize()) {
+ m_ds->setPixelSize(m_output->pixelSize());
+ m_ds->create();
+ }
+
+ if (!m_rt) {
+ m_rt.reset(m_rhi->newTextureRenderTarget({ { m_output }, m_ds.data() }));
+ m_rp.reset(m_rt->newCompatibleRenderPassDescriptor());
+ m_rt->setRenderPassDescriptor(m_rp.data());
+ m_rt->create();
+ }
+
+ if (!scene.vbuf)
+ initScene();
+
+ const QSize outputSize = m_output->pixelSize();
+ scene.mvp = m_rhi->clipSpaceCorrMatrix();
+ scene.mvp.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 1000.0f);
+ scene.mvp.translate(0, 0, -4);
+ if (!scene.resourceUpdates)
+ scene.resourceUpdates = m_rhi->nextResourceUpdateBatch();
+ scene.resourceUpdates->updateDynamicBuffer(scene.ubuf.data(), 0, 64, scene.mvp.constData());
+}
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+void TestRenderer::updateTexture()
+{
+ QImage img(TEX_SIZE, QImage::Format_RGBA8888);
+ img.fill(itemData.color);
+
+ if (!scene.resourceUpdates)
+ scene.resourceUpdates = m_rhi->nextResourceUpdateBatch();
+
+ scene.resourceUpdates->uploadTexture(scene.tex.data(), img);
+}
+
+void TestRenderer::initScene()
+{
+ static const float tri[] = {
+ 0.0f, 0.5f, 0.0f, 1.0f,
+ -0.5f, -0.5f, 0.0f, 0.0f,
+ 0.5f, -0.5f, 1.0f, 0.0f
+ };
+
+ scene.vbuf.reset(m_rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(tri)));
+ scene.vbuf->create();
+
+ scene.resourceUpdates = m_rhi->nextResourceUpdateBatch();
+ scene.resourceUpdates->uploadStaticBuffer(scene.vbuf.data(), tri);
+
+ scene.ubuf.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68));
+ scene.ubuf->create();
+
+ const qint32 flip = m_rhi->isYUpInFramebuffer() ? 1 : 0;
+ scene.resourceUpdates->updateDynamicBuffer(scene.ubuf.data(), 64, 4, &flip);
+
+ scene.tex.reset(m_rhi->newTexture(QRhiTexture::RGBA8, TEX_SIZE));
+ scene.tex->create();
+
+ scene.sampler.reset(m_rhi->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge));
+ scene.sampler->create();
+
+ scene.srb.reset(m_rhi->newShaderResourceBindings());
+ scene.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, scene.ubuf.data()),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, scene.tex.data(), scene.sampler.data())
+ });
+ scene.srb->create();
+
+ scene.ps.reset(m_rhi->newGraphicsPipeline());
+ scene.ps->setDepthTest(true);
+ scene.ps->setDepthWrite(true);
+ scene.ps->setDepthOp(QRhiGraphicsPipeline::Less);
+ scene.ps->setCullMode(QRhiGraphicsPipeline::Back);
+ scene.ps->setFrontFace(QRhiGraphicsPipeline::CCW);
+ QShader vs = getShader(QLatin1String(":/texture.vert.qsb"));
+ Q_ASSERT(vs.isValid());
+ QShader fs = getShader(QLatin1String(":/texture.frag.qsb"));
+ Q_ASSERT(fs.isValid());
+ scene.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 4 * sizeof(float) },
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) }
+ });
+ scene.ps->setVertexInputLayout(inputLayout);
+ scene.ps->setShaderResourceBindings(scene.srb.data());
+ scene.ps->setRenderPassDescriptor(m_rp.data());
+ scene.ps->create();
+}
+
+void TestRenderer::synchronize(RhiItem *rhiItem)
+{
+ TestRhiItem *item = static_cast<TestRhiItem *>(rhiItem);
+ if (item->color() != itemData.color) {
+ itemData.color = item->color();
+ updateTexture();
+ }
+}
+
+void TestRenderer::render(QRhiCommandBuffer *cb)
+{
+ QRhiResourceUpdateBatch *rub = scene.resourceUpdates;
+ if (rub)
+ scene.resourceUpdates = nullptr;
+
+ const QColor clearColor = QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f);
+ cb->beginPass(m_rt.data(), clearColor, { 1.0f, 0 }, rub);
+
+ cb->setGraphicsPipeline(scene.ps.data());
+ const QSize outputSize = m_output->pixelSize();
+ cb->setViewport(QRhiViewport(0, 0, outputSize.width(), outputSize.height()));
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBindings[] = {
+ { scene.vbuf.data(), 0 },
+ };
+ cb->setVertexInput(0, 1, vbufBindings);
+ cb->draw(3);
+
+ cb->endPass();
+}
+
+void TestRhiItem::setColor(QColor c)
+{
+ if (m_color == c)
+ return;
+
+ m_color = c;
+ emit colorChanged();
+ update();
+}
diff --git a/tests/auto/quick/qquickitemrhiintegration/testrhiitem.h b/tests/auto/quick/qquickitemrhiintegration/testrhiitem.h
new file mode 100644
index 0000000000..735c8e5355
--- /dev/null
+++ b/tests/auto/quick/qquickitemrhiintegration/testrhiitem.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESTRHIITEM_H
+#define TESTRHIITEM_H
+
+#include "rhiitem.h"
+
+class TestRenderer : public RhiItemRenderer
+{
+public:
+ void initialize(QRhi *rhi, QRhiTexture *outputTexture) override;
+ void synchronize(RhiItem *item) override;
+ void render(QRhiCommandBuffer *cb) override;
+
+private:
+ QRhi *m_rhi = nullptr;
+ QRhiTexture *m_output = nullptr;
+ QScopedPointer<QRhiRenderBuffer> m_ds;
+ QScopedPointer<QRhiTextureRenderTarget> m_rt;
+ QScopedPointer<QRhiRenderPassDescriptor> m_rp;
+
+ struct {
+ QRhiResourceUpdateBatch *resourceUpdates = nullptr;
+ QScopedPointer<QRhiBuffer> vbuf;
+ QScopedPointer<QRhiBuffer> ubuf;
+ QScopedPointer<QRhiShaderResourceBindings> srb;
+ QScopedPointer<QRhiGraphicsPipeline> ps;
+ QScopedPointer<QRhiSampler> sampler;
+ QScopedPointer<QRhiTexture> tex;
+ QMatrix4x4 mvp;
+ } scene;
+
+ struct {
+ QColor color;
+ } itemData;
+
+ void initScene();
+ void updateTexture();
+};
+
+class TestRhiItem : public RhiItem
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(TestRhiItem)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+
+public:
+ RhiItemRenderer *createRenderer() override { return new TestRenderer; }
+
+ QColor color() const { return m_color; }
+ void setColor(QColor c);
+
+signals:
+ void colorChanged();
+
+private:
+ QColor m_color;
+};
+
+#endif
diff --git a/tests/auto/quick/qquickitemrhiintegration/texture.frag b/tests/auto/quick/qquickitemrhiintegration/texture.frag
new file mode 100644
index 0000000000..a7b8bce0ad
--- /dev/null
+++ b/tests/auto/quick/qquickitemrhiintegration/texture.frag
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec2 v_texcoord;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ int flip;
+};
+
+layout(binding = 1) uniform sampler2D tex;
+
+void main()
+{
+ vec4 c = texture(tex, v_texcoord);
+ fragColor = vec4(c.rgb * c.a, c.a);
+}
diff --git a/tests/auto/quick/qquickitemrhiintegration/texture.vert b/tests/auto/quick/qquickitemrhiintegration/texture.vert
new file mode 100644
index 0000000000..bf678d1e9b
--- /dev/null
+++ b/tests/auto/quick/qquickitemrhiintegration/texture.vert
@@ -0,0 +1,19 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec2 texcoord;
+
+layout(location = 0) out vec2 v_texcoord;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ int flip;
+};
+
+void main()
+{
+ v_texcoord = texcoord;
+ if (flip != 0)
+ v_texcoord.y = 1.0 - v_texcoord.y;
+ gl_Position = mvp * position;
+}
diff --git a/tests/auto/quick/qquickitemrhiintegration/tst_qquickitemrhiintegration.cpp b/tests/auto/quick/qquickitemrhiintegration/tst_qquickitemrhiintegration.cpp
new file mode 100644
index 0000000000..0c8581d907
--- /dev/null
+++ b/tests/auto/quick/qquickitemrhiintegration/tst_qquickitemrhiintegration.cpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+
+#include <QtGui/private/qrhi_p.h>
+
+#include <QQuickView>
+#include <QSGRendererInterface>
+#include <private/qsgrhisupport_p.h>
+
+class tst_QQuickItemRhiIntegration : public QQmlDataTest
+{
+ Q_OBJECT
+
+public:
+ tst_QQuickItemRhiIntegration();
+
+private slots:
+ void initTestCase() override;
+ void cleanupTestCase();
+ void rhiItem();
+};
+
+tst_QQuickItemRhiIntegration::tst_QQuickItemRhiIntegration()
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
+{
+}
+
+void tst_QQuickItemRhiIntegration::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ qDebug() << "RHI backend:" << QSGRhiSupport::instance()->rhiBackendName();
+}
+
+void tst_QQuickItemRhiIntegration::cleanupTestCase()
+{
+}
+
+void tst_QQuickItemRhiIntegration::rhiItem()
+{
+ if (QGuiApplication::platformName() == QLatin1String("offscreen")
+ || QGuiApplication::platformName() == QLatin1String("minimal"))
+ {
+ QSKIP("Skipping on offscreen/minimal");
+ }
+
+ // Load up a scene that instantiates a TestRhiItem, which in turn
+ // renders a triangle with QRhi into a QRhiTexture and then draws
+ // a quad textured with it.
+
+ QQuickView view;
+ view.setSource(testFileUrl(QLatin1String("test.qml")));
+ view.setResizeMode(QQuickView::SizeViewToRootObject);
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ if (!QSGRendererInterface::isApiRhiBased(view.rendererInterface()->graphicsApi()))
+ QSKIP("Scenegraph does not use QRhi, test is pointless");
+
+ QImage result = view.grabWindow();
+ QVERIFY(!result.isNull());
+
+ const int tolerance = 5;
+
+ // The result is a red triangle in the center of the view, confirm at least one pixel.
+ QRgb a = result.pixel(result.width() / 2, result.height() / 2);
+ QRgb b = QColor(Qt::red).rgb();
+ QVERIFY(qAbs(qRed(a) - qRed(b)) <= tolerance
+ && qAbs(qGreen(a) - qGreen(b)) <= tolerance
+ && qAbs(qBlue(a) - qBlue(b)) <= tolerance);
+}
+
+#include "tst_qquickitemrhiintegration.moc"
+
+QTEST_MAIN(tst_QQuickItemRhiIntegration)
diff --git a/tests/auto/quick/qquicklayouts/BLACKLIST b/tests/auto/quick/qquicklayouts/BLACKLIST
index a9e6a444af..5859d0f7cd 100644
--- a/tests/auto/quick/qquicklayouts/BLACKLIST
+++ b/tests/auto/quick/qquicklayouts/BLACKLIST
@@ -1,2 +1,11 @@
[Tests_GridLayout::test_spacings]
qnx
+#QTBUG-101327
+[tst_stacklayout::compile]
+qnx
+#QTBUG-101327
+[tst_gridlayout::compile]
+qnx
+#QTBUG-101327
+[tst_rowlayout::compile]
+qnx
diff --git a/tests/auto/quick/qquicklistview/data/qtbug48044.qml b/tests/auto/quick/qquicklistview/data/qtbug48044.qml
index d318643c1c..368b6bd4bd 100644
--- a/tests/auto/quick/qquicklistview/data/qtbug48044.qml
+++ b/tests/auto/quick/qquicklistview/data/qtbug48044.qml
@@ -116,7 +116,7 @@ Item {
color: header ? "yellow" : "cyan"
border.color: "black"
height: 50
- width: parent.width
+ width: listView.width
Text {
anchors.centerIn: parent
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 6975fa2dbd..d3ecdaae68 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -37,11 +37,13 @@
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlincubator.h>
+#include <QtQml/qqmlcomponent.h>
#include <QtQuick/private/qquickitemview_p_p.h>
#include <QtQuick/private/qquicklistview_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
+#include <QtQuick/private/qquicktransition_p.h>
#include <QtQmlModels/private/qqmlobjectmodel_p.h>
#include <QtQmlModels/private/qqmllistmodel_p.h>
#include <QtQmlModels/private/qqmldelegatemodel_p.h>
diff --git a/tests/auto/quick/qquickloader/data/noEngine.qml b/tests/auto/quick/qquickloader/data/noEngine.qml
new file mode 100644
index 0000000000..19e619f32e
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/noEngine.qml
@@ -0,0 +1,32 @@
+import QtQuick 2
+
+Item {
+ id: root
+ property bool a: false
+ property int changes: 0
+ onAChanged: {
+ m.model = 0
+ m.model = 1
+ ++changes;
+ }
+
+ Repeater {
+ id: m
+ model: 1
+
+ Item {
+ Timer {
+ onTriggered: {
+ root.a = true
+ l.source = "loaded.qml"
+ }
+ interval: 0
+ running: true
+ }
+
+ Loader {
+ id: l
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index cf1c4fcce0..e990e94bc3 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -134,6 +134,7 @@ private slots:
void setSourceAndCheckStatus();
void asyncLoaderRace();
+ void noEngine();
};
Q_DECLARE_METATYPE(QList<QQmlError>)
@@ -1533,6 +1534,20 @@ void tst_QQuickLoader::asyncLoaderRace()
QCOMPARE(loader->item(), nullptr);
}
+void tst_QQuickLoader::noEngine()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("noEngine.qml");
+ QQmlComponent component(&engine, url);
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+
+ const QString message = url.toString()
+ + QStringLiteral(":27:13: QML Loader: createComponent: Cannot find a QML engine.");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ QTRY_COMPARE(o->property("changes").toInt(), 1);
+}
+
QTEST_MAIN(tst_QQuickLoader)
#include "tst_qquickloader.moc"
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index 0cbb047048..3d1f967b24 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -41,6 +41,8 @@
#include <QtGui/qstylehints.h>
#include <QtGui/QCursor>
#include <QtGui/QScreen>
+#include <QEvent>
+#include <QQmlComponent>
#include <qpa/qwindowsysteminterface.h>
Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
@@ -741,7 +743,9 @@ void tst_QQuickMouseArea::updateMouseAreaPosOnResize()
QCOMPARE(mouseRegion->mouseX(), 0.0);
QCOMPARE(mouseRegion->mouseY(), 0.0);
- QMouseEvent event(QEvent::MouseButtonPress, rect->position().toPoint(), Qt::LeftButton, Qt::LeftButton, {});
+ QMouseEvent event(QEvent::MouseButtonPress, rect->position().toPoint(),
+ window.mapToGlobal(rect->position().toPoint()),
+ Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &event);
QVERIFY(!mouseRegion->property("emitPositionChanged").toBool());
@@ -854,8 +858,10 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
QCOMPARE(window.rootObject()->property("released").toInt(), expectedRelease);
QCOMPARE(window.rootObject()->property("clicked").toInt(), expectedClicks);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100),
+ window.mapToGlobal(QPoint(100, 100)), Qt::LeftButton, Qt::LeftButton, {});
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100),
+ window.mapToGlobal(QPoint(100, 100)), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent);
@@ -872,7 +878,8 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
QCOMPARE(window.rootObject()->property("clicked").toInt(), ++expectedClicks);
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent pressEvent2(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, {});
+ QMouseEvent pressEvent2(QEvent::MouseButtonDblClick, QPoint(100, 100),
+ window.mapToGlobal(QPoint(100, 100)), Qt::LeftButton, Qt::LeftButton, {});
QGuiApplication::sendEvent(&window, &pressEvent2);
QTRY_VERIFY(window.rootObject()->property("pressed").toBool());
@@ -918,16 +925,19 @@ void tst_QQuickMouseArea::doubleClick()
// The sequence for a double click is:
// press, release, (click), press, double click, release
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, {});
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100),
+ window.mapToGlobal(QPoint(100, 100)), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, {});
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100),
+ window.mapToGlobal(QPoint(100, 100)), button, button, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("released").toInt(), 1);
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent pressEvent2 = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, {});
+ QMouseEvent pressEvent2 = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100),
+ window.mapToGlobal(QPoint(100, 100)), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent2);
QGuiApplication::sendEvent(&window, &releaseEvent);
@@ -949,10 +959,12 @@ void tst_QQuickMouseArea::clickTwice()
QVERIFY(mouseArea);
mouseArea->setAcceptedButtons(acceptedButtons);
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, {});
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100),
+ window.mapToGlobal(QPoint(100, 100)), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, {});
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100),
+ window.mapToGlobal(QPoint(100, 100)), button, button, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("pressed").toInt(), 1);
@@ -961,7 +973,8 @@ void tst_QQuickMouseArea::clickTwice()
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent pressEvent2 = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, {});
+ QMouseEvent pressEvent2 = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100),
+ window.mapToGlobal(QPoint(100, 100)), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent2);
QGuiApplication::sendEvent(&window, &releaseEvent);
@@ -984,16 +997,19 @@ void tst_QQuickMouseArea::invalidClick()
// The sequence for a double click is:
// press, release, (click), press, double click, release
- QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, {});
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100),
+ window.mapToGlobal(QPoint(100, 100)), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, {});
+ QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100),
+ window.mapToGlobal(QPoint(100, 100)), button, button, {});
QGuiApplication::sendEvent(&window, &releaseEvent);
QCOMPARE(window.rootObject()->property("released").toInt(), 0);
QGuiApplication::sendEvent(&window, &pressEvent);
- QMouseEvent pressEvent2 = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, {});
+ QMouseEvent pressEvent2 = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100),
+ window.mapToGlobal(QPoint(100, 100)), button, button, {});
QGuiApplication::sendEvent(&window, &pressEvent2);
QGuiApplication::sendEvent(&window, &releaseEvent);
@@ -1273,9 +1289,8 @@ void tst_QQuickMouseArea::hoverPropagation()
void tst_QQuickMouseArea::hoverVisible()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QQuickView window;
QVERIFY(QQuickTest::showView(window, testFileUrl("hoverVisible.qml")));
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index 8f45368f1c..2a0e1e5b6d 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -44,6 +44,7 @@
#include <QtGui/qstandarditemmodel.h>
#include <QStringListModel>
#include <QFile>
+#include <QEvent>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
@@ -1539,7 +1540,8 @@ void tst_QQuickPathView::mouseDrag()
QTest::qWait(100);
{
- QMouseEvent mv(QEvent::MouseMove, QPoint(50,100), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QMouseEvent mv(QEvent::MouseMove, QPoint(50,100), window->mapToGlobal(QPoint(50,100)),
+ Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
QGuiApplication::sendEvent(window.data(), &mv);
}
// first move beyond threshold does not trigger drag
@@ -1553,7 +1555,8 @@ void tst_QQuickPathView::mouseDrag()
QCOMPARE(dragEndedSpy.count(), 0);
{
- QMouseEvent mv(QEvent::MouseMove, QPoint(90,100), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QMouseEvent mv(QEvent::MouseMove, QPoint(90,100), window->mapToGlobal(QPoint(90,100)),
+ Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
QGuiApplication::sendEvent(window.data(), &mv);
}
// next move beyond threshold does trigger drag
@@ -1933,7 +1936,8 @@ void tst_QQuickPathView::cancelDrag()
// steal mouse grab - cancels PathView dragging
auto mouse = QPointingDevice::primaryPointingDevice();
auto mousePriv = QPointingDevicePrivate::get(const_cast<QPointingDevice *>(mouse));
- QMouseEvent fakeMouseEv(QEvent::MouseMove, QPoint(130, 100), Qt::NoButton, Qt::LeftButton, Qt::NoModifier, mouse);
+ QMouseEvent fakeMouseEv(QEvent::MouseMove, QPoint(130, 100), QPoint(130, 100),
+ Qt::NoButton, Qt::LeftButton, Qt::NoModifier, mouse);
mousePriv->setExclusiveGrabber(&fakeMouseEv, fakeMouseEv.points().first(), nullptr);
// returns to a snap point.
diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
index e8a46e41ce..0cdbeaf17a 100644
--- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
+++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
@@ -28,6 +28,7 @@
#include <QtTest/QtTest>
#include <QtQuick/qquickview.h>
#include <qqmlengine.h>
+#include <QtQml/qqmlcomponent.h>
#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuick/private/qquickpositioners_p.h>
#include <QtQuick/private/qquicktransition_p.h>
diff --git a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
index e28bfffe6f..e07e97ddd8 100644
--- a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
+++ b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
@@ -72,8 +72,7 @@ void tst_qquickrectangle::color()
QVERIFY(QTest::qWaitForWindowExposed(&view));
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QImage image = view.grabWindow();
diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
index 0b12aa551f..e8b53d046f 100644
--- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
+++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
@@ -30,6 +30,7 @@
#include <QtTest/QSignalSpy>
#include <QtQml/qqmlengine.h>
#include <QtQuick/qquickview.h>
+#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlincubator.h>
diff --git a/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp b/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp
index a77839afa4..8d95a6781e 100644
--- a/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp
+++ b/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp
@@ -29,6 +29,7 @@
#include <qtest.h>
#include <QDebug>
#include <QQmlEngine>
+#include <QQmlComponent>
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickView>
#include <QtGui/QScreen>
diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
index d72a3d265e..0d2debcf1f 100644
--- a/tests/auto/quick/qquickshape/tst_qquickshape.cpp
+++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
@@ -282,9 +282,8 @@ void tst_QQuickShape::render()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -306,9 +305,8 @@ void tst_QQuickShape::renderWithMultipleSp()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -330,9 +328,8 @@ void tst_QQuickShape::radialGrad()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -354,9 +351,8 @@ void tst_QQuickShape::conicalGrad()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -378,9 +374,8 @@ void tst_QQuickShape::renderPolyline()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -407,9 +402,8 @@ void tst_QQuickShape::renderMultiline()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -473,9 +467,8 @@ void tst_QQuickShape::polylineDataTypes()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -624,9 +617,8 @@ void tst_QQuickShape::multilineDataTypes()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
@@ -672,9 +664,8 @@ void tst_QQuickShape::multilineStronglyTyped()
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
provider->setPaths(m_lowPolyLogo);
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QImage img = window->grabWindow();
QVERIFY(!img.isNull());
diff --git a/tests/auto/quick/qquickstates/data/anchorRewind.qml b/tests/auto/quick/qquickstates/data/anchorRewind.qml
new file mode 100644
index 0000000000..740c94cf42
--- /dev/null
+++ b/tests/auto/quick/qquickstates/data/anchorRewind.qml
@@ -0,0 +1,31 @@
+import QtQuick
+
+Item {
+ width: 400
+ height: 400
+ Item {
+ id: outer
+ anchors.fill: parent
+ Item {
+ id: inner
+ width: parent.width / 2
+ height: parent.height / 2
+ anchors.left: parent.right
+ anchors.top: parent.bottom
+ }
+ states: [
+ State {
+ when: true
+ AnchorChanges {
+ target: inner
+ anchors.left: outer.left
+ anchors.top: outer.top
+ }
+ }
+ ]
+ transitions: Transition {
+ AnchorAnimation {}
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquickstates/data/noStateOsciallation.qml b/tests/auto/quick/qquickstates/data/noStateOsciallation.qml
new file mode 100644
index 0000000000..f0d7aeeb6d
--- /dev/null
+++ b/tests/auto/quick/qquickstates/data/noStateOsciallation.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.15
+
+Item {
+ id: root
+ property int number: 2
+ property int stateChangeCounter: 0
+
+ Item {
+ id: item
+ onStateChanged: ++stateChangeCounter
+ states: [
+ State {
+ name: "n1"
+ when: root.number === 1
+ },
+ State {
+ name: "n2"
+ when: root.number === 2
+ }
+ ]
+ }
+}
diff --git a/tests/auto/quick/qquickstates/data/parentChangeInvolvingBindings.qml b/tests/auto/quick/qquickstates/data/parentChangeInvolvingBindings.qml
index 9680e806b8..d3873883cd 100644
--- a/tests/auto/quick/qquickstates/data/parentChangeInvolvingBindings.qml
+++ b/tests/auto/quick/qquickstates/data/parentChangeInvolvingBindings.qml
@@ -3,25 +3,41 @@ import QtQuick
Item {
id: root
property alias childWidth: firstChild.width
+ property alias childX: firstChild.x
property alias childRotation: firstChild.rotation
property double myrotation: 100
property double myrotation2: 200
height: 400
+ y: 40
Item {
id: firstChild
height: parent.height
width: height
+ y: parent.y
+ x: y
rotation: root.myrotation
+
+ Item {
+ id: inner
+ anchors.fill: parent
+ }
}
states: State {
name: "reparented"
- ParentChange { target: firstChild; parent: otherChild; width: 2*height; rotation: root.myrotation2}
+ ParentChange {
+ target: firstChild
+ parent: otherChild
+ width: 2 *height
+ x: 2 * y
+ rotation: root.myrotation2
+ }
}
Item {
height: parent.height
+ y: parent.y
id: otherChild
}
}
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
index 176a377ed4..d6814bd057 100644
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
@@ -38,6 +38,7 @@
#include <private/qquickitem_p.h>
#include <private/qqmlproperty_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtTest/qsignalspy.h>
class MyAttached : public QObject
{
@@ -199,11 +200,13 @@ private slots:
void revertListMemoryLeak();
void duplicateStateName();
void trivialWhen();
+ void noStateOsciallation();
void parentChangeCorrectReversal();
void revertNullObjectBinding();
void bindableProperties();
void parentChangeInvolvingBindings();
void deferredProperties();
+ void rewindAnchorChange();
};
void tst_qquickstates::initTestCase()
@@ -1715,6 +1718,20 @@ void tst_qquickstates::trivialWhen()
QVERIFY(root);
}
+void tst_qquickstates::noStateOsciallation()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("noStateOsciallation.qml"));
+ QScopedPointer<QObject> root {component.create()};
+ QVERIFY(root);
+ // set to 1 on initial transition from "" to "n2"
+ QCOMPARE(root->property("stateChangeCounter").toInt(), 1);
+ root->setProperty("number", 1);
+ // setting number to 1 changes directly from "n2" to "n1"
+ // without any intermediate transition to ""
+ QCOMPARE(root->property("stateChangeCounter").toInt(), 2);
+}
+
void tst_qquickstates::parentChangeCorrectReversal()
{
QQmlEngine engine;
@@ -1781,33 +1798,125 @@ void tst_qquickstates::bindableProperties()
}
}
+struct Listener : QQuickItemChangeListener
+{
+ // We want to get notified about all the states.
+ constexpr static const QRectF expectations[] = {
+ QRectF(40, 40, 400, 400),
+ QRectF(40, 0, 400, 400),
+ QRectF(0, 0, 400, 400),
+ QRectF(0, 0, 800, 400),
+ QRectF(0, 0, 800, 200),
+ QRectF(0, 0, 400, 200),
+ QRectF(0, 20, 400, 200),
+ QRectF(40, 20, 400, 200),
+ QRectF(84, 42, 400, 200),
+ QRectF(84, 42, 86, 43),
+ QRectF(40, 40, 86, 43),
+ QRectF(40, 40, 400, 400),
+ QRectF(40, 20, 400, 400),
+ QRectF(40, 20, 400, 200),
+ QRectF(20, 20, 400, 200),
+ QRectF(20, 20, 200, 200),
+ QRectF(20, 20, 200, 300),
+ QRectF(20, 20, 300, 300),
+ QRectF(20, 30, 300, 300),
+ QRectF(30, 30, 300, 300),
+ };
+
+ int position = 0;
+ bool ok = true;
+
+ void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &rect) override
+ {
+ if (rect != expectations[position]) {
+ qDebug() << position << rect;
+ ok = false;
+ }
+ ++position;
+ }
+};
+
void tst_qquickstates::parentChangeInvolvingBindings()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("parentChangeInvolvingBindings.qml"));
QScopedPointer<QQuickItem> root { qobject_cast<QQuickItem *>(c.create()) };
QVERIFY2(root, qPrintable(c.errorString()));
+
+ QObject *child = qmlContext(root.data())->objectForName(QStringLiteral("firstChild"));
+ QVERIFY(child);
+ QQuickItem *childItem = qobject_cast<QQuickItem *>(child);
+ QVERIFY(childItem);
+ Listener listener;
+ QQuickItemPrivate::get(childItem)->addItemChangeListener(&listener, QQuickItemPrivate::Geometry);
+
+
QCOMPARE(root->property("childWidth").toInt(), 400);
+ QCOMPARE(root->property("childX").toInt(), 40);
QCOMPARE(root->property("childRotation").toInt(), 100);
root->setState("reparented");
QCOMPARE(root->property("childWidth").toInt(), 800);
+ QCOMPARE(root->property("childX").toInt(), 0); // x gets zeroed here, from unrelated place.
QCOMPARE(root->property("childRotation").toInt(), 200);
root->setProperty("myrotation2", 300);
root->setHeight(200);
+ root->setY(20);
QCOMPARE(root->property("childRotation").toInt(), 300);
QCOMPARE(root->property("childWidth").toInt(), 400);
+ QCOMPARE(root->property("childX").toInt(), 40);
+
+ QObject *inner = qmlContext(root.data())->objectForName(QStringLiteral("inner"));
+ QVERIFY(inner);
+ QQuickItem *innerItem = qobject_cast<QQuickItem *>(inner);
+ QVERIFY(innerItem);
+
+ QCOMPARE(innerItem->size(), childItem->size());
+
+ // Does not break bindings and does not survive the state change.
+ // However, since the binding between x and y stays intact, we don't know
+ // whether x is set another time from the new y. We pass a pair of numbers that
+ // matches the binding.
+ childItem->setPosition(QPointF(84, 42));
+ QCOMPARE(root->property("childX").toInt(), 84);
+ QVERIFY(listener.ok);
+ childItem->setSize(QSizeF(86, 43));
+ QCOMPARE(root->property("childWidth").toInt(), 86);
+ QVERIFY(listener.ok);
+
+ QCOMPARE(innerItem->size(), childItem->size());
+
+ QSignalSpy xSpy(childItem, SIGNAL(xChanged()));
+ QSignalSpy widthSpy(childItem, SIGNAL(widthChanged()));
root->setState("");
+
+ QVERIFY(listener.ok);
QCOMPARE(root->property("childRotation").toInt(), 100);
- // QCOMPARE(root->property("childWidth").toInt(), 200);
+ // First change to 40 via reverse(), then to 20 via binding.
+ QCOMPARE(xSpy.count(), 2);
+
+ // First change to 400 via reverse(), then to 200 via binding.
+ QCOMPARE(widthSpy.count(), 2);
+
+ QCOMPARE(root->property("childX").toInt(), 20);
+ QCOMPARE(root->property("childWidth").toInt(), 200);
+
+ QCOMPARE(innerItem->size(), childItem->size());
root->setProperty("myrotation", 50);
root->setHeight(300);
+ QVERIFY(listener.ok);
+ root->setY(30);
+ QVERIFY(listener.ok);
QCOMPARE(root->property("childWidth").toInt(), 300);
+ QCOMPARE(root->property("childX").toInt(), 30);
QCOMPARE(root->property("childRotation").toInt(), 50);
+
+ QCOMPARE(innerItem->size(), childItem->size());
}
void tst_qquickstates::deferredProperties()
@@ -1846,6 +1955,29 @@ void tst_qquickstates::deferredProperties()
QCOMPARE(root->height(), 100.0);
}
+void tst_qquickstates::rewindAnchorChange()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("anchorRewind.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> root(c.create());
+ QVERIFY(root);
+
+ QQmlContext *context = qmlContext(root.data());
+ QVERIFY(context);
+
+ QObject *inner = context->objectForName(QStringLiteral("inner"));
+ QVERIFY(inner);
+
+ QQuickItem *innerRect = qobject_cast<QQuickItem *>(inner);
+ QVERIFY(innerRect);
+
+ QTRY_COMPARE(innerRect->x(), 0);
+ QTRY_COMPARE(innerRect->y(), 0);
+ QTRY_COMPARE(innerRect->width(), 200);
+ QTRY_COMPARE(innerRect->height(), 200);
+}
+
QTEST_MAIN(tst_qquickstates)
#include "tst_qquickstates.moc"
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 1ecc3faa3a..cdcd704f98 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -38,6 +38,7 @@
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlincubator.h>
+#include <QtQml/qqmlcomponent.h>
#include <QtQmlModels/private/qqmlobjectmodel_p.h>
#include <QtQmlModels/private/qqmllistmodel_p.h>
@@ -192,6 +193,10 @@ private slots:
void positionViewAtRow();
void positionViewAtColumn_data();
void positionViewAtColumn();
+ void positionViewAtRowClamped_data();
+ void positionViewAtRowClamped();
+ void positionViewAtColumnClamped_data();
+ void positionViewAtColumnClamped();
void itemAtCell_data();
void itemAtCell();
void leftRightTopBottomProperties_data();
@@ -3065,9 +3070,10 @@ void tst_QQuickTableView::replaceModel()
void tst_QQuickTableView::cellAtPos_data()
{
QTest::addColumn<QPointF>("contentStartPos");
- QTest::addColumn<QPointF>("position");
+ QTest::addColumn<QPointF>("localPos");
QTest::addColumn<bool>("includeSpacing");
QTest::addColumn<QPoint>("expectedCell");
+ QTest::addColumn<QSizeF>("margins");
const int spacing = 10;
const QPointF cellSize(100, 50);
@@ -3080,49 +3086,62 @@ void tst_QQuickTableView::cellAtPos_data()
return QPointF(x, y);
};
- QTest::newRow("1") << QPointF(0, 0) << cellStart(0, 0) << false << QPoint(0, 0);
- QTest::newRow("2") << QPointF(0, 0) << cellStart(1, 0) << false << QPoint(1, 0);
- QTest::newRow("3") << QPointF(0, 0) << cellStart(0, 1) << false << QPoint(0, 1);
- QTest::newRow("4") << QPointF(0, 0) << cellStart(1, 1) << false << QPoint(1, 1);
+ QTest::newRow("1") << QPointF(0, 0) << cellStart(0, 0) << false << QPoint(0, 0) << QSizeF(0, 0);
+ QTest::newRow("2") << QPointF(0, 0) << cellStart(1, 0) << false << QPoint(1, 0) << QSizeF(0, 0);
+ QTest::newRow("3") << QPointF(0, 0) << cellStart(0, 1) << false << QPoint(0, 1) << QSizeF(0, 0);
+ QTest::newRow("4") << QPointF(0, 0) << cellStart(1, 1) << false << QPoint(1, 1) << QSizeF(0, 0);
- QTest::newRow("5") << QPointF(0, 0) << cellStart(1, 1) - quadSpace << false << QPoint(-1, -1);
- QTest::newRow("6") << QPointF(0, 0) << cellStart(0, 0) + cellSize + quadSpace << false << QPoint(-1, -1);
- QTest::newRow("7") << QPointF(0, 0) << cellStart(0, 1) + cellSize + quadSpace << false << QPoint(-1, -1);
+ QTest::newRow("5") << QPointF(0, 0) << cellStart(1, 1) - quadSpace << false << QPoint(-1, -1) << QSizeF(0, 0);
+ QTest::newRow("6") << QPointF(0, 0) << cellStart(0, 0) + cellSize + quadSpace << false << QPoint(-1, -1) << QSizeF(0, 0);
+ QTest::newRow("7") << QPointF(0, 0) << cellStart(0, 1) + cellSize + quadSpace << false << QPoint(-1, -1) << QSizeF(0, 0);
- QTest::newRow("8") << QPointF(0, 0) << cellStart(1, 1) - quadSpace << true << QPoint(1, 1);
- QTest::newRow("9") << QPointF(0, 0) << cellStart(0, 0) + cellSize + quadSpace << true << QPoint(0, 0);
- QTest::newRow("10") << QPointF(0, 0) << cellStart(0, 1) + cellSize + quadSpace << true << QPoint(0, 1);
+ QTest::newRow("8") << QPointF(0, 0) << cellStart(1, 1) - quadSpace << true << QPoint(1, 1) << QSizeF(0, 0);
+ QTest::newRow("9") << QPointF(0, 0) << cellStart(0, 0) + cellSize + quadSpace << true << QPoint(0, 0) << QSizeF(0, 0);
+ QTest::newRow("10") << QPointF(0, 0) << cellStart(0, 1) + cellSize + quadSpace << true << QPoint(0, 1) << QSizeF(0, 0);
- QTest::newRow("11") << cellStart(50, 50) << cellStart(0, 0) << false << QPoint(50, 50);
- QTest::newRow("12") << cellStart(50, 50) << cellStart(4, 4) << false << QPoint(54, 54);
- QTest::newRow("13") << cellStart(50, 50) << cellStart(4, 4) - quadSpace << false << QPoint(-1, -1);
- QTest::newRow("14") << cellStart(50, 50) << cellStart(4, 4) + cellSize + quadSpace << false << QPoint(-1, -1);
- QTest::newRow("15") << cellStart(50, 50) << cellStart(4, 4) - quadSpace << true << QPoint(54, 54);
- QTest::newRow("16") << cellStart(50, 50) << cellStart(4, 4) + cellSize + quadSpace << true << QPoint(54, 54);
+ QTest::newRow("11") << cellStart(50, 50) << cellStart(50, 50) << false << QPoint(50, 50) << QSizeF(0, 0);
+ QTest::newRow("12") << cellStart(50, 50) << cellStart(54, 54) << false << QPoint(54, 54) << QSizeF(0, 0);
+ QTest::newRow("13") << cellStart(50, 50) << cellStart(54, 54) - quadSpace << false << QPoint(-1, -1) << QSizeF(0, 0);
+ QTest::newRow("14") << cellStart(50, 50) << cellStart(54, 54) + cellSize + quadSpace << false << QPoint(-1, -1) << QSizeF(0, 0);
+ QTest::newRow("15") << cellStart(50, 50) << cellStart(54, 54) - quadSpace << true << QPoint(54, 54) << QSizeF(0, 0);
+ QTest::newRow("16") << cellStart(50, 50) << cellStart(54, 54) + cellSize + quadSpace << true << QPoint(54, 54) << QSizeF(0, 0);
- QTest::newRow("17") << cellStart(50, 50) + halfCell << cellStart(0, 0) << false << QPoint(50, 50);
- QTest::newRow("18") << cellStart(50, 50) + halfCell << cellStart(1, 1) << false << QPoint(51, 51);
- QTest::newRow("19") << cellStart(50, 50) + halfCell << cellStart(4, 4) << false << QPoint(54, 54);
+ QTest::newRow("17") << cellStart(50, 50) + halfCell << cellStart(50, 50) << false << QPoint(50, 50) << QSizeF(0, 0);
+ QTest::newRow("18") << cellStart(50, 50) + halfCell << cellStart(51, 51) << false << QPoint(51, 51) << QSizeF(0, 0);
+ QTest::newRow("19") << cellStart(50, 50) + halfCell << cellStart(54, 54) << false << QPoint(54, 54) << QSizeF(0, 0);
+
+ QTest::newRow("20") << QPointF(0, 0) << cellStart(0, 0) << false << QPoint(0, 0) << QSizeF(150, 150);
+ QTest::newRow("20") << QPointF(0, 0) << cellStart(5, 5) << false << QPoint(5, 5) << QSizeF(150, 150);
+
+ QTest::newRow("20") << QPointF(-150, -150) << cellStart(0, 0) << false << QPoint(0, 0) << QSizeF(150, 150);
+ QTest::newRow("21") << QPointF(-150, -150) << cellStart(4, 0) + halfCell << false << QPoint(4, 0) << QSizeF(150, 150);
+ QTest::newRow("22") << QPointF(-150, -150) << cellStart(0, 4) + halfCell << false << QPoint(0, 4) << QSizeF(150, 150);
+ QTest::newRow("23") << QPointF(-150, -150) << cellStart(4, 4) + halfCell << false << QPoint(4, 4) << QSizeF(150, 150);
}
void tst_QQuickTableView::cellAtPos()
{
QFETCH(QPointF, contentStartPos);
- QFETCH(QPointF, position);
+ QFETCH(QPointF, localPos);
QFETCH(bool, includeSpacing);
QFETCH(QPoint, expectedCell);
+ QFETCH(QSizeF, margins);
LOAD_TABLEVIEW("plaintableview.qml");
auto model = TestModelAsVariant(100, 100);
tableView->setModel(model);
tableView->setRowSpacing(10);
tableView->setColumnSpacing(10);
+ tableView->setLeftMargin(margins.width());
+ tableView->setLeftMargin(margins.height());
+ tableView->setTopMargin(margins.height());
tableView->setContentX(contentStartPos.x());
tableView->setContentY(contentStartPos.y());
WAIT_UNTIL_POLISHED;
- QPoint cell = tableView->cellAtPos(position, includeSpacing);
+ const QPointF posInView = tableView->mapFromItem(tableView->contentItem(), localPos);
+ QPoint cell = tableView->cellAtPos(posInView, includeSpacing);
QCOMPARE(cell, expectedCell);
}
@@ -3138,48 +3157,30 @@ void tst_QQuickTableView::positionViewAtRow_data()
QTest::newRow("AlignTop 1") << 1 << Qt::AlignTop << 0. << 50.;
QTest::newRow("AlignTop 50") << 50 << Qt::AlignTop << 0. << -1.;
QTest::newRow("AlignTop 0") << 0 << Qt::AlignTop << 0. << -1.;
- QTest::newRow("AlignTop 99") << 99 << Qt::AlignTop << 0. << -1.;
-
- QTest::newRow("AlignTop 0") << 0 << Qt::AlignTop << -10. << 0.;
QTest::newRow("AlignTop 1") << 1 << Qt::AlignTop << -10. << 0.;
QTest::newRow("AlignTop 1") << 1 << Qt::AlignTop << -10. << 50.;
QTest::newRow("AlignTop 50") << 50 << Qt::AlignTop << -10. << -1.;
- QTest::newRow("AlignTop 0") << 0 << Qt::AlignTop << -10. << -1.;
- QTest::newRow("AlignTop 99") << 99 << Qt::AlignTop << -10. << -1.;
- QTest::newRow("AlignBottom 0") << 0 << Qt::AlignBottom << 0. << 0.;
- QTest::newRow("AlignBottom 1") << 1 << Qt::AlignBottom << 0. << 0.;
- QTest::newRow("AlignBottom 1") << 1 << Qt::AlignBottom << 0. << 50.;
QTest::newRow("AlignBottom 50") << 50 << Qt::AlignBottom << 0. << -1.;
- QTest::newRow("AlignBottom 0") << 0 << Qt::AlignBottom << 0. << -1.;
+ QTest::newRow("AlignBottom 98") << 98 << Qt::AlignBottom << 0. << -1.;
QTest::newRow("AlignBottom 99") << 99 << Qt::AlignBottom << 0. << -1.;
+ QTest::newRow("AlignBottom 50") << 40 << Qt::AlignBottom << 10. << -1.;
+ QTest::newRow("AlignBottom 40") << 50 << Qt::AlignBottom << -10. << -1.;
+ QTest::newRow("AlignBottom 98") << 98 << Qt::AlignBottom << 10. << -1.;
+ QTest::newRow("AlignBottom 99") << 99 << Qt::AlignBottom << -10. << -1.;
- QTest::newRow("AlignBottom 0") << 0 << Qt::AlignBottom << 10. << 0.;
- QTest::newRow("AlignBottom 1") << 1 << Qt::AlignBottom << 10. << 0.;
- QTest::newRow("AlignBottom 1") << 1 << Qt::AlignBottom << 10. << 50.;
- QTest::newRow("AlignBottom 50") << 50 << Qt::AlignBottom << 10. << -1.;
- QTest::newRow("AlignBottom 0") << 0 << Qt::AlignBottom << 10. << -1.;
- QTest::newRow("AlignBottom 99") << 99 << Qt::AlignBottom << 10. << -1.;
-
- QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << 0. << 0.;
- QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << 0. << 0.;
- QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << 0. << 50.;
+ QTest::newRow("AlignCenter 40") << 40 << Qt::AlignCenter << 0. << -1.;
QTest::newRow("AlignCenter 50") << 50 << Qt::AlignCenter << 0. << -1.;
- QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << 0. << -1.;
- QTest::newRow("AlignCenter 99") << 99 << Qt::AlignCenter << 0. << -1.;
-
- QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << -10. << 0.;
- QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << -10. << 0.;
- QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << -10. << 50.;
+ QTest::newRow("AlignCenter 40") << 40 << Qt::AlignCenter << 10. << -1.;
QTest::newRow("AlignCenter 50") << 50 << Qt::AlignCenter << -10. << -1.;
- QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << -10. << -1.;
- QTest::newRow("AlignCenter 99") << 99 << Qt::AlignCenter << -10. << -1.;
}
void tst_QQuickTableView::positionViewAtRow()
{
// Check that positionViewAtRow actually flicks the view
- // to the right position so that the row becomes visible
+ // to the right position so that the row becomes visible.
+ // For this test, we only check cells that can be placed exactly
+ // according to the given alignment.
QFETCH(int, row);
QFETCH(Qt::AlignmentFlag, alignment);
QFETCH(qreal, offset);
@@ -3229,48 +3230,27 @@ void tst_QQuickTableView::positionViewAtColumn_data()
QTest::newRow("AlignLeft 1") << 1 << Qt::AlignLeft << 0. << 50.;
QTest::newRow("AlignLeft 50") << 50 << Qt::AlignLeft << 0. << -1.;
QTest::newRow("AlignLeft 0") << 0 << Qt::AlignLeft << 0. << -1.;
- QTest::newRow("AlignLeft 99") << 99 << Qt::AlignLeft << 0. << -1.;
-
- QTest::newRow("AlignLeft 0") << 0 << Qt::AlignLeft << -10. << 0.;
QTest::newRow("AlignLeft 1") << 1 << Qt::AlignLeft << -10. << 0.;
QTest::newRow("AlignLeft 1") << 1 << Qt::AlignLeft << -10. << 50.;
QTest::newRow("AlignLeft 50") << 50 << Qt::AlignLeft << -10. << -1.;
- QTest::newRow("AlignLeft 0") << 0 << Qt::AlignLeft << -10. << -1.;
- QTest::newRow("AlignLeft 99") << 99 << Qt::AlignLeft << -10. << -1.;
- QTest::newRow("AlignRight 0") << 0 << Qt::AlignRight << 0. << 0.;
- QTest::newRow("AlignRight 1") << 1 << Qt::AlignRight << 0. << 0.;
- QTest::newRow("AlignRight 1") << 1 << Qt::AlignRight << 0. << 50.;
QTest::newRow("AlignRight 50") << 50 << Qt::AlignRight << 0. << -1.;
- QTest::newRow("AlignRight 0") << 0 << Qt::AlignRight << 0. << -1.;
QTest::newRow("AlignRight 99") << 99 << Qt::AlignRight << 0. << -1.;
-
- QTest::newRow("AlignRight 0") << 0 << Qt::AlignRight << 10. << 0.;
- QTest::newRow("AlignRight 1") << 1 << Qt::AlignRight << 10. << 0.;
- QTest::newRow("AlignRight 1") << 1 << Qt::AlignRight << 10. << 50.;
QTest::newRow("AlignRight 50") << 50 << Qt::AlignRight << 10. << -1.;
- QTest::newRow("AlignRight 0") << 0 << Qt::AlignRight << 10. << -1.;
- QTest::newRow("AlignRight 99") << 99 << Qt::AlignRight << 10. << -1.;
+ QTest::newRow("AlignRight 99") << 99 << Qt::AlignRight << -10. << -1.;
- QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << 0. << 0.;
- QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << 0. << 0.;
- QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << 0. << 50.;
+ QTest::newRow("AlignCenter 40") << 50 << Qt::AlignCenter << 0. << -1.;
QTest::newRow("AlignCenter 50") << 50 << Qt::AlignCenter << 0. << -1.;
- QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << 0. << -1.;
- QTest::newRow("AlignCenter 99") << 99 << Qt::AlignCenter << 0. << -1.;
-
- QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << -10. << 0.;
- QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << -10. << 0.;
- QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << -10. << 50.;
+ QTest::newRow("AlignCenter 40") << 50 << Qt::AlignCenter << 10. << -1.;
QTest::newRow("AlignCenter 50") << 50 << Qt::AlignCenter << -10. << -1.;
- QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << -10. << -1.;
- QTest::newRow("AlignCenter 99") << 99 << Qt::AlignCenter << -10. << -1.;
}
void tst_QQuickTableView::positionViewAtColumn()
{
// Check that positionViewAtColumn actually flicks the view
- // to the right position so that the row becomes visible
+ // to the right position so that the row becomes visible.
+ // For this test, we only check cells that can be placed exactly
+ // according to the given alignment.
QFETCH(int, column);
QFETCH(Qt::AlignmentFlag, alignment);
QFETCH(qreal, offset);
@@ -3308,6 +3288,134 @@ void tst_QQuickTableView::positionViewAtColumn()
}
}
+void tst_QQuickTableView::positionViewAtRowClamped_data()
+{
+ QTest::addColumn<int>("row");
+ QTest::addColumn<Qt::AlignmentFlag>("alignment");
+ QTest::addColumn<qreal>("offset");
+ QTest::addColumn<qreal>("contentYStartPos");
+
+ QTest::newRow("AlignTop 0") << 0 << Qt::AlignTop << -10. << 0.;
+ QTest::newRow("AlignTop 0") << 0 << Qt::AlignTop << -10. << -1.;
+ QTest::newRow("AlignTop 99") << 99 << Qt::AlignTop << 0. << -1.;
+ QTest::newRow("AlignTop 99") << 99 << Qt::AlignTop << -10. << -1.;
+
+ QTest::newRow("AlignBottom 0") << 0 << Qt::AlignBottom << 0. << 0.;
+ QTest::newRow("AlignBottom 1") << 1 << Qt::AlignBottom << 0. << 0.;
+ QTest::newRow("AlignBottom 1") << 1 << Qt::AlignBottom << 0. << 50.;
+ QTest::newRow("AlignBottom 0") << 0 << Qt::AlignBottom << 0. << -1.;
+
+ QTest::newRow("AlignBottom 0") << 0 << Qt::AlignBottom << 10. << 0.;
+ QTest::newRow("AlignBottom 1") << 1 << Qt::AlignBottom << 10. << 0.;
+ QTest::newRow("AlignBottom 1") << 1 << Qt::AlignBottom << 10. << 50.;
+ QTest::newRow("AlignBottom 0") << 0 << Qt::AlignBottom << 10. << -1.;
+ QTest::newRow("AlignBottom 99") << 99 << Qt::AlignBottom << 10. << -1.;
+
+ QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << 0. << 0.;
+ QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << 0. << 0.;
+ QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << 0. << 50.;
+ QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << 0. << -1.;
+ QTest::newRow("AlignCenter 99") << 99 << Qt::AlignCenter << 0. << -1.;
+
+ QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << -10. << 0.;
+ QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << -10. << 0.;
+ QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << -10. << 50.;
+ QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << -10. << -1.;
+ QTest::newRow("AlignCenter 99") << 99 << Qt::AlignCenter << -10. << -1.;
+}
+
+void tst_QQuickTableView::positionViewAtRowClamped()
+{
+ // Check that positionViewAtRow actually flicks the table to the
+ // right position so that the row becomes visible. For this test, we
+ // only test cells that cannot be placed exactly at the given alignment,
+ // because it would cause the table to overshoot. Instead the
+ // table should be flicked to the edge of the viewport, close to the
+ // requested alignment.
+ QFETCH(int, row);
+ QFETCH(Qt::AlignmentFlag, alignment);
+ QFETCH(qreal, offset);
+ QFETCH(qreal, contentYStartPos);
+
+ LOAD_TABLEVIEW("plaintableview.qml");
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+ if (contentYStartPos >= 0)
+ tableView->setContentY(contentYStartPos);
+
+ WAIT_UNTIL_POLISHED;
+
+ tableView->positionViewAtRow(row, alignment, offset);
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableView->contentY(), row < 50 ? 0 : tableView->contentHeight() - tableView->height());
+}
+
+void tst_QQuickTableView::positionViewAtColumnClamped_data()
+{
+ QTest::addColumn<int>("column");
+ QTest::addColumn<Qt::AlignmentFlag>("alignment");
+ QTest::addColumn<qreal>("offset");
+ QTest::addColumn<qreal>("contentXStartPos");
+
+ QTest::newRow("AlignLeft 0") << 0 << Qt::AlignLeft << -10. << 0.;
+ QTest::newRow("AlignLeft 0") << 0 << Qt::AlignLeft << -10. << -1.;
+ QTest::newRow("AlignLeft 99") << 99 << Qt::AlignLeft << 0. << -1.;
+ QTest::newRow("AlignLeft 99") << 99 << Qt::AlignLeft << -10. << -1.;
+
+ QTest::newRow("AlignRight 0") << 0 << Qt::AlignRight << 0. << 0.;
+ QTest::newRow("AlignRight 1") << 1 << Qt::AlignRight << 0. << 0.;
+ QTest::newRow("AlignRight 1") << 1 << Qt::AlignRight << 0. << 50.;
+ QTest::newRow("AlignRight 0") << 0 << Qt::AlignRight << 0. << -1.;
+
+ QTest::newRow("AlignRight 0") << 0 << Qt::AlignRight << 10. << 0.;
+ QTest::newRow("AlignRight 1") << 1 << Qt::AlignRight << 10. << 0.;
+ QTest::newRow("AlignRight 1") << 1 << Qt::AlignRight << 10. << 50.;
+ QTest::newRow("AlignRight 0") << 0 << Qt::AlignRight << 10. << -1.;
+ QTest::newRow("AlignRight 99") << 99 << Qt::AlignRight << 10. << -1.;
+
+ QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << 0. << 0.;
+ QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << 0. << 0.;
+ QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << 0. << 50.;
+ QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << 0. << -1.;
+ QTest::newRow("AlignCenter 99") << 99 << Qt::AlignCenter << 0. << -1.;
+
+ QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << -10. << 0.;
+ QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << -10. << 0.;
+ QTest::newRow("AlignCenter 1") << 1 << Qt::AlignCenter << -10. << 50.;
+ QTest::newRow("AlignCenter 0") << 0 << Qt::AlignCenter << -10. << -1.;
+ QTest::newRow("AlignCenter 99") << 99 << Qt::AlignCenter << -10. << -1.;
+}
+
+void tst_QQuickTableView::positionViewAtColumnClamped()
+{
+ // Check that positionViewAtColumn actually flicks the table to the
+ // right position so that the column becomes visible. For this test, we
+ // only test cells that cannot be placed exactly at the given alignment,
+ // because it would cause the table to overshoot. Instead the
+ // table should be flicked to the edge of the viewport, close to the
+ // requested alignment.
+ QFETCH(int, column);
+ QFETCH(Qt::AlignmentFlag, alignment);
+ QFETCH(qreal, offset);
+ QFETCH(qreal, contentXStartPos);
+
+ LOAD_TABLEVIEW("plaintableview.qml");
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+ if (contentXStartPos >= 0)
+ tableView->setContentX(contentXStartPos);
+
+ WAIT_UNTIL_POLISHED;
+
+ tableView->positionViewAtColumn(column, alignment, offset);
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableView->contentX(), column < 50 ? 0 : tableView->contentWidth() - tableView->width());
+}
+
void tst_QQuickTableView::itemAtCell_data()
{
QTest::addColumn<QPoint>("cell");
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index bf90a8efd4..c31e698527 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -1028,9 +1028,6 @@ static inline QByteArray msgNotLessThan(int n1, int n2)
void tst_qquicktext::hAlignImplicitWidth()
{
-#ifdef Q_OS_MACOS
- QSKIP("this test currently crashes on MacOS. See QTBUG-68047");
-#endif
QQuickView view(testFileUrl("hAlignImplicitWidth.qml"));
view.setFlags(view.flags() | Qt::WindowStaysOnTopHint); // Prevent being obscured by other windows.
view.show();
@@ -1054,9 +1051,8 @@ void tst_qquicktext::hAlignImplicitWidth()
const int centeredSection3End = centeredSection3 + sectionWidth;
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
// Left Align
QImage image = view.grabWindow();
@@ -4049,7 +4045,11 @@ static qreal expectedBaselineScaled(QQuickText *item)
{
QFont font = item->font();
QTextLayout layout(item->text().replace(QLatin1Char('\n'), QChar::LineSeparator));
- do {
+
+ qreal low = 0;
+ qreal high = 10000;
+
+ while (low < high) {
layout.setFont(font);
qreal width = 0;
layout.beginLayout();
@@ -4059,12 +4059,23 @@ static qreal expectedBaselineScaled(QQuickText *item)
}
layout.endLayout();
- if (width < item->width()) {
- QFontMetricsF fm(layout.font());
- return fm.ascent() + item->topPadding();
+ if (width > item->width()) {
+ high = font.pointSizeF();
+ font.setPointSizeF((high + low) / 2);
+ } else {
+ low = font.pointSizeF();
+
+ // When fontSizeMode != FixedSize, the font size will be scaled to a value
+ // The goal is to find a pointSize that uses as much space as possible while
+ // still fitting inside the available space. 0.01 is chosen as the threshold.
+ if ((high - low) < qreal(0.01)) {
+ QFontMetricsF fm(layout.font());
+ return fm.ascent() + item->topPadding();
+ }
+
+ font.setPointSizeF((high + low) / 2);
}
- font.setPointSize(font.pointSize() - 1);
- } while (font.pointSize() > 0);
+ }
return item->topPadding();
}
@@ -4682,9 +4693,8 @@ void tst_qquicktext::verticallyAlignedImageInTable()
void tst_qquicktext::transparentBackground()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabToImage not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("transparentBackground.qml"));
@@ -4703,9 +4713,8 @@ void tst_qquicktext::transparentBackground()
void tst_qquicktext::displaySuperscriptedTag()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabToImage not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("displaySuperscriptedTag.qml"));
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index 0fc3db86ae..c15a626d33 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -945,9 +945,8 @@ void tst_qquicktextedit::hAlignVisual()
const int centeredSection3End = centeredSection3 + sectionWidth;
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
// Left Align
QImage image = view.grabWindow();
@@ -2729,7 +2728,8 @@ void tst_qquicktextedit::cursorDelegate()
const QPoint point2 = textEditObject->positionToRectangle(10).center().toPoint();
QTest::qWait(400); //ensure this isn't treated as a double-click
QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, point1);
- QMouseEvent mv(QEvent::MouseMove, point2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QMouseEvent mv(QEvent::MouseMove, point2, view.mapToGlobal(point2),
+ Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
QGuiApplication::sendEvent(&view, &mv);
QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, point2);
QTest::qWait(50);
@@ -3766,8 +3766,7 @@ void tst_qquicktextedit::largeTextObservesViewport()
{
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to few fonts installed on offscreen/minimal platforms");
-
+ QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
QFETCH(QString, text);
QFETCH(QQuickTextEdit::TextFormat, textFormat);
QFETCH(bool, parentIsViewport);
@@ -6124,9 +6123,8 @@ void tst_qquicktextedit::keys_shortcutoverride()
void tst_qquicktextedit::transparentSelectionColor()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabToImage not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
QQuickView view;
view.setSource(testFileUrl("transparentSelectionColor.qml"));
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 669f94ed48..42099762f0 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -31,6 +31,7 @@
#include <QtQuickTestUtils/private/testhttpserver_p.h>
#include <private/qinputmethod_p.h>
#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlexpression.h>
#include <QFile>
#include <QtQuick/qquickview.h>
@@ -2896,7 +2897,8 @@ void tst_qquicktextinput::cursorDelegate()
const QPoint point2 = textInputObject->positionToRectangle(10).center().toPoint();
QTest::qWait(400); //ensure this isn't treated as a double-click
QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, point1);
- QMouseEvent mv(QEvent::MouseMove, point2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QMouseEvent mv(QEvent::MouseMove, point2, textInputObject->mapToGlobal(point2),
+ Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
QGuiApplication::sendEvent(&view, &mv);
QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, point2);
QTest::qWait(50);
diff --git a/tests/auto/quick/qquicktreeview/testmodel.cpp b/tests/auto/quick/qquicktreeview/testmodel.cpp
index a562b3274a..83c7ead4a8 100644
--- a/tests/auto/quick/qquicktreeview/testmodel.cpp
+++ b/tests/auto/quick/qquicktreeview/testmodel.cpp
@@ -61,18 +61,21 @@ TestModel::TestModel(QObject *parent)
m_rootItem.reset(new TreeItem());
for (int col = 0; col < m_columnCount; ++col)
m_rootItem.data()->m_entries << QVariant(QString("0, %1").arg(col));
- createTreeRecursive(m_rootItem.data(), 4, 0, 4);
+ createTreeRecursive(m_rootItem.data(), 4, 1);
}
-void TestModel::createTreeRecursive(TreeItem *item, int childCount, int currentDepth, int maxDepth)
+void TestModel::createTreeRecursive(TreeItem *item, int childCount, int currentDepth)
{
+ if (currentDepth > maxDepth())
+ return;
+
for (int row = 0; row < childCount; ++row) {
auto childItem = new TreeItem(item);
for (int col = 0; col < m_columnCount; ++col)
childItem->m_entries << QVariant(QString("%1, %2").arg(row).arg(col));
item->m_childItems.append(childItem);
- if (currentDepth < maxDepth && row == childCount - 1)
- createTreeRecursive(childItem, childCount, currentDepth + 1, maxDepth);
+ if (row == childCount - 1)
+ createTreeRecursive(childItem, childCount, currentDepth + 1);
}
}
diff --git a/tests/auto/quick/qquicktreeview/testmodel.h b/tests/auto/quick/qquicktreeview/testmodel.h
index 4d9006d112..fc4272af8b 100644
--- a/tests/auto/quick/qquicktreeview/testmodel.h
+++ b/tests/auto/quick/qquicktreeview/testmodel.h
@@ -64,7 +64,7 @@ class TestModel : public QAbstractItemModel
public:
explicit TestModel(QObject *parent = nullptr);
- void createTreeRecursive(TreeItem *item, int childCount, int currentDepth, int maxDepth);
+ void createTreeRecursive(TreeItem *item, int childCount, int currentDepth);
TreeItem *treeItem(const QModelIndex &index) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex & = QModelIndex()) const override;
@@ -72,6 +72,7 @@ public:
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &index) const override;
+ int maxDepth() { return 4; }
bool insertRows(int position, int rows, const QModelIndex &parent) override;
diff --git a/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp b/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp
index abba5fced6..712ccdc6cc 100644
--- a/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp
+++ b/tests/auto/quick/qquicktreeview/tst_qquicktreeview.cpp
@@ -90,10 +90,20 @@ private:
private slots:
void initTestCase() override;
void showTreeView();
+ void invalidArguments();
void expandAndCollapseRoot();
void toggleExpanded();
void expandAndCollapseChildren();
void expandChildPendingToBeVisible();
+ void expandRecursivelyRoot_data();
+ void expandRecursivelyRoot();
+ void expandRecursivelyChild_data();
+ void expandRecursivelyChild();
+ void expandRecursivelyWholeTree();
+ void collapseRecursivelyRoot();
+ void collapseRecursivelyChild();
+ void collapseRecursivelyWholeTree();
+ void expandToIndex();
void requiredPropertiesRoot();
void requiredPropertiesChildren();
void emptyModel();
@@ -120,14 +130,47 @@ void tst_qquicktreeview::showTreeView()
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
}
+
+void tst_qquicktreeview::invalidArguments()
+{
+ // Check that we handle gracefully invalid arguments
+ LOAD_TREEVIEW("normaltreeview.qml");
+
+ treeView->expand(-2);
+ QCOMPARE(treeView->rows(), 1);
+ treeView->expandRecursively(200);
+ QCOMPARE(treeView->rows(), 1);
+ treeView->expandRecursively(-2);
+ QCOMPARE(treeView->rows(), 1);
+ treeView->expandRecursively(200);
+ QCOMPARE(treeView->rows(), 1);
+
+ treeView->collapse(-2);
+ QCOMPARE(treeView->rows(), 1);
+ treeView->collapseRecursively(200);
+ QCOMPARE(treeView->rows(), 1);
+ treeView->collapseRecursively(-2);
+ QCOMPARE(treeView->rows(), 1);
+ treeView->collapseRecursively(200);
+ QCOMPARE(treeView->rows(), 1);
+}
+
void tst_qquicktreeview::expandAndCollapseRoot()
{
LOAD_TREEVIEW("normaltreeview.qml");
// Check that the view only has one row loaded so far (the root of the tree)
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
+ QSignalSpy expandedSpy(treeView, SIGNAL(expanded(int, int)));
+
// Expand the root
treeView->expand(0);
+
+ QCOMPARE(expandedSpy.count(), 1);
+ auto signalArgs = expandedSpy.takeFirst();
+ QVERIFY(signalArgs.at(0).toInt() == 0);
+ QVERIFY(signalArgs.at(1).toInt() == 1);
+
WAIT_UNTIL_POLISHED;
// We now expect 5 rows, the root pluss it's 4 children
QCOMPARE(treeViewPrivate->loadedRows.count(), 5);
@@ -163,14 +206,23 @@ void tst_qquicktreeview::expandAndCollapseChildren()
LOAD_TREEVIEW("normaltreeview.qml");
const int childCount = 4;
+ QSignalSpy expandedSpy(treeView, SIGNAL(expanded(int, int)));
// Expand the last child of a parent recursively four times
for (int level = 0; level < 4; ++level) {
const int nodeToExpand = level * childCount;
const int firstChildRow = nodeToExpand + 1; // (+ 1 for the root)
const int lastChildRow = firstChildRow + 4;
+
treeView->expand(nodeToExpand);
+
+ QCOMPARE(expandedSpy.count(), 1);
+ auto signalArgs = expandedSpy.takeFirst();
+ QVERIFY(signalArgs.at(0).toInt() == nodeToExpand);
+ QVERIFY(signalArgs.at(1).toInt() == 1);
+
WAIT_UNTIL_POLISHED;
+
QCOMPARE(treeView->rows(), lastChildRow);
auto childItem1 = treeViewPrivate->loadedTableItem(QPoint(0, firstChildRow))->item;
@@ -381,9 +433,305 @@ void tst_qquicktreeview::expandChildPendingToBeVisible()
// Now the view have updated to show
// all the rows that has been expanded.
- QCOMPARE(treeView->rows(), 9);
+ QCOMPARE(treeView->rows(), 9);
+}
+
+void tst_qquicktreeview::expandRecursivelyRoot_data()
+{
+ QTest::addColumn<int>("rowToExpand");
+ QTest::addColumn<int>("depth");
+
+ QTest::newRow("0, -1") << 0 << -1;
+ QTest::newRow("0, 0") << 0 << 0;
+ QTest::newRow("0, 1") << 0 << 1;
+ QTest::newRow("0, 2") << 0 << 2;
+}
+
+void tst_qquicktreeview::expandRecursivelyRoot()
+{
+ // Check that we can expand the root node (row 0), and that
+ // all its children are expanded recursively down to the
+ // given depth.
+ QFETCH(int, rowToExpand);
+ QFETCH(int, depth);
+
+ LOAD_TREEVIEW("normaltreeview.qml");
+ QSignalSpy spy(treeView, SIGNAL(expanded(int, int)));
+
+ treeView->expandRecursively(rowToExpand, depth);
+
+ if (depth == 0) {
+ QCOMPARE(spy.count(), 0);
+ } else {
+
+ QCOMPARE(spy.count(), 1);
+ const auto signalArgs = spy.takeFirst();
+ QVERIFY(signalArgs.at(0).toInt() == rowToExpand);
+ QVERIFY(signalArgs.at(1).toInt() == depth);
+ }
+
+ WAIT_UNTIL_POLISHED;
+
+ const int rowToExpandDepth = treeView->depth(rowToExpand);
+ const int effectiveMaxDepth = depth != -1 ? rowToExpandDepth + depth : model->maxDepth();
+
+ if (depth > 0 || depth == -1)
+ QVERIFY(treeView->isExpanded(rowToExpand));
+ else
+ QVERIFY(!treeView->isExpanded(rowToExpand));
+
+ // Check that all rows after rowToExpand, that are also
+ // children of that row, is expanded (down to depth)
+ for (int currentRow = rowToExpand + 1; currentRow < treeView->rows(); ++currentRow) {
+ const auto modelIndex = treeView->modelIndex(currentRow, 0);
+ const int currentDepth = treeView->depth(currentRow);
+ const bool isChild = currentDepth > rowToExpandDepth;
+ const bool isExpandable = model->rowCount(modelIndex) > 0;
+ const bool shouldBeExpanded = isChild && isExpandable && currentDepth < effectiveMaxDepth;
+ QCOMPARE(treeView->isExpanded(currentRow), shouldBeExpanded);
+ }
+}
+
+void tst_qquicktreeview::expandRecursivelyChild_data()
+{
+ QTest::addColumn<int>("rowToExpand");
+ QTest::addColumn<int>("depth");
+
+ QTest::newRow("5, -1") << 4 << -1;
+ QTest::newRow("5, 0") << 4 << 0;
+ QTest::newRow("5, 1") << 4 << 1;
+ QTest::newRow("5, 2") << 4 << 2;
+ QTest::newRow("5, 3") << 4 << 3;
+}
+
+void tst_qquicktreeview::expandRecursivelyChild()
+{
+ // Check that we can first expand the root node, and the expand
+ // recursive the first child node with children (row 4), and that all
+ // its children of that node are expanded recursively according to depth.
+ QFETCH(int, rowToExpand);
+ QFETCH(int, depth);
+
+ LOAD_TREEVIEW("normaltreeview.qml");
+ QSignalSpy spy(treeView, SIGNAL(expanded(int, int)));
+
+ treeView->expand(0);
+
+ QCOMPARE(spy.count(), 1);
+ auto signalArgs = spy.takeFirst();
+ QVERIFY(signalArgs.at(0).toInt() == 0);
+ QVERIFY(signalArgs.at(1).toInt() == 1);
+
+ treeView->expandRecursively(rowToExpand, depth);
+
+ if (depth == 0) {
+ QCOMPARE(spy.count(), 0);
+ } else {
+ QCOMPARE(spy.count(), 1);
+ signalArgs = spy.takeFirst();
+ QVERIFY(signalArgs.at(0).toInt() == rowToExpand);
+ QVERIFY(signalArgs.at(1).toInt() == depth);
+ }
+
+ WAIT_UNTIL_POLISHED;
+
+ const bool rowToExpandDepth = treeView->depth(rowToExpand);
+ const int effectiveMaxDepth = depth != -1 ? rowToExpandDepth + depth : model->maxDepth();
+
+ // Check that all rows before rowToExpand is not expanded
+ // (except the root node)
+ for (int currentRow = 1; currentRow < rowToExpand; ++currentRow)
+ QVERIFY(!treeView->isExpanded(currentRow));
+
+ // Check if rowToExpand is expanded
+ if (depth > 0 || depth == -1)
+ QVERIFY(treeView->isExpanded(rowToExpand));
+ else
+ QVERIFY(!treeView->isExpanded(rowToExpand));
+
+ // Check that all rows after rowToExpand that is also
+ // children of that row is expanded (down to depth)
+ for (int currentRow = rowToExpand + 1; currentRow < treeView->rows(); ++currentRow) {
+ const int currentDepth = treeView->depth(currentRow);
+ const bool isChild = currentDepth > rowToExpandDepth;
+ const auto modelIndex = treeView->modelIndex(currentRow, 0);
+ const bool isExpandable = model->rowCount(modelIndex) > 0;
+ const bool shouldBeExpanded = isChild && isExpandable && currentDepth < effectiveMaxDepth;
+ QCOMPARE(treeView->isExpanded(currentRow), shouldBeExpanded);
+ }
}
+void tst_qquicktreeview::expandRecursivelyWholeTree()
+{
+ // Check that we expand the whole tree recursively by passing -1, -1
+ LOAD_TREEVIEW("normaltreeview.qml");
+ QSignalSpy spy(treeView, SIGNAL(expanded(int, int)));
+ treeView->expandRecursively(-1, -1);
+
+ QCOMPARE(spy.count(), 1);
+ auto signalArgs = spy.takeFirst();
+ QVERIFY(signalArgs.at(0).toInt() == -1);
+ QVERIFY(signalArgs.at(1).toInt() == -1);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Check that all rows that have children are expanded
+ for (int currentRow = 0; currentRow < treeView->rows(); ++currentRow) {
+ const auto modelIndex = treeView->modelIndex(currentRow, 0);
+ const bool isExpandable = model->rowCount(modelIndex) > 0;
+ QCOMPARE(treeView->isExpanded(currentRow), isExpandable);
+ }
+}
+
+void tst_qquicktreeview::collapseRecursivelyRoot()
+{
+ // Check that we can collapse the root node (row 0), and that
+ // all its children are collapsed recursively down to the leaves.
+ LOAD_TREEVIEW("normaltreeview.qml");
+ treeView->expandRecursively();
+ WAIT_UNTIL_POLISHED;
+
+ // Verify that the tree is now fully expanded
+ const int expectedRowCount = 1 + (model->maxDepth() * 4); // root + 4 children per level
+ QCOMPARE(treeView->rows(), expectedRowCount);
+
+ QSignalSpy spy(treeView, SIGNAL(collapsed(int, bool)));
+
+ // Collapse the whole tree again. This time, only the root should end up visible
+ treeView->collapseRecursively();
+
+ QCOMPARE(spy.count(), 1);
+ const auto signalArgs = spy.takeFirst();
+ QVERIFY(signalArgs.at(0).toInt() == -1);
+ QVERIFY(signalArgs.at(1).toBool() == true);
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(treeView->rows(), 1);
+
+ // We need to check that all descendants are collapsed as well. But since they're
+ // now no longer visible in the view, we need to expand each parent one by one again to make
+ // them visible, and check that the child inside that has children is still collapsed.
+ // We can do that by simply iterate over the rows in the view as we expand.
+ int currentRow = 0;
+ while (currentRow < treeView->rows()) {
+ const QModelIndex currentIndex = treeView->modelIndex(currentRow, 0);
+ if (model->hasChildren(currentIndex)) {
+ QVERIFY(!treeView->isExpanded(currentRow));
+ treeView->expand(currentRow);
+ WAIT_UNTIL_POLISHED;
+ }
+ currentRow++;
+ }
+
+ // Sanity check that we ended up with all rows expanded again
+ QCOMPARE(currentRow, expectedRowCount);
+}
+
+void tst_qquicktreeview::collapseRecursivelyChild()
+{
+ // Check that we can collapse a child node (row 4), and that all its children
+ // are collapsed recursively down to the leaves (without touching the root).
+ LOAD_TREEVIEW("normaltreeview.qml");
+ treeView->expandRecursively();
+ WAIT_UNTIL_POLISHED;
+
+ // Verify that the tree is now fully expanded
+ const int expectedRowCount = 1 + (model->maxDepth() * 4); // root + 4 children per level
+ QCOMPARE(treeView->rows(), expectedRowCount);
+
+ QSignalSpy spy(treeView, SIGNAL(collapsed(int, bool)));
+
+ // Collapse the 4th child recursive
+ const int rowToCollapse = 4;
+ QCOMPARE(model->data(treeView->modelIndex(rowToCollapse, 0), Qt::DisplayRole), QStringLiteral("3, 0"));
+ treeView->collapseRecursively(rowToCollapse);
+
+ QCOMPARE(spy.count(), 1);
+ const auto signalArgs = spy.takeFirst();
+ QVERIFY(signalArgs.at(0).toInt() == rowToCollapse);
+ QVERIFY(signalArgs.at(1).toBool() == true);
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(treeView->rows(), 5); // root + 4 children
+
+ // We need to check that all descendants are collapsed as well. But since they're
+ // now no longer visible in the view, we need to expand each parent one by one again to make
+ // them visible, and check that the child inside that has children is still collapsed.
+ // We can do that by simply iterate over the rows in the view as we expand.
+ int currentRow = 1; // start at first child
+ while (currentRow < treeView->rows()) {
+ const QModelIndex currentIndex = treeView->modelIndex(currentRow, 0);
+ if (model->hasChildren(currentIndex)) {
+ QVERIFY(!treeView->isExpanded(currentRow));
+ treeView->expand(currentRow);
+ WAIT_UNTIL_POLISHED;
+ }
+ currentRow++;
+ }
+
+ // Sanity check that we ended up with all rows expanded again
+ QCOMPARE(currentRow, expectedRowCount);
+}
+
+void tst_qquicktreeview::collapseRecursivelyWholeTree()
+{
+ // Check that we collapse the whole tree recursively by passing -1
+ LOAD_TREEVIEW("normaltreeview.qml");
+ QSignalSpy spy(treeView, SIGNAL(collapsed(int, bool)));
+ treeView->expandRecursively();
+ treeView->collapseRecursively();
+
+ QCOMPARE(spy.count(), 1);
+ auto signalArgs = spy.takeFirst();
+ QVERIFY(signalArgs.at(0).toInt() == -1);
+ QVERIFY(signalArgs.at(1).toBool() == true);
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(treeView->rows(), 1); // root
+}
+
+void tst_qquicktreeview::expandToIndex()
+{
+ // Check that expandToIndex(index) expands the tree so
+ // that index becomes visible in the view
+ LOAD_TREEVIEW("normaltreeview.qml");
+ QSignalSpy spy(treeView, SIGNAL(expanded(int, int)));
+
+ const QModelIndex root = model->index(0, 0);
+ const QModelIndex child1 = model->index(3, 0, root);
+ const QModelIndex child2 = model->index(3, 0, child1);
+
+ QVERIFY(model->hasChildren(root));
+ QVERIFY(model->hasChildren(child1));
+ QVERIFY(model->hasChildren(child2));
+
+ QVERIFY(!treeView->isExpanded(treeView->rowAtIndex(root)));
+ QVERIFY(!treeView->isExpanded(treeView->rowAtIndex(child1)));
+ QVERIFY(!treeView->isExpanded(treeView->rowAtIndex(child2)));
+
+ const QModelIndex childToExpand = model->index(1, 0, child2);
+ treeView->expandToIndex(childToExpand);
+
+ QVERIFY(treeView->isExpanded(treeView->rowAtIndex(root)));
+ QVERIFY(treeView->isExpanded(treeView->rowAtIndex(child1)));
+ QVERIFY(treeView->isExpanded(treeView->rowAtIndex(child2)));
+
+ QCOMPARE(spy.count(), 1);
+ auto signalArgs = spy.takeFirst();
+ QVERIFY(signalArgs.at(0).toInt() == 0);
+ QVERIFY(signalArgs.at(1).toInt() == 3);
+
+ WAIT_UNTIL_POLISHED;
+
+ // The view should now have 13 rows:
+ // root + 3 expanded nodes that each have 4 children
+ QCOMPARE(treeView->rows(), 13);
+}
+
+
QTEST_MAIN(tst_qquicktreeview)
#include "tst_qquicktreeview.moc"
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index aca156f911..ba09401545 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -28,6 +28,7 @@
#include <qtest.h>
#include <QDebug>
+#include <QEvent>
#include <QMimeData>
#include <QTouchEvent>
#include <QtQuick/QQuickItem>
@@ -1618,9 +1619,8 @@ public:
void tst_qquickwindow::earlyGrab()
{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
+ if (QGuiApplication::platformName() == QLatin1String("minimal"))
+ QSKIP("Skipping due to grabWindow not functional on minimal platforms");
qmlRegisterType<Grabber>("Test", 1, 0, "Grabber");
QQmlEngine engine;
@@ -1867,24 +1867,24 @@ void tst_qquickwindow::ignoreUnhandledMouseEvents()
item->setParentItem(window->contentItem());
{
- QMouseEvent me(QEvent::MouseButtonPress, QPointF(50, 50), Qt::LeftButton, Qt::LeftButton,
- Qt::NoModifier);
+ QMouseEvent me(QEvent::MouseButtonPress, QPointF(50, 50), window->mapToGlobal(QPointF(50, 50)),
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
me.setAccepted(true);
QVERIFY(QCoreApplication::sendEvent(window, &me));
QVERIFY(!me.isAccepted());
}
{
- QMouseEvent me(QEvent::MouseMove, QPointF(51, 51), Qt::LeftButton, Qt::LeftButton,
- Qt::NoModifier);
+ QMouseEvent me(QEvent::MouseMove, QPointF(51, 51), window->mapToGlobal(QPointF(51, 51)),
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
me.setAccepted(true);
QVERIFY(QCoreApplication::sendEvent(window, &me));
QVERIFY(!me.isAccepted());
}
{
- QMouseEvent me(QEvent::MouseButtonRelease, QPointF(51, 51), Qt::LeftButton, Qt::LeftButton,
- Qt::NoModifier);
+ QMouseEvent me(QEvent::MouseButtonRelease, QPointF(51, 51), window->mapToGlobal(QPointF(51, 51)),
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
me.setAccepted(true);
QVERIFY(QCoreApplication::sendEvent(window, &me));
QVERIFY(!me.isAccepted());
diff --git a/tests/auto/quickcontrols2/CMakeLists.txt b/tests/auto/quickcontrols2/CMakeLists.txt
index 06eecf6714..b3b655f2cd 100644
--- a/tests/auto/quickcontrols2/CMakeLists.txt
+++ b/tests/auto/quickcontrols2/CMakeLists.txt
@@ -1,7 +1,9 @@
# Generated from auto.pro.
add_subdirectory(accessibility)
+if(NOT ANDROID) # temporarily disabled until QTBUG-100991 is fixed
add_subdirectory(controls)
+endif()
add_subdirectory(cursor)
add_subdirectory(customization)
add_subdirectory(designer)
@@ -24,10 +26,14 @@ add_subdirectory(qquickiconlabel)
add_subdirectory(qquickimaginestyle)
add_subdirectory(qquickmaterialstyle)
add_subdirectory(qquickmaterialstyleconf)
+if(NOT ANDROID) # QTBUG-101005
add_subdirectory(qquickmenu)
+endif()
add_subdirectory(qquickmenubar)
add_subdirectory(qquickninepatchimage)
+if(NOT ANDROID) # QTBUG-101005
add_subdirectory(qquickpopup)
+endif()
add_subdirectory(qquickstyle)
add_subdirectory(qquickuniversalstyle)
add_subdirectory(qquickuniversalstyleconf)
diff --git a/tests/auto/quickcontrols2/controls/basic/CMakeLists.txt b/tests/auto/quickcontrols2/controls/basic/CMakeLists.txt
index 844f0eade5..6ae45f1460 100644
--- a/tests/auto/quickcontrols2/controls/basic/CMakeLists.txt
+++ b/tests/auto/quickcontrols2/controls/basic/CMakeLists.txt
@@ -20,9 +20,21 @@ qt_internal_add_test(tst_basic
PUBLIC_LIBRARIES
Qt::Gui
Qt::QuickControls2
+ Qt::QuickTemplates2
TESTDATA ${test_data}
)
+# Make the QML files available to Creator's locator.
+target_sources(tst_basic
+ PRIVATE
+ ${test_data}
+)
+
+set_source_files_properties(${test_data}
+ PROPERTIES
+ HEADER_FILE_ONLY ON
+)
+
#### Keys ignored in scope 1:.:.:basic.pro:<TRUE>:
# OTHER_FILES = "$$PWD/../data/*.qml"
# TEMPLATE = "app"
diff --git a/tests/auto/quickcontrols2/controls/basic/dummy.qml b/tests/auto/quickcontrols2/controls/basic/dummy.qml
deleted file mode 100644
index 6b1bdfec0e..0000000000
--- a/tests/auto/quickcontrols2/controls/basic/dummy.qml
+++ /dev/null
@@ -1,9 +0,0 @@
-import QtQml
-import QtQuick
-import QtQuick.NativeStyle
-import QtQuick.Layouts
-import Qt.labs.settings
-import Qt.labs.qmlmodels
-
-QtObject {
-}
diff --git a/tests/auto/quickcontrols2/controls/basic/dummy_imports.qml b/tests/auto/quickcontrols2/controls/basic/dummy_imports.qml
new file mode 100644
index 0000000000..580db56d12
--- /dev/null
+++ b/tests/auto/quickcontrols2/controls/basic/dummy_imports.qml
@@ -0,0 +1,12 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQml
+import QtQuick
+import QtQuick.NativeStyle
+import QtQuick.Layouts
+import Qt.labs.settings
+import Qt.labs.qmlmodels
+
+QtObject { }
diff --git a/tests/auto/quickcontrols2/controls/data/tst_button.qml b/tests/auto/quickcontrols2/controls/data/tst_button.qml
index a6ec4faad9..f26a050dfc 100644
--- a/tests/auto/quickcontrols2/controls/data/tst_button.qml
+++ b/tests/auto/quickcontrols2/controls/data/tst_button.qml
@@ -272,7 +272,9 @@ TestCase {
// no change
sequenceSpy.expectedSequence = []
- var keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab]
+ // 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) {
sequenceSpy.reset()
keyClick(keys[i])
diff --git a/tests/auto/quickcontrols2/controls/data/tst_checkbox.qml b/tests/auto/quickcontrols2/controls/data/tst_checkbox.qml
index be68ac0d1f..ff6b7ec8b8 100644
--- a/tests/auto/quickcontrols2/controls/data/tst_checkbox.qml
+++ b/tests/auto/quickcontrols2/controls/data/tst_checkbox.qml
@@ -313,7 +313,9 @@ TestCase {
// no change
sequenceSpy.expectedSequence = []
- var keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab]
+ // 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) {
sequenceSpy.reset()
keyClick(keys[i])
diff --git a/tests/auto/quickcontrols2/controls/data/tst_combobox.qml b/tests/auto/quickcontrols2/controls/data/tst_combobox.qml
index 100ec45a40..e8e24652de 100644
--- a/tests/auto/quickcontrols2/controls/data/tst_combobox.qml
+++ b/tests/auto/quickcontrols2/controls/data/tst_combobox.qml
@@ -641,14 +641,15 @@ TestCase {
}
function test_keys_space_enter_escape_data() {
+ // Not testing Key_Enter + Key_Enter and Key_Return + Key_Return because
+ // QGnomeTheme uses Key_Enter and Key_Return for pressing buttons/comboboxes
+ // and the CI uses the QGnomeTheme platform theme.
return [
{ tag: "space-space", key1: Qt.Key_Space, key2: Qt.Key_Space, showPopup: true, showPress: true, hidePopup: true, hidePress: true },
{ tag: "space-enter", key1: Qt.Key_Space, key2: Qt.Key_Enter, showPopup: true, showPress: true, hidePopup: true, hidePress: true },
{ tag: "space-return", key1: Qt.Key_Space, key2: Qt.Key_Return, showPopup: true, showPress: true, hidePopup: true, hidePress: true },
{ tag: "space-escape", key1: Qt.Key_Space, key2: Qt.Key_Escape, showPopup: true, showPress: true, hidePopup: true, hidePress: false },
{ tag: "space-0", key1: Qt.Key_Space, key2: Qt.Key_0, showPopup: true, showPress: true, hidePopup: false, hidePress: false },
- { tag: "enter-enter", key1: Qt.Key_Enter, key2: Qt.Key_Enter, showPopup: false, showPress: false, hidePopup: true, hidePress: false },
- { tag: "return-return", key1: Qt.Key_Return, key2: Qt.Key_Return, showPopup: false, showPress: false, hidePopup: true, hidePress: false },
{ tag: "escape-escape", key1: Qt.Key_Escape, key2: Qt.Key_Escape, showPopup: false, showPress: false, hidePopup: true, hidePress: false }
]
}
diff --git a/tests/auto/quickcontrols2/controls/data/tst_delaybutton.qml b/tests/auto/quickcontrols2/controls/data/tst_delaybutton.qml
index 0e8d188dd2..7350b54320 100644
--- a/tests/auto/quickcontrols2/controls/data/tst_delaybutton.qml
+++ b/tests/auto/quickcontrols2/controls/data/tst_delaybutton.qml
@@ -307,7 +307,9 @@ TestCase {
// no change
sequenceSpy.expectedSequence = []
- var keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab]
+ // 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) {
sequenceSpy.reset()
keyClick(keys[i])
diff --git a/tests/auto/quickcontrols2/controls/data/tst_radiobutton.qml b/tests/auto/quickcontrols2/controls/data/tst_radiobutton.qml
index 973e56a360..d0ff56207d 100644
--- a/tests/auto/quickcontrols2/controls/data/tst_radiobutton.qml
+++ b/tests/auto/quickcontrols2/controls/data/tst_radiobutton.qml
@@ -258,7 +258,9 @@ TestCase {
// no change
sequenceSpy.expectedSequence = []
- var keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab]
+ // 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) {
sequenceSpy.reset()
keyClick(keys[i])
diff --git a/tests/auto/quickcontrols2/controls/data/tst_scrollbar.qml b/tests/auto/quickcontrols2/controls/data/tst_scrollbar.qml
index d49658762c..d453f017e7 100644
--- a/tests/auto/quickcontrols2/controls/data/tst_scrollbar.qml
+++ b/tests/auto/quickcontrols2/controls/data/tst_scrollbar.qml
@@ -964,4 +964,38 @@ TestCase {
compare(vertical.visualPosition, 0.2)
compare(vertical.contentItem.y, vertical.topPadding + 0.2 * vertical.availableHeight)
}
+
+ function test_setting_invalid_property_values() {
+ var control = createTemporaryObject(scrollBar, testCase, {size: 2.0, minimumSize: -1.0})
+ verify(control)
+
+ // check that the values are within the expected range
+ compare(control.size, 1.0)
+ compare(control.minimumSize, 0)
+
+ control.minimumSize = 2.0
+ compare(control.minimumSize, 1.0)
+
+ // test if setting NaN is prevented
+ control.size = NaN
+ control.minimumSize = NaN
+ compare(control.size, 1.0)
+ compare(control.minimumSize, 1.0)
+
+
+ // test if setting float infinity is prevented
+ control.size = Number.POSITIVE_INFINITY
+ control.minimumSize = Number.POSITIVE_INFINITY
+ compare(control.size, 1.0)
+ compare(control.minimumSize, 1.0)
+
+ let oldPosition = control.position;
+ let oldStepSize = control.stepSize;
+
+ control.position = NaN;
+ control.stepSize = NaN;
+
+ compare(oldPosition, control.position)
+ compare(oldStepSize, control.stepSize)
+ }
}
diff --git a/tests/auto/quickcontrols2/controls/data/tst_switch.qml b/tests/auto/quickcontrols2/controls/data/tst_switch.qml
index bf25fcacff..a4e1f813a0 100644
--- a/tests/auto/quickcontrols2/controls/data/tst_switch.qml
+++ b/tests/auto/quickcontrols2/controls/data/tst_switch.qml
@@ -570,7 +570,9 @@ TestCase {
// no change
spy.expectedSequence = []
- var keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab]
+ // 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) {
keyClick(keys[i])
compare(control.checked, false)
diff --git a/tests/auto/quickcontrols2/controls/data/tst_toolbutton.qml b/tests/auto/quickcontrols2/controls/data/tst_toolbutton.qml
index a7acd05ae4..f85a9193e8 100644
--- a/tests/auto/quickcontrols2/controls/data/tst_toolbutton.qml
+++ b/tests/auto/quickcontrols2/controls/data/tst_toolbutton.qml
@@ -169,7 +169,9 @@ TestCase {
compare(clickedSpy.count, 2)
// no change
- var keys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab]
+ // 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) {
keyClick(keys[i])
compare(clickedSpy.count, 2)
diff --git a/tests/auto/quickcontrols2/controls/fusion/CMakeLists.txt b/tests/auto/quickcontrols2/controls/fusion/CMakeLists.txt
index 633e0442de..6381718103 100644
--- a/tests/auto/quickcontrols2/controls/fusion/CMakeLists.txt
+++ b/tests/auto/quickcontrols2/controls/fusion/CMakeLists.txt
@@ -20,9 +20,21 @@ qt_internal_add_test(tst_fusion
PUBLIC_LIBRARIES
Qt::Gui
Qt::QuickControls2
+ Qt::QuickTemplates2
TESTDATA ${test_data}
)
+# Make the QML files available to Creator's locator.
+target_sources(tst_fusion
+ PRIVATE
+ ${test_data}
+)
+
+set_source_files_properties(${test_data}
+ PROPERTIES
+ HEADER_FILE_ONLY ON
+)
+
#### Keys ignored in scope 1:.:.:fusion.pro:<TRUE>:
# OTHER_FILES = "$$PWD/../data/*.qml"
# TEMPLATE = "app"
diff --git a/tests/auto/quickcontrols2/controls/fusion/dummy.qml b/tests/auto/quickcontrols2/controls/fusion/dummy.qml
deleted file mode 100644
index 6b1bdfec0e..0000000000
--- a/tests/auto/quickcontrols2/controls/fusion/dummy.qml
+++ /dev/null
@@ -1,9 +0,0 @@
-import QtQml
-import QtQuick
-import QtQuick.NativeStyle
-import QtQuick.Layouts
-import Qt.labs.settings
-import Qt.labs.qmlmodels
-
-QtObject {
-}
diff --git a/tests/auto/quickcontrols2/controls/fusion/dummy_imports.qml b/tests/auto/quickcontrols2/controls/fusion/dummy_imports.qml
new file mode 100644
index 0000000000..580db56d12
--- /dev/null
+++ b/tests/auto/quickcontrols2/controls/fusion/dummy_imports.qml
@@ -0,0 +1,12 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQml
+import QtQuick
+import QtQuick.NativeStyle
+import QtQuick.Layouts
+import Qt.labs.settings
+import Qt.labs.qmlmodels
+
+QtObject { }
diff --git a/tests/auto/quickcontrols2/controls/imagine/CMakeLists.txt b/tests/auto/quickcontrols2/controls/imagine/CMakeLists.txt
index 9638eb8250..962628e1b6 100644
--- a/tests/auto/quickcontrols2/controls/imagine/CMakeLists.txt
+++ b/tests/auto/quickcontrols2/controls/imagine/CMakeLists.txt
@@ -20,9 +20,21 @@ qt_internal_add_test(tst_imagine
PUBLIC_LIBRARIES
Qt::Gui
Qt::QuickControls2
+ Qt::QuickTemplates2
TESTDATA ${test_data}
)
+# Make the QML files available to Creator's locator.
+target_sources(tst_imagine
+ PRIVATE
+ ${test_data}
+)
+
+set_source_files_properties(${test_data}
+ PROPERTIES
+ HEADER_FILE_ONLY ON
+)
+
#### Keys ignored in scope 1:.:.:imagine.pro:<TRUE>:
# OTHER_FILES = "$$PWD/../data/*.qml"
# TEMPLATE = "app"
diff --git a/tests/auto/quickcontrols2/controls/imagine/dummy.qml b/tests/auto/quickcontrols2/controls/imagine/dummy.qml
deleted file mode 100644
index 6b1bdfec0e..0000000000
--- a/tests/auto/quickcontrols2/controls/imagine/dummy.qml
+++ /dev/null
@@ -1,9 +0,0 @@
-import QtQml
-import QtQuick
-import QtQuick.NativeStyle
-import QtQuick.Layouts
-import Qt.labs.settings
-import Qt.labs.qmlmodels
-
-QtObject {
-}
diff --git a/tests/auto/quickcontrols2/controls/imagine/dummy_imports.qml b/tests/auto/quickcontrols2/controls/imagine/dummy_imports.qml
new file mode 100644
index 0000000000..580db56d12
--- /dev/null
+++ b/tests/auto/quickcontrols2/controls/imagine/dummy_imports.qml
@@ -0,0 +1,12 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQml
+import QtQuick
+import QtQuick.NativeStyle
+import QtQuick.Layouts
+import Qt.labs.settings
+import Qt.labs.qmlmodels
+
+QtObject { }
diff --git a/tests/auto/quickcontrols2/controls/macos/CMakeLists.txt b/tests/auto/quickcontrols2/controls/macos/CMakeLists.txt
index da8c14230e..555a11b4ea 100644
--- a/tests/auto/quickcontrols2/controls/macos/CMakeLists.txt
+++ b/tests/auto/quickcontrols2/controls/macos/CMakeLists.txt
@@ -17,3 +17,13 @@ qt_internal_add_test(tst_macos
TESTDATA ${test_data}
)
+# Make the QML files available to Creator's locator.
+target_sources(tst_macos
+ PRIVATE
+ ${test_data}
+)
+
+set_source_files_properties(${test_data}
+ PROPERTIES
+ HEADER_FILE_ONLY ON
+)
diff --git a/tests/auto/quickcontrols2/controls/material/CMakeLists.txt b/tests/auto/quickcontrols2/controls/material/CMakeLists.txt
index 8cc0cd3fab..b07a63e32d 100644
--- a/tests/auto/quickcontrols2/controls/material/CMakeLists.txt
+++ b/tests/auto/quickcontrols2/controls/material/CMakeLists.txt
@@ -20,9 +20,21 @@ qt_internal_add_test(tst_material
PUBLIC_LIBRARIES
Qt::Gui
Qt::QuickControls2
+ Qt::QuickTemplates2
TESTDATA ${test_data}
)
+# Make the QML files available to Creator's locator.
+target_sources(tst_material
+ PRIVATE
+ ${test_data}
+)
+
+set_source_files_properties(${test_data}
+ PROPERTIES
+ HEADER_FILE_ONLY ON
+)
+
#### Keys ignored in scope 1:.:.:material.pro:<TRUE>:
# OTHER_FILES = "$$PWD/../data/*.qml"
# TEMPLATE = "app"
diff --git a/tests/auto/quickcontrols2/controls/material/dummy.qml b/tests/auto/quickcontrols2/controls/material/dummy.qml
deleted file mode 100644
index 6b1bdfec0e..0000000000
--- a/tests/auto/quickcontrols2/controls/material/dummy.qml
+++ /dev/null
@@ -1,9 +0,0 @@
-import QtQml
-import QtQuick
-import QtQuick.NativeStyle
-import QtQuick.Layouts
-import Qt.labs.settings
-import Qt.labs.qmlmodels
-
-QtObject {
-}
diff --git a/tests/auto/quickcontrols2/controls/material/dummy_imports.qml b/tests/auto/quickcontrols2/controls/material/dummy_imports.qml
new file mode 100644
index 0000000000..580db56d12
--- /dev/null
+++ b/tests/auto/quickcontrols2/controls/material/dummy_imports.qml
@@ -0,0 +1,12 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQml
+import QtQuick
+import QtQuick.NativeStyle
+import QtQuick.Layouts
+import Qt.labs.settings
+import Qt.labs.qmlmodels
+
+QtObject { }
diff --git a/tests/auto/quickcontrols2/controls/universal/CMakeLists.txt b/tests/auto/quickcontrols2/controls/universal/CMakeLists.txt
index 2faa30cc37..0b3478a227 100644
--- a/tests/auto/quickcontrols2/controls/universal/CMakeLists.txt
+++ b/tests/auto/quickcontrols2/controls/universal/CMakeLists.txt
@@ -20,9 +20,21 @@ qt_internal_add_test(tst_universal
PUBLIC_LIBRARIES
Qt::Gui
Qt::QuickControls2
+ Qt::QuickTemplates2
TESTDATA ${test_data}
)
+# Make the QML files available to Creator's locator.
+target_sources(tst_universal
+ PRIVATE
+ ${test_data}
+)
+
+set_source_files_properties(${test_data}
+ PROPERTIES
+ HEADER_FILE_ONLY ON
+)
+
#### Keys ignored in scope 1:.:.:universal.pro:<TRUE>:
# OTHER_FILES = "$$PWD/../data/*.qml"
# TEMPLATE = "app"
diff --git a/tests/auto/quickcontrols2/controls/universal/dummy.qml b/tests/auto/quickcontrols2/controls/universal/dummy.qml
deleted file mode 100644
index 6b1bdfec0e..0000000000
--- a/tests/auto/quickcontrols2/controls/universal/dummy.qml
+++ /dev/null
@@ -1,9 +0,0 @@
-import QtQml
-import QtQuick
-import QtQuick.NativeStyle
-import QtQuick.Layouts
-import Qt.labs.settings
-import Qt.labs.qmlmodels
-
-QtObject {
-}
diff --git a/tests/auto/quickcontrols2/controls/universal/dummy_imports.qml b/tests/auto/quickcontrols2/controls/universal/dummy_imports.qml
new file mode 100644
index 0000000000..580db56d12
--- /dev/null
+++ b/tests/auto/quickcontrols2/controls/universal/dummy_imports.qml
@@ -0,0 +1,12 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQml
+import QtQuick
+import QtQuick.NativeStyle
+import QtQuick.Layouts
+import Qt.labs.settings
+import Qt.labs.qmlmodels
+
+QtObject { }
diff --git a/tests/auto/quickcontrols2/controls/windows/CMakeLists.txt b/tests/auto/quickcontrols2/controls/windows/CMakeLists.txt
index 33755c1bbd..c448c55d25 100644
--- a/tests/auto/quickcontrols2/controls/windows/CMakeLists.txt
+++ b/tests/auto/quickcontrols2/controls/windows/CMakeLists.txt
@@ -16,3 +16,14 @@ qt_internal_add_test(tst_windows
Qt::QuickControls2
TESTDATA ${test_data}
)
+
+# Make the QML files available to Creator's locator.
+target_sources(tst_windows
+ PRIVATE
+ ${test_data}
+)
+
+set_source_files_properties(${test_data}
+ PROPERTIES
+ HEADER_FILE_ONLY ON
+)
diff --git a/tests/auto/quickcontrols2/customization/dummy_imports.qml b/tests/auto/quickcontrols2/customization/dummy_imports.qml
new file mode 100644
index 0000000000..40d9cea712
--- /dev/null
+++ b/tests/auto/quickcontrols2/customization/dummy_imports.qml
@@ -0,0 +1,9 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQuick
+import QtQuick.Window
+import QtQuick.Controls
+
+QtObject { }
diff --git a/tests/auto/quickcontrols2/designer/CMakeLists.txt b/tests/auto/quickcontrols2/designer/CMakeLists.txt
index 50331f8fef..d13b014c93 100644
--- a/tests/auto/quickcontrols2/designer/CMakeLists.txt
+++ b/tests/auto/quickcontrols2/designer/CMakeLists.txt
@@ -11,6 +11,7 @@ qt_internal_add_test(tst_designer
Qt::Gui
Qt::Quick
Qt::QuickControls2
+ Qt::QuickTemplates2
Qt::QuickPrivate
)
diff --git a/tests/auto/quickcontrols2/designer/dummy_imports.qml b/tests/auto/quickcontrols2/designer/dummy_imports.qml
new file mode 100644
index 0000000000..401692e570
--- /dev/null
+++ b/tests/auto/quickcontrols2/designer/dummy_imports.qml
@@ -0,0 +1,8 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQuick
+import QtQuick.Controls
+
+QtObject { }
diff --git a/tests/auto/quickcontrols2/pressandhold/CMakeLists.txt b/tests/auto/quickcontrols2/pressandhold/CMakeLists.txt
index 926d446f82..cf2d92a567 100644
--- a/tests/auto/quickcontrols2/pressandhold/CMakeLists.txt
+++ b/tests/auto/quickcontrols2/pressandhold/CMakeLists.txt
@@ -11,6 +11,7 @@ qt_internal_add_test(tst_pressandhold
Qt::Gui
Qt::Quick
Qt::QuickControls2
+ Qt::QuickTemplates2
)
#### Keys ignored in scope 1:.:.:pressandhold.pro:<TRUE>:
diff --git a/tests/auto/quickcontrols2/pressandhold/tst_pressandhold.cpp b/tests/auto/quickcontrols2/pressandhold/tst_pressandhold.cpp
index 1bf3c6e343..89038201cf 100644
--- a/tests/auto/quickcontrols2/pressandhold/tst_pressandhold.cpp
+++ b/tests/auto/quickcontrols2/pressandhold/tst_pressandhold.cpp
@@ -93,10 +93,14 @@ void tst_PressAndHold::pressAndHold()
QVERIFY(spy.isValid() && waitSpy.isValid());
int startDragDistance = QGuiApplication::styleHints()->startDragDistance();
- QMouseEvent press(QEvent::MouseButtonPress, QPointF(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
- QMouseEvent press2(QEvent::MouseButtonPress, QPointF(), Qt::RightButton, Qt::RightButton, Qt::NoModifier);
- QMouseEvent move(QEvent::MouseMove, QPointF(2 * startDragDistance, 2 * startDragDistance), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
- QMouseEvent release(QEvent::MouseButtonRelease, QPointF(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ QMouseEvent press(QEvent::MouseButtonPress, QPointF(), QPointF(),
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ QMouseEvent press2(QEvent::MouseButtonPress, QPointF(), QPointF(),
+ Qt::RightButton, Qt::RightButton, Qt::NoModifier);
+ QMouseEvent move(QEvent::MouseMove, QPointF(2 * startDragDistance, 2 * startDragDistance), QPointF(),
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ QMouseEvent release(QEvent::MouseButtonRelease, QPointF(), QPointF(),
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
// pressAndHold() emitted
QGuiApplication::sendEvent(control.data(), &press);
@@ -166,9 +170,12 @@ void tst_PressAndHold::keepSelection()
QSignalSpy waitSpy(waitControl.data(), SIGNAL(pressAndHold(QQuickMouseEvent*)));
QVERIFY(spy.isValid() && waitSpy.isValid());
- QMouseEvent press(QEvent::MouseButtonPress, QPointF(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
- QMouseEvent press2(QEvent::MouseButtonPress, QPointF(), Qt::RightButton, Qt::RightButton, Qt::NoModifier);
- QMouseEvent release(QEvent::MouseButtonRelease, QPointF(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ QMouseEvent press(QEvent::MouseButtonPress, QPointF(), QPointF(),
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ QMouseEvent press2(QEvent::MouseButtonPress, QPointF(), QPointF(),
+ Qt::RightButton, Qt::RightButton, Qt::NoModifier);
+ QMouseEvent release(QEvent::MouseButtonRelease, QPointF(), QPointF(),
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QVERIFY(!control->property("text").toString().isEmpty());
QVERIFY(QMetaObject::invokeMethod(control.data(), "selectAll"));
diff --git a/tests/auto/quickcontrols2/qquickcontrol/data/fractionalFontSize.qml b/tests/auto/quickcontrols2/qquickcontrol/data/fractionalFontSize.qml
new file mode 100644
index 0000000000..a4574e460e
--- /dev/null
+++ b/tests/auto/quickcontrols2/qquickcontrol/data/fractionalFontSize.qml
@@ -0,0 +1,18 @@
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias control: ctrl
+
+ Control {
+ id: ctrl
+ contentItem: Text {
+ font.pointSize: 10.5
+ elide: Text.ElideRight
+ text: "This is some sample text"
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols2/qquickcontrol/tst_qquickcontrol.cpp b/tests/auto/quickcontrols2/qquickcontrol/tst_qquickcontrol.cpp
index 94dccf6115..3ee9cc2328 100644
--- a/tests/auto/quickcontrols2/qquickcontrol/tst_qquickcontrol.cpp
+++ b/tests/auto/quickcontrols2/qquickcontrol/tst_qquickcontrol.cpp
@@ -33,6 +33,7 @@
#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtQuickTemplates2/private/qquickbutton_p.h>
#include <QtQuickControlsTestUtils/private/qtest_quickcontrols_p.h>
+#include <QtQuick/private/qquicktext_p_p.h>
using namespace QQuickVisualTestUtils;
@@ -46,6 +47,7 @@ public:
private slots:
void initTestCase() override;
void flickable();
+ void fractionalFontSize();
private:
QScopedPointer<QPointingDevice> touchDevice;
@@ -93,6 +95,24 @@ void tst_QQuickControl::flickable()
QTRY_COMPARE(buttonClickedSpy.count(), 1);
}
+void tst_QQuickControl::fractionalFontSize()
+{
+ QQuickApplicationHelper helper(this, QStringLiteral("fractionalFontSize.qml"));
+ QQuickWindow *window = helper.window;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+ const QQuickControl *control = window->property("control").value<QQuickControl *>();
+ QVERIFY(control);
+ QQuickText *contentItem = qobject_cast<QQuickText *>(control->contentItem());
+ QVERIFY(contentItem);
+
+ QVERIFY(!contentItem->truncated());
+
+ QVERIFY2(qFuzzyCompare(contentItem->contentWidth(),
+ QQuickTextPrivate::get(contentItem)->layout.boundingRect().width()),
+ "The QQuickText::contentWidth() doesn't match the layout's preferred text width");
+}
+
QTEST_QUICKCONTROLS_MAIN(tst_QQuickControl)
#include "tst_qquickcontrol.moc"
diff --git a/tests/auto/quickcontrols2/qquickdrawer/tst_qquickdrawer.cpp b/tests/auto/quickcontrols2/qquickdrawer/tst_qquickdrawer.cpp
index edcd1e7173..da3522d89d 100644
--- a/tests/auto/quickcontrols2/qquickdrawer/tst_qquickdrawer.cpp
+++ b/tests/auto/quickcontrols2/qquickdrawer/tst_qquickdrawer.cpp
@@ -34,6 +34,7 @@
#include <QtGui/qstylehints.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qpa/qwindowsysteminterface.h>
+#include <QtQml/QQmlComponent>
#include <QtQuick/private/qquickwindow_p.h>
#include <QtQuick/private/qquickflickable_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
diff --git a/tests/auto/quickcontrols2/qquickheaderview/tst_qquickheaderview.cpp b/tests/auto/quickcontrols2/qquickheaderview/tst_qquickheaderview.cpp
index 5f8ad65248..2dcb6a4a18 100644
--- a/tests/auto/quickcontrols2/qquickheaderview/tst_qquickheaderview.cpp
+++ b/tests/auto/quickcontrols2/qquickheaderview/tst_qquickheaderview.cpp
@@ -31,6 +31,7 @@
#include <QAbstractItemModelTester>
#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlComponent>
#include <QtQuick/private/qquickwindow_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
diff --git a/tests/auto/quickcontrols2/qquickiconimage/BLACKLIST b/tests/auto/quickcontrols2/qquickiconimage/BLACKLIST
new file mode 100644
index 0000000000..70c935375d
--- /dev/null
+++ b/tests/auto/quickcontrols2/qquickiconimage/BLACKLIST
@@ -0,0 +1,15 @@
+# QTBUG-101006
+[nameBindingSourceSize]
+android
+[sourceBindingSourceSize]
+android
+[alignment]
+android
+[color]
+android
+[fileSelectors]
+android
+[imageProvider]
+android
+[translucentColors]
+android
diff --git a/tests/auto/quickcontrols2/qquickiconimage/tst_qquickiconimage.cpp b/tests/auto/quickcontrols2/qquickiconimage/tst_qquickiconimage.cpp
index c35f8420f7..8c5c8780c9 100644
--- a/tests/auto/quickcontrols2/qquickiconimage/tst_qquickiconimage.cpp
+++ b/tests/auto/quickcontrols2/qquickiconimage/tst_qquickiconimage.cpp
@@ -410,9 +410,6 @@ void tst_qquickiconimage::color()
{
SKIP_IF_DPR_TOO_HIGH();
- if (QGuiApplication::platformName() == QLatin1String("offscreen"))
- QSKIP("grabToImage() doesn't work on the \"offscreen\" platform plugin (QTBUG-63185)");
-
QQuickView view(testFileUrl("color.qml"));
QCOMPARE(view.status(), QQuickView::Ready);
view.show();
@@ -468,9 +465,6 @@ void tst_qquickiconimage::fileSelectors()
{
SKIP_IF_DPR_TOO_HIGH();
- if (QGuiApplication::platformName() == QLatin1String("offscreen"))
- QSKIP("grabToImage() doesn't work on the \"offscreen\" platform plugin (QTBUG-63185)");
-
QQuickView view;
QScopedPointer<QQmlFileSelector> fileSelector(new QQmlFileSelector(view.engine()));
fileSelector->setExtraSelectors(QStringList() << "testselector");
@@ -513,9 +507,6 @@ public:
// don't crash (QTBUG-63959)
void tst_qquickiconimage::imageProvider()
{
- if (QGuiApplication::platformName() == QLatin1String("offscreen"))
- QSKIP("grabToImage() doesn't work on the \"offscreen\" platform plugin (QTBUG-63185)");
-
QQuickView view;
view.engine()->addImageProvider("provider", new TestImageProvider);
view.setSource(testFileUrl("imageProvider.qml"));
@@ -545,9 +536,6 @@ void tst_qquickiconimage::imageProvider()
*/
void tst_qquickiconimage::translucentColors()
{
- if (QGuiApplication::platformName() == QLatin1String("offscreen"))
- QSKIP("grabToImage() doesn't work on the \"offscreen\" platform plugin (QTBUG-63185)");
-
// Doesn't reproduce with QQuickView.
QQmlApplicationEngine engine;
engine.load(testFileUrl("translucentColors.qml"));
diff --git a/tests/auto/quickcontrols2/qquickiconlabel/data/iconSourceContext.qml b/tests/auto/quickcontrols2/qquickiconlabel/data/iconSourceContext.qml
index 0d562d1500..8cf09666d0 100644
--- a/tests/auto/quickcontrols2/qquickiconlabel/data/iconSourceContext.qml
+++ b/tests/auto/quickcontrols2/qquickiconlabel/data/iconSourceContext.qml
@@ -1,7 +1,18 @@
-import QtQuick.Controls
import QtQuick
+import QtQuick.Controls.Basic
+import QtQuick.Controls.impl
+import "sub" as Sub
Item {
Image { source: "a.png" }
IconLabel { icon.source: "a.png" }
+ Button {
+ icon.color: "transparent"
+ icon.source: "a.png"
+ }
+ Button {
+ action: actions.action
+ icon.color: "transparent"
+ Sub.Actions { id: actions }
+ }
}
diff --git a/tests/auto/quickcontrols2/qquickiconlabel/data/sub/Actions.qml b/tests/auto/quickcontrols2/qquickiconlabel/data/sub/Actions.qml
new file mode 100644
index 0000000000..20bd6a5e6b
--- /dev/null
+++ b/tests/auto/quickcontrols2/qquickiconlabel/data/sub/Actions.qml
@@ -0,0 +1,6 @@
+import QtQuick
+import QtQuick.Controls.Basic
+
+QtObject {
+ readonly property Action action: Action { icon.source: "../a.png" }
+}
diff --git a/tests/auto/quickcontrols2/qquickiconlabel/tst_qquickiconlabel.cpp b/tests/auto/quickcontrols2/qquickiconlabel/tst_qquickiconlabel.cpp
index 2ee0bf4c9f..21018d742f 100644
--- a/tests/auto/quickcontrols2/qquickiconlabel/tst_qquickiconlabel.cpp
+++ b/tests/auto/quickcontrols2/qquickiconlabel/tst_qquickiconlabel.cpp
@@ -30,6 +30,7 @@
#include <qtest.h>
+#include <QtQml/QQmlComponent>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitemgrabresult.h>
@@ -37,6 +38,7 @@
#include <QtQuick/private/qquickimage_p_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
+#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
#include <QtQuickTemplates2/private/qquickicon_p.h>
#include <QtQuickControls2Impl/private/qquickiconimage_p.h>
#include <QtQuickControls2Impl/private/qquickiconlabel_p.h>
@@ -303,9 +305,6 @@ void tst_qquickiconlabel::emptyIconSource()
void tst_qquickiconlabel::colorChanges()
{
- if (QGuiApplication::platformName() == QLatin1String("offscreen"))
- QSKIP("grabToImage() doesn't work on the \"offscreen\" platform plugin (QTBUG-63185)");
-
QQuickView view(testFileUrl("colorChanges.qml"));
QCOMPARE(view.status(), QQuickView::Ready);
view.show();
@@ -345,7 +344,13 @@ void tst_qquickiconlabel::iconSourceContext()
for (QQuickItem *child : root->childItems()) {
QQuickImage *image = qobject_cast<QQuickImage *>(child);
if (!image) {
- if (QQuickIconLabel *label = qobject_cast<QQuickIconLabel *>(child)) {
+ QQuickIconLabel *label = nullptr;
+ if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(child)) {
+ label = qobject_cast<QQuickIconLabel *>(button->contentItem());
+ } else {
+ label = qobject_cast<QQuickIconLabel *>(child);
+ }
+ if (label) {
QQuickIconLabelPrivate *labelPrivate = static_cast<QQuickIconLabelPrivate *>(
QQuickItemPrivate::get(label));
image = labelPrivate->image;
diff --git a/tests/auto/quickcontrols2/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp b/tests/auto/quickcontrols2/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp
index 021628709c..0478c97431 100644
--- a/tests/auto/quickcontrols2/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp
+++ b/tests/auto/quickcontrols2/qquicktreeviewdelegate/tst_qquicktreeviewdelegate.cpp
@@ -89,6 +89,8 @@ private slots:
void showTreeView();
void expandAndCollapsUsingDoubleClick();
void expandAndCollapseClickOnIndicator();
+ void expandAndCollapsUsingNonSupportedButtonAndModifers_data();
+ void expandAndCollapsUsingNonSupportedButtonAndModifers();
void checkPropertiesRoot();
void checkPropertiesChildren();
};
@@ -163,6 +165,57 @@ void tst_qquicktreeviewdelegate::expandAndCollapseClickOnIndicator()
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
}
+void tst_qquicktreeviewdelegate::expandAndCollapsUsingNonSupportedButtonAndModifers_data()
+{
+ QTest::addColumn<Qt::MouseButton>("button");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+
+ QTest::newRow("left + Qt::ControlModifier") << Qt::LeftButton << Qt::KeyboardModifiers(Qt::ControlModifier);
+ QTest::newRow("left + Qt::ShiftModifier") << Qt::LeftButton << Qt::KeyboardModifiers(Qt::ShiftModifier);
+ QTest::newRow("left + Qt::AltModifier") << Qt::LeftButton << Qt::KeyboardModifiers(Qt::AltModifier);
+ QTest::newRow("left + Qt::MetaModifier") << Qt::LeftButton << Qt::KeyboardModifiers(Qt::MetaModifier);
+ QTest::newRow("left + Qt::ControlModifier + Qt::ShiftModifier") << Qt::LeftButton << (Qt::ShiftModifier | Qt::ControlModifier);
+
+ QTest::newRow("right + Qt::NoModifier") << Qt::RightButton << Qt::KeyboardModifiers(Qt::ControlModifier);
+ QTest::newRow("right + Qt::ControlModifier") << Qt::RightButton << Qt::KeyboardModifiers(Qt::ShiftModifier);
+}
+
+void tst_qquicktreeviewdelegate::expandAndCollapsUsingNonSupportedButtonAndModifers()
+{
+ QFETCH(Qt::MouseButton, button);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ // Ensure that we don't expand or collapse the tree if the user is using the right mouse
+ // button, or holding down modifier keys. This "space" is reserved for application specific actions.
+ LOAD_TREEVIEW("unmodified.qml");
+
+ QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
+ const auto item = treeView->itemAtCell(0, 0);
+ QVERIFY(item);
+ const QPoint localPos = QPoint(item->width() / 2, item->height() / 2);
+ const QPoint pos = item->window()->contentItem()->mapFromItem(item, localPos).toPoint();
+ QTest::mouseDClick(item->window(), button, modifiers, pos);
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
+
+ // Expand first row, and ensure we don't collapse it again
+ // if doing a double click together with Qt::CTRL.
+ QTest::mouseDClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos);
+
+ WAIT_UNTIL_POLISHED;
+
+ // We now expect 5 rows, the root pluss it's 4 children
+ QCOMPARE(treeViewPrivate->loadedRows.count(), 5);
+
+ QTest::mouseDClick(item->window(), button, modifiers, pos);
+
+ WAIT_UNTIL_POLISHED;
+
+ // We still expect 5 rows, the root pluss it's 4 children
+ QCOMPARE(treeViewPrivate->loadedRows.count(), 5);
+}
+
void tst_qquicktreeviewdelegate::checkPropertiesRoot()
{
LOAD_TREEVIEW("unmodified.qml");
diff --git a/tests/auto/quickcontrols2/revisions/CMakeLists.txt b/tests/auto/quickcontrols2/revisions/CMakeLists.txt
index 79a0f8e310..801dd6d66d 100644
--- a/tests/auto/quickcontrols2/revisions/CMakeLists.txt
+++ b/tests/auto/quickcontrols2/revisions/CMakeLists.txt
@@ -11,6 +11,7 @@ qt_internal_add_test(tst_revisions
Qt::Gui
Qt::Qml
Qt::QuickControls2
+ Qt::QuickTemplates2
)
## Scopes:
diff --git a/tests/auto/quickcontrols2/snippets/CMakeLists.txt b/tests/auto/quickcontrols2/snippets/CMakeLists.txt
index 1d8ac11673..ce76c4fbc5 100644
--- a/tests/auto/quickcontrols2/snippets/CMakeLists.txt
+++ b/tests/auto/quickcontrols2/snippets/CMakeLists.txt
@@ -20,6 +20,7 @@ qt_internal_add_test(tst_snippets
Qt::Quick
Qt::QuickControls2
Qt::QuickControls2Private
+ Qt::QuickTemplates2
TESTDATA ${test_data}
)
diff --git a/tests/auto/quickcontrols2/styleimportscompiletimeqmlonly/dummy_imports.qml b/tests/auto/quickcontrols2/styleimportscompiletimeqmlonly/dummy_imports.qml
new file mode 100644
index 0000000000..aa37fd14b0
--- /dev/null
+++ b/tests/auto/quickcontrols2/styleimportscompiletimeqmlonly/dummy_imports.qml
@@ -0,0 +1,8 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQuick
+import QtQuick.Controls.Basic
+
+QtObject { }
diff --git a/tests/auto/quickdialogs/CMakeLists.txt b/tests/auto/quickdialogs/CMakeLists.txt
index a3b5f15cb3..a8541bb3d5 100644
--- a/tests/auto/quickdialogs/CMakeLists.txt
+++ b/tests/auto/quickdialogs/CMakeLists.txt
@@ -1,4 +1,6 @@
+if(NOT ANDROID) # temporarily disabled until QTBUG-100991 is fixed
add_subdirectory(qquickfiledialogimpl)
add_subdirectory(qquickfolderdialogimpl)
add_subdirectory(qquickfontdialogimpl)
+endif()
add_subdirectory(qquickmessagedialogimpl)
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/BLACKLIST b/tests/auto/quickdialogs/qquickfiledialogimpl/BLACKLIST
index 822b92dd19..1145255781 100644
--- a/tests/auto/quickdialogs/qquickfiledialogimpl/BLACKLIST
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/BLACKLIST
@@ -5,3 +5,6 @@
# QTBUG-92585
[fileMode:OpenFiles]
*
+#QTBUG-101488
+[goUp]
+qnx
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/CMakeLists.txt b/tests/auto/quickdialogs/qquickfiledialogimpl/CMakeLists.txt
index 64022f6293..096ebaacb1 100644
--- a/tests/auto/quickdialogs/qquickfiledialogimpl/CMakeLists.txt
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/CMakeLists.txt
@@ -21,6 +21,7 @@ qt_internal_add_test(tst_qquickfiledialogimpl
Qt::QuickDialogs2QuickImplPrivate
Qt::QuickDialogs2UtilsPrivate
Qt::QuickPrivate
+ Qt::QuickTemplates2
Qt::QuickTemplates2Private
Qt::QuickTest
Qt::QuickTestUtilsPrivate
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/dummy_imports.qml b/tests/auto/quickdialogs/qquickfiledialogimpl/dummy_imports.qml
new file mode 100644
index 0000000000..4ea33de671
--- /dev/null
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/dummy_imports.qml
@@ -0,0 +1,9 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQuick.Controls
+import QtQuick.Layouts
+import Qt.labs.folderlistmodel
+
+QtObject { }
diff --git a/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp b/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp
index e70c7e7171..a9fa0f21cc 100644
--- a/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp
+++ b/tests/auto/quickdialogs/qquickfiledialogimpl/tst_qquickfiledialogimpl.cpp
@@ -123,6 +123,7 @@ void tst_QQuickFileDialogImpl::initTestCase()
QQmlDataTest::initTestCase();
qputenv("QT_QUICK_DIALOGS_SHOW_DIRS_FIRST", "1");
+ qputenv("QT_QUICK_DIALOGS_PRESELECT_FIRST_FILE", "1");
QVERIFY(tempDir.isValid());
// QTEST_QUICKCONTROLS_MAIN constructs the test case object once,
diff --git a/tests/auto/quickdialogs/qquickfolderdialogimpl/dummy_imports.qml b/tests/auto/quickdialogs/qquickfolderdialogimpl/dummy_imports.qml
new file mode 100644
index 0000000000..7faa9b98e0
--- /dev/null
+++ b/tests/auto/quickdialogs/qquickfolderdialogimpl/dummy_imports.qml
@@ -0,0 +1,10 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import Qt.labs.folderlistmodel
+
+QtObject { }
diff --git a/tests/auto/quickdialogs/qquickfontdialogimpl/dummy_imports.qml b/tests/auto/quickdialogs/qquickfontdialogimpl/dummy_imports.qml
new file mode 100644
index 0000000000..5b8af918ea
--- /dev/null
+++ b/tests/auto/quickdialogs/qquickfontdialogimpl/dummy_imports.qml
@@ -0,0 +1,8 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQuick
+import QtQuick.Layouts
+
+QtObject { }
diff --git a/tests/auto/quickdialogs/qquickmessagedialogimpl/dummy_imports.qml b/tests/auto/quickdialogs/qquickmessagedialogimpl/dummy_imports.qml
new file mode 100644
index 0000000000..5b8af918ea
--- /dev/null
+++ b/tests/auto/quickdialogs/qquickmessagedialogimpl/dummy_imports.qml
@@ -0,0 +1,8 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQuick
+import QtQuick.Layouts
+
+QtObject { }
diff --git a/tests/auto/quicktest/quicktestmainwithsetup/CMakeLists.txt b/tests/auto/quicktest/quicktestmainwithsetup/CMakeLists.txt
index c8900b38de..bca7d7fb00 100644
--- a/tests/auto/quicktest/quicktestmainwithsetup/CMakeLists.txt
+++ b/tests/auto/quicktest/quicktestmainwithsetup/CMakeLists.txt
@@ -10,6 +10,11 @@ file(GLOB_RECURSE test_data_glob
${CMAKE_CURRENT_SOURCE_DIR}/data/*.qml)
list(APPEND test_data ${test_data_glob})
+file(GLOB_RECURSE test_imports_glob
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/imports/*)
+list(APPEND test_data ${test_imports_glob})
+
qt_internal_add_test(tst_quicktestmainwithsetup
QMLTEST
SOURCES